]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lsfd: use constants defined in asm/fctl.h flags field of a fdinfo
authorMasatake YAMATO <yamato@redhat.com>
Wed, 8 Jun 2022 15:32:19 +0000 (00:32 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Thu, 9 Jun 2022 18:21:20 +0000 (03:21 +0900)
Close #1709.

The original code decoded the field using constants defined in
/usr/include/fcntl.h. The constants defined in /usr/include/fcntl.h
was suitable for passing to the kernel as a part of arguments of
system calls like open(2). However, they were not suitable for
decoding the field.

Let's think about decoding 0300000 in

    $ cat /proc/157067/fdinfo/3
    pos: 0
    flags: 0300000
    $ lsfd -p 157067 -o+flags -Q -Q 'ASSOC == "3"'
    COMMAND       PID USER ASSOC MODE TYPE SOURCE MNTID INODE NAME               FLAGS
    test_mkfds 125128  jet     3  r--  DIR   dm-0    96    96 /    ???????????????????

The decoded string is printed at ???????????????????.

Quoted from /usr/include/bits/fcntl-linux.h:

    #ifndef __O_LARGEFILE
    # define __O_LARGEFILE 0100000
    #endif
    #ifndef __O_DIRECTORY
    # define __O_DIRECTORY 0200000
    #endif
    #ifndef __O_TMPFILE
    # define __O_TMPFILE   (020000000 | __O_DIRECTORY)
    #endif
    ...
    #ifdef __USE_XOPEN2K8
    # define O_DIRECTORY __O_DIRECTORY /* Must be a directory.  */
    ...
    #endif
    ...
    #ifdef __USE_LARGEFILE64
    # define O_LARGEFILE __O_LARGEFILE
    #endif

With these constants, 0300000 is decoded as "directory,_tmpfile" or
"largefile,directory,_tmpfile".

Unexpectedly the decoded string has "_tmpfile".
It has "largefile" only when we define __USE_LARGEFILE64 when building
lsfd though it should have "largefile" always.

Quoted from /usr/include/asm-generic/fcntl.h:

    #ifndef O_LARGEFILE
    #define O_LARGEFILE 00100000
    #endif
    #ifndef O_DIRECTORY
    #define O_DIRECTORY 00200000 /* must be a directory */
    #endif
    #ifndef __O_TMPFILE
    #define __O_TMPFILE 020000000
    #endif

The decoded string is "largefile,directory". It doesn't depend on
__USE_LARGEFILE64.

This change adds lsfd-decode-file-flags.c, a new small and isolated
source file, in which lsfd_decode_file_flags(), the function for
decoding the field is defined.

include/c.h includes /usr/include/fcntl.h. Almost all lsfd related
source files includes include/c.h indirectly. On the other hand,
lsfd-decode-file-flags.c includes only /usr/include/asm-generic/fcntl.h
or /usr/include/asm/fcntl.h. So the function can decode the field
expectedly.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
configure.ac
meson.build
misc-utils/Makemodule.am
misc-utils/lsfd-decode-file-flags.c [new file with mode: 0644]
misc-utils/lsfd-file.c
misc-utils/meson.build
tests/expected/lsfd/mkfds-directory

index 3ac79a503588978ecf2c9e958f85bc2bd01d3389..f6ce2d12b4b98a35607677f0399280008eab3f66 100644 (file)
@@ -291,6 +291,8 @@ AC_CHECK_HEADERS([linux/compiler.h linux/blkpg.h linux/major.h], [], [], [
 #endif
 ])
 AC_CHECK_HEADERS([ \
+       asm-generic/fcntl.h \
+       asm/fcntl.h \
        asm/io.h \
        byteswap.h \
        endian.h \
index 460c322e786106baa10af7f793fcd30456a9393b..536bb36facd12e7634dee0d9560d6a253bbaa1c3 100644 (file)
@@ -151,6 +151,8 @@ headers = '''
         unistd.h
         utmp.h
         utmpx.h
+        asm-generic/fcntl.h
+        asm/fcntl.h
         asm/io.h
         linux/blkzoned.h
         linux/capability.h
index dea07982003d1249d19442e7812b037976a41958..dfeff6f4e643942759b8b4f7654923c0618db846 100644 (file)
@@ -258,6 +258,7 @@ lsfd_SOURCES = \
        misc-utils/lsfd-filter.c \
        misc-utils/lsfd-counter.h \
        misc-utils/lsfd-counter.c \
+       misc-utils/lsfd-decode-file-flags.c \
        misc-utils/lsfd-file.c \
        misc-utils/lsfd-cdev.c \
        misc-utils/lsfd-bdev.c \
diff --git a/misc-utils/lsfd-decode-file-flags.c b/misc-utils/lsfd-decode-file-flags.c
new file mode 100644 (file)
index 0000000..b958797
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * lsfd(1) - list file descriptors
+ *
+ * Copyright (C) 2022 Red Hat, Inc. All rights reserved.
+ * Written by Masatake YAMATO <yamato@redhat.com>
+ *
+ * Very generally based on lsof(8) by Victor A. Abell <abe@purdue.edu>
+ * It supports multiple OSes. lsfd specializes to Linux.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* lsfd_decode_file_flags() is for decoding `flags' field of
+ * /proc/$pid/fdinfo/$fd. Bits of the field have name defined
+ * in fctl.h.
+ * A system on which lsfd is built may have multiple
+ * fctl.h files:
+ *
+ * - /usr/include/asm-generic/fcntl.h (a part of Linux kernel)
+ * - /usr/include/asm/fcntl.h         (a part of Linux kernel)
+ * - /usr/include/fcntl.h             (a part of glibc)
+ * - /usr/include/bits/fcntl.h        (a part of glibc)
+ *
+ * For decoding purpose, /usr/include/asm-generic/fcntl.h or
+ * /usr/include/asm/fcntl.h is needed.
+ *
+ * /usr/include/bits/fcntl.h and /usr/include/fcntl.h are
+ * not suitable for decoding. They should not be included.
+ * /usr/include/fcntl.h includes /usr/include/bits/fcntl.h.
+ */
+
+#ifdef HAVE_ASM_GENERIC_FCNTL_H
+#include <asm-generic/fcntl.h>
+#elif HAVE_ASM_FCNTL_H
+#include <asm/fcntl.h>
+#else
+#error "kernel's fcntl.h is not available"
+#endif
+
+#include <stddef.h>            /* for size_t */
+struct ul_buffer;
+
+void lsfd_decode_file_flags(struct ul_buffer *buf, int flags);
+
+/* We cannot include buffer.h because buffer.h includes
+ * /usr/include/fcntl.h indirectly. */
+extern int ul_buffer_is_empty(struct ul_buffer *buf);
+extern int ul_buffer_append_data(struct ul_buffer *buf, const char *data, size_t sz);
+extern int ul_buffer_append_string(struct ul_buffer *buf, const char *str);
+
+void lsfd_decode_file_flags(struct ul_buffer *buf, int flags)
+{
+#define SET_FLAG_FULL(L,s)                                             \
+       do {                                                            \
+               if (flags & (L)) {                                      \
+                       if (!ul_buffer_is_empty(buf))                   \
+                               ul_buffer_append_data(buf, ",", 1);     \
+                       ul_buffer_append_string(buf, #s);               \
+               }                                                       \
+       } while (0)
+
+#define SET_FLAG(L,s) SET_FLAG_FULL(O_##L,s)
+
+#ifdef O_WRONLY
+       SET_FLAG(WRONLY,wronly);
+#endif
+
+#ifdef O_RDWR
+       SET_FLAG(RDWR,rdwr);
+#endif
+
+#ifdef O_CREAT
+       SET_FLAG(CREAT,creat);
+#endif
+
+#ifdef O_EXCL
+       SET_FLAG(EXCL,excl);
+#endif
+
+#ifdef O_NOCTTY
+       SET_FLAG(NOCTTY,noctty);
+#endif
+
+#ifdef O_APPEND
+       SET_FLAG(APPEND,append);
+#endif
+
+#ifdef O_NONBLOCK
+       SET_FLAG(NONBLOCK,nonblock);
+#endif
+
+#ifdef O_DSYNC
+       SET_FLAG(DSYNC,dsync);
+#endif
+
+#ifdef O_FASYNC
+       SET_FLAG(FASYNC,fasync);
+#endif
+
+#ifdef O_DIRECT
+       SET_FLAG(DIRECT,direct);
+#endif
+
+#ifdef O_LARGEFILE
+       SET_FLAG(LARGEFILE,largefile);
+#endif
+
+#ifdef O_DIRECTORY
+       SET_FLAG(DIRECTORY,directory);
+#endif
+
+#ifdef O_FOLLOW
+       SET_FLAG(FOLLOW,follow);
+#endif
+
+#ifdef O_NOATIME
+       SET_FLAG(NOATIME,noatime);
+#endif
+
+#ifdef O_CLOEXEC
+       SET_FLAG(CLOEXEC,cloexec);
+#endif
+
+#ifdef __O_SYNC
+       SET_FLAG_FULL(__O_SYNC,_sync);
+#endif
+
+#ifdef O_PATH
+       SET_FLAG(PATH,path);
+#endif
+
+#ifdef __O_TMPFILE
+       SET_FLAG_FULL(__O_TMPFILE,_tmpfile);
+#endif
+
+}
index e65af38015ae14b8a080e8c83dea7942b3659e15..842bf034017b9589ab722efda9781cfc28fb1c05 100644 (file)
@@ -78,92 +78,10 @@ static const char *strftype(mode_t ftype)
        }
 }
 
-/* See /usr/include/asm-generic/fcntl.h */
+extern void lsfd_decode_file_flags(struct ul_buffer *buf, int flags);
 static void file_fill_flags_buf(struct ul_buffer *buf, int flags)
 {
-#define SET_FLAG_FULL(L,s)                                             \
-       do {                                                            \
-               if (flags & (L)) {                                      \
-                       if (!ul_buffer_is_empty(buf))                   \
-                               ul_buffer_append_data(buf, ",", 1);     \
-                       ul_buffer_append_string(buf, #s);               \
-               }                                                       \
-       } while (0)
-
-#define SET_FLAG(L,s) SET_FLAG_FULL(O_##L,s)
-
-#ifdef O_WRONLY
-       SET_FLAG(WRONLY,wronly);
-#endif
-
-#ifdef O_RDWR
-       SET_FLAG(RDWR,rdwr);
-#endif
-
-#ifdef O_CREAT
-       SET_FLAG(CREAT,creat);
-#endif
-
-#ifdef O_EXCL
-       SET_FLAG(EXCL,excl);
-#endif
-
-#ifdef O_NOCTTY
-       SET_FLAG(NOCTTY,noctty);
-#endif
-
-#ifdef O_APPEND
-       SET_FLAG(APPEND,append);
-#endif
-
-#ifdef O_NONBLOCK
-       SET_FLAG(NONBLOCK,nonblock);
-#endif
-
-#ifdef O_DSYNC
-       SET_FLAG(DSYNC,dsync);
-#endif
-
-#ifdef O_FASYNC
-       SET_FLAG(FASYNC,fasync);
-#endif
-
-#ifdef O_DIRECT
-       SET_FLAG(DIRECT,direct);
-#endif
-
-#ifdef O_LARGEFILE
-       SET_FLAG(LARGEFILE,largefile);
-#endif
-
-#ifdef O_DIRECTORY
-       SET_FLAG(DIRECTORY,directory);
-#endif
-
-#ifdef O_FOLLOW
-       SET_FLAG(FOLLOW,follow);
-#endif
-
-#ifdef O_NOATIME
-       SET_FLAG(NOATIME,noatime);
-#endif
-
-#ifdef O_CLOEXEC
-       SET_FLAG(CLOEXEC,cloexec);
-#endif
-
-#ifdef __O_SYNC
-       SET_FLAG_FULL(__O_SYNC,_sync);
-#endif
-
-#ifdef O_PATH
-       SET_FLAG(PATH,path);
-#endif
-
-#ifdef __O_TMPFILE
-       SET_FLAG_FULL(__O_TMPFILE,_tmpfile);
-#endif
-
+       lsfd_decode_file_flags(buf, flags);
 }
 
 #define does_file_has_fdinfo_alike(file)       \
index 405f1ccf00bbc8bda42367a0e7d97e191e820e1c..818232a580df055a5a25112412b5a7885a3ffa16 100644 (file)
@@ -46,6 +46,7 @@ lsfd_sources = files (
   'lsfd-filter.c',
   'lsfd-counter.h',
   'lsfd-counter.c',
+  'lsfd-decode-file-flags.c',
   'lsfd-file.c',
   'lsfd-cdev.c',
   'lsfd-bdev.c',
index a1d0aac2727a2a95c3d2c9cb9b66900d152a1517..fd7f2935cc6c2ad421e47c9629cda25859995789 100644 (file)
@@ -1,4 +1,4 @@
-    3  r--  DIR directory,_tmpfile /
+    3  r--  DIR directory /
 ASSOC,MODE,TYPE,FLAGS,NAME: 0
 PID[RUN]: 0
 PID[STR]: 0