Is it possible to determine which fds a process has open for reading vs. writing via procfs?

StackOverflow https://stackoverflow.com/questions/22367367

  •  13-06-2023
  •  | 
  •  

Question

The procfs will tell me which fds a process is using at any given time. But is there a way to determine which are open for reading vs. writing?

In the output below, clearly the process owner (user 'x') has read/write access to the link/file, but this isn't the same as knowing whether pid 4166 is writing to or reading from a particular fd.

$ ls -l /proc/4166/fd/
total 0
lrwx------ 1 x x 64 Mar 12 21:15 0 -> /dev/pts/3
lrwx------ 1 x x 64 Mar 12 21:15 1 -> /dev/pts/3
lrwx------ 1 x x 64 Mar 12 21:15 2 -> /dev/pts/3
lrwx------ 1 x x 64 Mar 12 21:15 255 -> /dev/pts/3

I know that the lsof utility can do this:

$ lsof -p 4166 | grep CHR
bash    4166    x    0u   CHR  136,3      0t0      6 /dev/pts/3
bash    4166    x    1u   CHR  136,3      0t0      6 /dev/pts/3
bash    4166    x    2u   CHR  136,3      0t0      6 /dev/pts/3
bash    4166    x  255u   CHR  136,3      0t0      6 /dev/pts/3

The manpage for lsof says that for example those trailing u's behind the fd numbers (0, 1, 2, 255) mean that the fd is open for reading and writing.

My question though is whether or not it's possible to obtain this information via the procfs rather than lsof. For various reasons, executing lsof inside of another programming language is less convenient for me than polling procfs, so I'm wondering if there's a direct way to do it there.

Was it helpful?

Solution

I dug through the lsof code as suggested, and found the answer.

Essentially the lsof utility opens files in /proc/XX/fdinfo/YY where XX is the process PID and YY is the file descriptor number. Each of those files is a tiny text file that looks like this:

user@host:/proc/6095/fdinfo$ cat 8 
pos:    0
flags:  02004002

Consulting additional manpages, the "flags" field refers to flags passed to the open system command relevant man page for open(2) here. So just to make it a bit more difficult, of course open() defines all of those flags symbolically, not numerically. So what do flags of 02004002 (example above) mean?

I found definitions as part of libc6-dev, in /usr/include/i386-linux-gnu/bits/fcntl-linux.h, including these excerpted: (warning do not trust these values for your system, look them up yourself as they may be different)

# define O_CREAT           0100
# define O_APPEND         02000
#define O_ACCMODE          0003
#define O_RDONLY             00
#define O_WRONLY             01
#define O_RDWR               02
# define O_CREAT           0100 /* Not fcntl.  */
# define O_TRUNC          01000
# define __O_DIRECTORY  0200000
# define O_DIRECTORY    __O_DIRECTORY   /* Must be a directory.  */
# define O_NONBLOCK       04000
# define __O_CLOEXEC   02000000

So given flags: 02004002, that file looks like it's open for read/write (02), non-blocking (4000), close-on-exec (2000000).

HTH someone else who gets confused on these points.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top