Open file by inode

2020-03-13 04:53发布

问题:

Is it possible to open a file knowing its inode?

ls -i /tmp/test/test.txt
529965 /tmp/test/test.txt

I can provide path, inode (above 529965) and I am looking to get in return a file descriptor.

回答1:

This is not possible because it would open a loophole in the access control rules. Whether you can open a file depends not only on its own access permission bits, but on the permission bits of every containing directory. (For instance, in your example, if test.txt were mode 644 but the containing directory test were mode 700, then only root and the owner of test could open test.txt.) Inode numbers only identify the file, not the containing directories (it's possible for a file to be in more than one directory; read up on "hard links") so the kernel cannot perform a complete set of access control checks with only an inode number.

(Some Unix implementations have offered nonstandard root-only APIs to open a file by inode number, bypassing some of the access-control rules, but if current Linux has such an API, I don't know about it.)



回答2:

Not exactly what you are asking, but (as hinted by zwol) both Linux and NetBSD/FreeBSD provide the ability to open files using previously created “handles”: These are inode-like persistent names that identify a file on a file system.

On *BSD (getfh and fhopen) using this is as simple as:

#include <sys/param.h>
#include <sys/mount.h>


fhandle_t file_handle;
getfh("<file_path>", &file_handle);  // Or `getfhat` for the *at-style API

// … possibly save handle as bytes somewhere and recreate it some time later …

int fd = fhopen(&file_handle, O_RDWR);

The last call requiring the caller to be root however.

The Linux name_to_handle_at and open_by_handle_at system calls are similar, but a lot more explicit and require the caller to keep track of the relevant file system mount IDs/UUIDs themselves, so I'll humbly link to the detailed example in the manpage instead. Beware, that the example is not complete if you are looking to persist the handles across reboots; one has to convert the received mount ID to a persistent filesystem identifier, such as a filesystem UUID, and convert that back to a mount ID later on. In essence they do the same however. And just like on *BSD using the later system call requires elevated privileges (CAP_DAC_READ_SEARCH to be exact).