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?
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.