X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Frealpath.c;h=89f77378d432b05c4bcfe01906ffcd5987847b50;hp=bfe8e6762336f2c7d07c322a38fe9e88ad90cee8;hb=e44cf42f362d793c47d892a18a6853d88abd6ecb;hpb=9add3c10a3b769e309f476bd0fd05e2a7126d31d diff --git a/daemon/realpath.c b/daemon/realpath.c index bfe8e67..89f7737 100644 --- a/daemon/realpath.c +++ b/daemon/realpath.c @@ -22,29 +22,48 @@ #include #include #include +#include #include #include #include -#include "ignore-value.h" - #include "daemon.h" +#include "optgroups.h" #include "actions.h" +/* On Windows, NAME_MAX is not defined. */ +#ifndef NAME_MAX +#define NAME_MAX FILENAME_MAX +#endif + +int +optgroup_realpath_available (void) +{ +#ifdef HAVE_REALPATH + return 1; +#else + return 0; +#endif +} + char * do_realpath (const char *path) { +#ifdef HAVE_REALPATH char *ret; CHROOT_IN; ret = realpath (path, NULL); CHROOT_OUT; if (ret == NULL) { - reply_with_perror ("realpath"); + reply_with_perror ("%s", path); return NULL; } return ret; /* caller frees */ +#else + NOT_AVAILABLE (NULL); +#endif } char * @@ -52,9 +71,13 @@ do_case_sensitive_path (const char *path) { char ret[PATH_MAX+1] = "/"; size_t next = 1; + int fd_cwd; - /* MUST chdir ("/") before leaving this function. */ - if (chdir (sysroot) == -1) { + /* 'fd_cwd' here is a surrogate for the current working directory, so + * that we don't have to actually call chdir(2). + */ + fd_cwd = open (sysroot, O_RDONLY | O_DIRECTORY); + if (fd_cwd == -1) { reply_with_perror ("%s", sysroot); return NULL; } @@ -75,11 +98,11 @@ do_case_sensitive_path (const char *path) if ((i == 1 && path[0] == '.') || (i == 2 && path[0] == '.' && path[1] == '.')) { - reply_with_error ("case_sensitive_path: path contained . or .. elements"); + reply_with_error ("path contained . or .. elements"); goto error; } if (i > NAME_MAX) { - reply_with_error ("case_sensitive_path: path element too long"); + reply_with_error ("path element too long"); goto error; } @@ -93,7 +116,12 @@ do_case_sensitive_path (const char *path) /* Read the current directory looking (case insensitively) for * this element of the path. */ - DIR *dir = opendir ("."); + int fd2 = dup (fd_cwd); /* because closedir will close it */ + if (fd2 == -1) { + reply_with_perror ("dup"); + goto error; + } + DIR *dir = fdopendir (fd2); if (dir == NULL) { reply_with_perror ("opendir"); goto error; @@ -103,7 +131,7 @@ do_case_sensitive_path (const char *path) errno = 0; while ((d = readdir (dir)) != NULL) { - if (strcasecmp (d->d_name, name) == 0) + if (STRCASEEQ (d->d_name, name)) break; } @@ -136,10 +164,15 @@ do_case_sensitive_path (const char *path) next += i; /* Is it a directory? Try going into it. */ - if (chdir (d->d_name) == -1) { + fd2 = openat (fd_cwd, d->d_name, O_RDONLY | O_DIRECTORY); + int err = errno; + close (fd_cwd); + fd_cwd = fd2; + errno = err; + if (fd_cwd == -1) { /* ENOTDIR is OK provided we've reached the end of the path. */ if (errno != ENOTDIR) { - reply_with_perror ("chdir: %s", d->d_name); + reply_with_perror ("openat: %s", d->d_name); goto error; } @@ -150,7 +183,7 @@ do_case_sensitive_path (const char *path) } } - ignore_value (chdir ("/")); + close (fd_cwd); ret[next] = '\0'; char *retp = strdup (ret); @@ -161,6 +194,6 @@ do_case_sensitive_path (const char *path) return retp; /* caller frees */ error: - ignore_value (chdir ("/")); + close (fd_cwd); return NULL; }