From: Bill Kendall Date: Wed, 6 Jan 2010 17:38:41 +0000 (+0100) Subject: libhandle: always use a good path for by-handle ioctls X-Git-Tag: v3.1.0~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a8de1cf93a56007458baeafadf8611c550572023;p=thirdparty%2Fxfsprogs-dev.git libhandle: always use a good path for by-handle ioctls We can't open symbolic links to perform the by-handle XFS ioctls, and while we can open special files they won't end up calling into the XFS ioctl method. So before calling into the handle ioctls generate a fspath that always points to a regular file or directory that we can call the ioctl on. Signed-off-by: Bill Kendall Signed-off-by: Christoph Hellwig --- diff --git a/libhandle/handle.c b/libhandle/handle.c index 627679748..c3a61299c 100644 --- a/libhandle/handle.c +++ b/libhandle/handle.c @@ -16,6 +16,7 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -40,6 +41,7 @@ typedef union { static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*); static int handle_to_fsfd(void *, char **); +static char *path_to_fspath(char *path); /* @@ -70,13 +72,18 @@ path_to_fshandle( comarg_t obj; struct fdhash *fdhp; char *tmppath; + char *fspath; - fd = open(path, O_RDONLY); + fspath = path_to_fspath(path); + if (fspath == NULL) + return -1; + + fd = open(fspath, O_RDONLY); if (fd < 0) return -1; obj.path = path; - result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_FSHANDLE, + result = obj_to_handle(fspath, fd, XFS_IOC_PATH_TO_FSHANDLE, obj, fshanp, fshlen); if (result < 0) { close(fd); @@ -95,7 +102,7 @@ path_to_fshandle( } fdhp->fsfd = fd; - strncpy(fdhp->fspath, path, sizeof(fdhp->fspath)); + strncpy(fdhp->fspath, fspath, sizeof(fdhp->fspath)); memcpy(fdhp->fsh, *fshanp, FSIDSIZE); fdhp->fnxt = fdhash_head; @@ -114,18 +121,46 @@ path_to_handle( int fd; int result; comarg_t obj; + char *fspath; - fd = open(path, O_RDONLY); + fspath = path_to_fspath(path); + if (fspath == NULL) + return -1; + + fd = open(fspath, O_RDONLY); if (fd < 0) return -1; obj.path = path; - result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_HANDLE, + result = obj_to_handle(fspath, fd, XFS_IOC_PATH_TO_HANDLE, obj, hanp, hlen); close(fd); return result; } +/* Given a path, return a suitable "fspath" for use in obtaining + * an fd for xfsctl calls. For regular files and directories the + * input path is sufficient. For other types the parent directory + * is used to avoid issues with opening dangling symlinks and + * potentially blocking in an open on a named pipe. Also + * symlinks to files on other filesystems would be a problem, + * since an fd would be obtained for the wrong fs. + */ +static char * +path_to_fspath(char *path) +{ + static char dirpath[MAXPATHLEN]; + struct stat statbuf; + + if (lstat(path, &statbuf) != 0) + return NULL; + + if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) + return path; + + strcpy(dirpath, path); + return dirname(dirpath); +} int fd_to_handle (