]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_io: Allow -P and -L to be given to open for O_PATH and O_NOFOLLOW
authorDavid Howells <dhowells@redhat.com>
Thu, 24 May 2018 19:48:41 +0000 (14:48 -0500)
committerEric Sandeen <sandeen@redhat.com>
Thu, 24 May 2018 19:48:41 +0000 (14:48 -0500)
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 <dhowells@redhat.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
io/file.c
io/init.c
io/io.h
io/open.c
man/man8/xfs_io.8

index 349b19cdc4200c9ece5ac206377977e4452d503f..b7edf6ef841feb0cc3d5385459982fe50dc08c5d 100644 (file)
--- 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
index 612962e8b59744c31188b5a5694d6bf9f42d1581..3f637e5a29e8b3aac204af7c4d1927efd078a34b 100644 (file)
--- 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 7f8197caef04eedf49c5398e8d2c17386707c9f8..fa0cdff7ddd1744c2b7d607cc17d30dbf1e11a2b 100644 (file)
--- 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
index 2cce0455263a1da26cc1eaea762c68b67fa0735c..4a92b423e9e0ffabd038b56586a795e485706a1c 100644 (file)
--- a/io/open.c
+++ b/io/open.c
 #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;
 
index 82ea8c1a2b3fae2f4daf9ee6e8896bb3fe185309..d9fede248fdb7bf48a987e9c7e70b83781eb03c2 100644 (file)
@@ -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