From: David Howells Date: Thu, 24 May 2018 19:48:41 +0000 (-0500) Subject: xfs_io: Allow -P and -L to be given to open for O_PATH and O_NOFOLLOW X-Git-Tag: v4.17.0-rc1~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fc52865c480556966b1c869c4f32338c8a60be5f;p=thirdparty%2Fxfsprogs-dev.git xfs_io: Allow -P and -L to be given to open for O_PATH and O_NOFOLLOW Allow "open -P" to specify O_PATH so that paths which would otherwise be unopenable might be opened for stat()'ing. Such things include files that would incur an access error or device files for which no corresponding driver is available. Allow "-L" to be given in conjunction with O_PATH to specify O_NOFOLLOW also. We also have to avoid calling xfsctl() if O_PATH is given as ioctls are forbidden on such fds. This means we cannot retrieve the geometry information on an XFS filesystem, so the record gets cleared instead. For the moment, only the xfsctl() calls in the 'open' command are conditionalised. Signed-off-by: David Howells Signed-off-by: Jeff Layton Reviewed-by: Eric Sandeen Signed-off-by: Eric Sandeen --- diff --git a/io/file.c b/io/file.c index 349b19cdc..b7edf6ef8 100644 --- a/io/file.c +++ b/io/file.c @@ -35,7 +35,7 @@ print_fileio( int index, int braces) { - printf(_("%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s)\n"), + printf(_("%c%03d%c %-14s (%s,%s,%s,%s%s%s%s%s%s%s)\n"), braces? '[' : ' ', index, braces? ']' : ' ', file->name, file->flags & IO_FOREIGN ? _("foreign") : _("xfs"), file->flags & IO_OSYNC ? _("sync") : _("non-sync"), @@ -44,7 +44,9 @@ print_fileio( file->flags & IO_REALTIME ? _(",real-time") : "", file->flags & IO_APPEND ? _(",append-only") : "", file->flags & IO_NONBLOCK ? _(",non-block") : "", - file->flags & IO_TMPFILE ? _(",tmpfile") : ""); + file->flags & IO_TMPFILE ? _(",tmpfile") : "", + file->flags & IO_PATH ? _(",path") : "", + file->flags & IO_NOFOLLOW ? _(",nofollow") : ""); } int diff --git a/io/init.c b/io/init.c index 612962e8b..3f637e5a2 100644 --- a/io/init.c +++ b/io/init.c @@ -155,7 +155,7 @@ init( gettimeofday(&stopwatch, NULL); fs_table_initialise(0, NULL, 0, NULL); - while ((c = getopt(argc, argv, "ac:C:dFfim:p:nrRstTVx")) != EOF) { + while ((c = getopt(argc, argv, "ac:C:dFfiLm:p:PnrRstTVx")) != EOF) { switch (c) { case 'a': flags |= IO_APPEND; @@ -201,6 +201,12 @@ init( case 't': flags |= IO_TRUNC; break; + case 'P': + flags |= IO_PATH; + break; + case 'L': + flags |= IO_NOFOLLOW; + break; case 'R': flags |= IO_REALTIME; break; diff --git a/io/io.h b/io/io.h index 7f8197cae..fa0cdff7d 100644 --- a/io/io.h +++ b/io/io.h @@ -40,6 +40,8 @@ #define IO_FOREIGN (1<<7) #define IO_NONBLOCK (1<<8) #define IO_TMPFILE (1<<9) +#define IO_PATH (1<<10) +#define IO_NOFOLLOW (1<<11) /* * Regular file I/O control diff --git a/io/open.c b/io/open.c index 2cce04552..4a92b423e 100644 --- a/io/open.c +++ b/io/open.c @@ -38,6 +38,18 @@ #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) #endif +#ifndef O_PATH +#if defined __alpha__ +#define O_PATH 040000000 +#elif defined(__hppa__) +#define O_PATH 020000000 +#elif defined(__sparc__) +#define O_PATH 0x1000000 +#else +#define O_PATH 010000000 +#endif +#endif /* O_PATH */ + static cmdinfo_t open_cmd; static cmdinfo_t close_cmd; static cmdinfo_t chproj_cmd; @@ -74,6 +86,10 @@ openfile( oflags |= O_NONBLOCK; if (flags & IO_TMPFILE) oflags |= O_TMPFILE; + if (flags & IO_PATH) + oflags |= O_PATH; + if (flags & IO_NOFOLLOW) + oflags |= O_NOFOLLOW; fd = open(path, oflags, mode); if (fd < 0) { @@ -97,13 +113,16 @@ openfile( if (!geom || !platform_test_xfs_fd(fd)) return fd; - if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) { + if (flags & IO_PATH) { + /* Can't call ioctl() on O_PATH fds */ + memset(geom, 0, sizeof(*geom)); + } else if (xfsctl(path, fd, XFS_IOC_FSGEOMETRY, geom) < 0) { perror("XFS_IOC_FSGEOMETRY"); close(fd); return -1; } - if (!(flags & IO_READONLY) && (flags & IO_REALTIME)) { + if (!(flags & (IO_READONLY | IO_PATH)) && (flags & IO_REALTIME)) { struct fsxattr attr; if (xfsctl(path, fd, FS_IOC_FSGETXATTR, &attr) < 0) { @@ -191,6 +210,8 @@ open_help(void) " -t -- open with O_TRUNC (truncate the file to zero length if it exists)\n" " -R -- mark the file as a realtime XFS file immediately after opening it\n" " -T -- open with O_TMPFILE (create a file not visible in the namespace)\n" +" -P -- open with O_PATH (create an fd that is merely a location reference)\n" +" -L -- open with O_NOFOLLOW (don't follow symlink)\n" " Note1: usually read/write direct IO requests must be blocksize aligned;\n" " some kernels, however, allow sectorsize alignment for direct IO.\n" " Note2: the bmap for non-regular files can be obtained provided the file\n" @@ -216,7 +237,7 @@ open_f( return 0; } - while ((c = getopt(argc, argv, "FRTacdfm:nrstx")) != EOF) { + while ((c = getopt(argc, argv, "FLPRTacdfm:nrstx")) != EOF) { switch (c) { case 'F': /* Ignored / deprecated now, handled automatically */ @@ -257,6 +278,12 @@ open_f( case 'T': flags |= IO_TMPFILE; break; + case 'P': + flags |= IO_PATH; + break; + case 'L': + flags |= IO_NOFOLLOW; + break; default: return command_usage(&open_cmd); } @@ -270,6 +297,12 @@ open_f( return -1; } + if ((flags & (IO_PATH|IO_NOFOLLOW)) && + (flags & ~(IO_PATH|IO_NOFOLLOW))) { + fprintf(stderr, _("-P and -L are incompatible with the other options\n")); + return -1; + } + fd = openfile(argv[optind], &geometry, flags, mode, &fsp); if (fd < 0) return 0; @@ -785,7 +818,7 @@ open_init(void) open_cmd.argmax = -1; open_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK | CMD_FLAG_ONESHOT; - open_cmd.args = _("[-acdrstxT] [-m mode] [path]"); + open_cmd.args = _("[-acdrstxRTPL] [-m mode] [path]"); open_cmd.oneline = _("open the file specified by path"); open_cmd.help = open_help; diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index 82ea8c1a2..d9fede248 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -122,7 +122,7 @@ command for more details on any command. Display a list of all open files and (optionally) switch to an alternate current open file. .TP -.BI "open [[ \-acdfrstRT ] " path " ]" +.BI "open [[ \-acdfrstRTPL ] " path " ]" Closes the current file, and opens the file specified by .I path instead. Without any arguments, displays statistics about the current @@ -164,6 +164,16 @@ option. .B \-R marks the file as a realtime XFS file after opening it, if it is not already marked as such. +.TP +.B \-P +opens the path as a referent only (O_PATH). This is incompatible with other +flags specifying other O_xxx flags apart from +.BR \-L . +.TP +.B \-L +doesn't follow symlinks (O_NOFOLLOW). This is incompatible with other +flags specifying other O_xxx flags apart from +.BR \-P . .PD .RE .TP