Skip to content
Advertisement

Create a hard link from a file handle on Unix?

If I’ve got a handle to an open file, is it possible to create a hard link to that file after all references to it have been removed from the filesystem?

For example, something like this:

fd = fopen("/tmp/foo", "w");
unlink("/tmp/foo");
fwrite(fd, "Hello, world!n");
create_link_from_fd(fd, "/tmp/hello");
fclose(fd);

Specifically, I’d like to do this so that I can safely write to large data files, then move them into place atomically without having to worry about cleaning up after myself if my program is killed in the middle of writing the file.

Advertisement

Answer

Not generally, no. [Edit: since Linux 3.11 there is now linkat; see safsaf32’s answer. This does not work on POSIX systems in general since POSIX linkat is restricted to directories only.] There are security considerations here: someone can pass to you an open file descriptor that you could not normally open on your own, e.g.:

mkdir lock; chmod 700 lock
echo secret contents > lock/in
sudoish cmd < lock/in

Here cmd runs as a user who has no permission to open the input file (lock/in) by name, but can still read from it. If cmd could create a new name on the same file system, it could pass the file contents on to a later process. (Obviously it can copy those contents, so this issue is more of a “pass the contents on by mistake” thing than “pass the contents on, on purpose”.)

That said, people have come up with ways of “relinking” files by inode/vnode internally (it’s pretty easy to do inside most file systems), so you could make your own private system call for it. The descriptor must refer to a real file on the appropriate mount point, of course—there’s no way of “relinking” a pipe or socket or device into becoming a regular file.

Otherwise you’re stuck with “catch signals and clean up and hope for the best”, or a similar trick, “fork off a subprocess, run it, and if it succeeds/fails, take appropriate move/clean-up action”.


Edit to add historical note: the above lock example is not particularly good, but back in the days of V6 Unix, MDQS used a fancier version of this trick. Bits and pieces of MDQS survive in various forms today.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement