File descriptor using fstat(1) - OpenBSD

5 minute read Published: 2021-04-15

File descriptor is essential when it's come to Unix-Like OSes but not limited to.

How can we list them for a specific process on OpenBSD?

After a quick search I found the tool available by default on an OpenBSD installation called fstat(1).

Let's call it without any arguments stated on the man page:

unhu# fstat
USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV
root     fstat      29479 text /          233347  -r-xr-xr-x     r    23232
root     fstat      29479   wd /          336960  drwx------     r      512
root     fstat      29479    0 /           52336  crw--w----    rw    ttyp0
root     fstat      29479    1 /           52336  crw--w----    rw    ttyp0
root     fstat      29479    2 /           52336  crw--w----    rw    ttyp0
root     ksh           43 text /           25939  -r-xr-xr-x     r   613992
root     ksh           43   wd /          336960  drwx------     r      512
root     ksh           43    0 /           52336  crw--w----    rw    ttyp0
root     ksh           43    1 /           52336  crw--w----    rw    ttyp0
root     ksh           43    2 /           52336  crw--w----    rw    ttyp0
root     ksh           43   10 /           52997  crw-rw-rw-  rwep      tty
gunhu    ksh        13163 text /           25939  -r-xr-xr-x     r   613992
gunhu    ksh        13163   wd /          414775  drwxr-xr-x     r      512
gunhu    ksh        13163    0 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        13163    1 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        13163    2 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        13163   10 /           52997  crw-rw-rw-  rwep      tty

We can clearly see here that each users of this OpenBSD box own and have file descriptors.

You can add arguments to list and filter file descriptor from specific process:

unhu# fstat -p 13163
USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV
gunhu    ksh        13163 text /           25939  -r-xr-xr-x     r   613992
gunhu    ksh        13163   wd /          414775  drwxr-xr-x     r      512
gunhu    ksh        13163    0 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        13163    1 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        13163    2 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        13163   10 /           52997  crw-rw-rw-  rwep      tty

Or even a specific user for example:

unhu# fstat -u gunhu
USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV
gunhu    fstat      22246   wd /          414775  drwxr-xr-x     r      512
gunhu    fstat      22246    0 /           52336  crw--w----    rw    ttyp0
gunhu    fstat      22246    1 /           52336  crw--w----    rw    ttyp0
gunhu    fstat      22246    2 /           52336  crw--w----    rw    ttyp0
gunhu    fstat      22246    3 /          130018  -rw-r--r--    re    40960
gunhu    ksh        95242   wd /          414775  drwxr-xr-x     r      512
gunhu    ksh        95242    0 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        95242    1 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        95242    2 /           52336  crw--w----    rw    ttyp0
gunhu    ksh        95242   10 /           52997  crw-rw-rw-  rwep      tty
gunhu    sshd       31638   wd /               2  drwxr-xr-x     r      512
gunhu    sshd       31638    0 /           53000  crw-rw-rw-    rw     null
gunhu    sshd       31638    1 /           53000  crw-rw-rw-    rw     null
gunhu    sshd       31638    2 /           53000  crw-rw-rw-    rw     null
gunhu    sshd       31638    3* unix stream 0x0
gunhu    sshd       31638    4* internet stream tcp 0x0 127.0.0.1:22 <-- 127.0.0.1:5594
gunhu    sshd       31638    5 pipe 0x0 state:
gunhu    sshd       31638    6* unix stream 0x0
gunhu    sshd       31638    7 pipe 0x0 state:
gunhu    sshd       31638    8* unix stream 0x0 /tmp/ssh-2LhRuwykPy/agent.31638
gunhu    sshd       31638    9 /           52337  crw-rw-rw-   rwe    ptyp0
gunhu    sshd       31638   11 /           52337  crw-rw-rw-   rwe    ptyp0
gunhu    sshd       31638   12 /           52337  crw-rw-rw-    rw    ptyp0

Now let's take a close look on specific columns name:

One exception is for Unix/network socket:

If the file number is followed by an asterisk (‘*’), the file is not an inode, but rather a socket,
or there is an error. In this case the remainder of the line doesn't correspond to the remaining headers —
the format of the line is described later under SOCKETS.

Every files have an inode number which is a pointer of the file on the filesystem except for Unix/network socket.

Let's check strmode(3) pointed out by fstat(1)#MODE.

The first character is the inode type, and will be one of the following:
	-
	regular file
	b
	block special
	c
	character special
	d
	directory
	l
	symbolic link
	p
	FIFO
	s
	socket
	?
	unknown inode type

R/W column is the way to know it. Read (R) and Write (W) flags are easy to know what they are meant for.

Let's check a line with extra flags:

gunhu    ksh        95242   10 /           52997  crw-rw-rw-  rwep      tty

As you can see we have two more flags e and p.

e flag's description is close-on-exec which tell the program to close the file descriptor when any of the exec() functions are called.

p flag's description is Opened after pledge(2).

We now know a way to list every opened files on an OpenBSD box.

See you space cowboy...