Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a hard link from a file handle on Unix?

Tags:

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.

like image 950
David Wolever Avatar asked Jun 15 '13 20:06

David Wolever


People also ask

How do you create a hard link in Unix?

To create a hard links on a Linux or Unix-like system: Create hard link between sfile1file and link1file, run: ln sfile1file link1file. To make symbolic links instead of hard links, use: ln -s source link. To verify soft or hard links on Linux, run: ls -l source link.

What is hard link command in Unix?

A hard link is essentially a label or name assigned to a file. Conventionally, we think of a file as consisting of a set of information that has a single name. However, it is possible to create a number of different names that all refer to the same contents.

Can you hard link a file?

While useful, there are some limitations to what hard links can do. For starters, they can only be created for regular files (not directories or special files). Also, a hard link cannot span multiple filesystems. They only work when the new hard link exists on the same filesystem as the original.

Which command create hard link for the file file txt?

To create a hard links in Linux, we will use ln utility. For example, the following command creates a hard link named tp to the file topprocs.sh . Looking at the output above, using ls command, the new file is not indicated as a link, it is shown as a regular file.


2 Answers

The newly released linux 3.11 offers a solution to this problem with the new O_TMPFILE open(2) flag. With this flag you can create an "invisible" file (i.e. an inode with no hardlinks) in some file system (specified by a directory in that file system). Then, after the file is fully set up, you can create a hardlink using linkat. It works like this:

fd = open("/tmp", O_TMPFILE | O_RDWR, 0600);
// write something to the file here
// fchown()/fchmod() it
linkat(fd, "", AT_FDCWD, "/tmp/test", AT_EMPTY_PATH);

Note that aside from the >=3.11 kernel requirement, this also requires support from the underlying file system (I tried the above snippet on ext3 and it worked, but it did not seem to work on btrfs).

like image 177
safsaf32 Avatar answered Nov 02 '22 12:11

safsaf32


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.

like image 41
torek Avatar answered Nov 02 '22 12:11

torek