Search code examples
linuxassemblyx86-64file-descriptor

How to identify if two file diescriptors point to the same file


I'm writing a program which has to work with files (open/write/close/etc). If I open a file and get a file descriptor and some other process moves the file to another location on the filesystem, the file descriptor I got before still remains valid. For example:

SYS_exit equ 0x3C
SYS_inotify_init equ 253
SYS_read equ 0x00
SYS_open equ 0x02
O_RDONLY equ 0x00
O_WRONLY equ 0x01
O_RDWR equ 0x02

section .text
    global _start

_start:
    mov rax, SYS_inotify_init
    syscall
    mov r13, rax            ;storing inotify instance

    mov rax, SYS_open
    mov rdi, dir_name_moved_from_file
    mov rsi, O_RDWR
    mov rdx, 0x00
    syscall                 ; <---- OPEN 1

    mov rax, SYS_open
    mov rdi, dir_name_moved_from_file
    mov rsi, O_RDWR
    mov rdx, 0x00
    syscall                 ; <---- OPEN 2

    ;listening inotify events and doing some other useful things

    mov eax, SYS_exit
    mov rdi, 0x00
    syscall

section .data
    dir_name_moved_from_file: db '/tmp/data/test', 0

The problem is that file descriptors returned by OPEN 1 and OPEN 2 are different even if I open the same file twice.

QUESTION: Is there a file-system independent way to identify if the file is already opened by the current process?


Solution

  • fstat on the FDs, and compare st_dev and st_ino. If they're both equal, you have the same file. The FDs may have been opened with different hardlink names for the same inode, but that situation is considered having multiple names for the same file.

    fstat is exactly what GNU cmp does, which you can see if you strace it. (It has an early-out check to exit true if you give it the same input twice.)

    But why is it true only for the same filesystems? As I checked inode number contains the location on a harddrive which seems to me filesystem independent

    Each st_dev has its own st_ino address space. The inode number corresponds to the position within the filesystem, not relative to the start of a physical hard drive. So typically it's relative to the start of the partition for the FS.

    It couldn't make sense any other way: filesystems don't care if they're on a RAID, or a logical block device made up of parts of multiple hard drives with Linux LVM, or whatever.