util-linux/misc-utils/lsfd-decode-file-flags.c

149 lines
3.5 KiB
C
Raw Normal View History

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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
/*
* 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/fcntl.h (a part of Linux kernel)
* - /usr/include/asm-generic/fcntl.h (a part of Linux kernel)
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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
* - /usr/include/fcntl.h (a part of glibc)
* - /usr/include/bits/fcntl.h (a part of glibc)
*
* For decoding purpose, /usr/include/asm/fcntl.h or
* /usr/include/asm-generic/fcntl.h is needed.
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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
*
* /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.
*/
#if defined HAVE_ASM_FCNTL_H
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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
#include <asm/fcntl.h>
#elif defined HAVE_ASM_GENERIC_FCNTL_H
#include <asm-generic/fcntl.h>
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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
#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 FASYNC
SET_FLAG_FULL(FASYNC,fasync);
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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
#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_NOFOLLOW
SET_FLAG(NOFOLLOW,nofollow);
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 <yamato@redhat.com>
2022-06-09 00:32:19 +09:00
#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
}