From 908ac36f27bf1f86abcf4cad31318d84de544985 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 9 Jun 2022 00:32:19 +0900 Subject: [PATCH] lsfd: use constants defined in asm/fctl.h flags field of a fdinfo 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 --- configure.ac | 2 + meson.build | 2 + misc-utils/Makemodule.am | 1 + misc-utils/lsfd-decode-file-flags.c | 148 ++++++++++++++++++++++++++++ misc-utils/lsfd-file.c | 86 +--------------- misc-utils/meson.build | 1 + tests/expected/lsfd/mkfds-directory | 2 +- 7 files changed, 157 insertions(+), 85 deletions(-) create mode 100644 misc-utils/lsfd-decode-file-flags.c diff --git a/configure.ac b/configure.ac index 3ac79a5035..f6ce2d12b4 100644 --- a/configure.ac +++ b/configure.ac @@ -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 \ diff --git a/meson.build b/meson.build index 460c322e78..536bb36fac 100644 --- a/meson.build +++ b/meson.build @@ -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 diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am index dea0798200..dfeff6f4e6 100644 --- a/misc-utils/Makemodule.am +++ b/misc-utils/Makemodule.am @@ -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 index 0000000000..b958797549 --- /dev/null +++ b/misc-utils/lsfd-decode-file-flags.c @@ -0,0 +1,148 @@ +/* + * lsfd(1) - list file descriptors + * + * Copyright (C) 2022 Red Hat, Inc. All rights reserved. + * Written by Masatake YAMATO + * + * Very generally based on lsof(8) by Victor A. Abell + * 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 +#elif HAVE_ASM_FCNTL_H +#include +#else +#error "kernel's fcntl.h is not available" +#endif + +#include /* 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 + +} diff --git a/misc-utils/lsfd-file.c b/misc-utils/lsfd-file.c index e65af38015..842bf03401 100644 --- a/misc-utils/lsfd-file.c +++ b/misc-utils/lsfd-file.c @@ -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) \ diff --git a/misc-utils/meson.build b/misc-utils/meson.build index 405f1ccf00..818232a580 100644 --- a/misc-utils/meson.build +++ b/misc-utils/meson.build @@ -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', diff --git a/tests/expected/lsfd/mkfds-directory b/tests/expected/lsfd/mkfds-directory index a1d0aac272..fd7f2935cc 100644 --- a/tests/expected/lsfd/mkfds-directory +++ b/tests/expected/lsfd/mkfds-directory @@ -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 -- 2.47.3