Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relinking an anonymous (unlinked but open) file

In Unix, it's possible to create a handle to an anonymous file by, e.g., creating and opening it with creat() and then removing the directory link with unlink() - leaving you with a file with an inode and storage but no possible way to re-open it. Such files are often used as temp files (and typically this is what tmpfile() returns to you).

My question: is there any way to re-attach a file like this back into the directory structure? If you could do this it means that you could e.g. implement file writes so that the file appears atomically and fully formed. This appeals to my compulsive neatness. ;)

When poking through the relevant system call functions I expected to find a version of link() called flink() (compare with chmod()/fchmod()) but, at least on Linux this doesn't exist.

Bonus points for telling me how to create the anonymous file without briefly exposing a filename in the disk's directory structure.

like image 365
ijw Avatar asked Nov 13 '10 08:11

ijw


People also ask

Does unlink remove a file?

The unlink function deletes the file name filename . If this is a file's sole name, the file itself is also deleted. (Actually, if any process has the file open when this happens, deletion is postponed until all processes have closed the file.)

What does it mean to unlink a file?

unlink() deletes a name from the filesystem. If that name was the last link to a file and no processes have the file open, the file is deleted and the space it was using is made available for reuse.


2 Answers

A patch for a proposed Linux flink() system call was submitted several years ago, but when Linus stated "there is no way in HELL we can do this securely without major other incursions", that pretty much ended the debate on whether to add this.

Update: As of Linux 3.11, it is now possible to create a file with no directory entry using open() with the new O_TMPFILE flag, and link it into the filesystem once it is fully formed using linkat() on /proc/self/fd/fd with the AT_SYMLINK_FOLLOW flag.

The following example is provided on the open() manual page:

    char path[PATH_MAX];     fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);      /* File I/O on 'fd'... */      snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);     linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW); 

Note that linkat() will not allow open files to be re-attached after the last link is removed with unlink().

like image 166
mark4o Avatar answered Oct 14 '22 06:10

mark4o


My question: is there any way to re-attach a file like this back into the directory structure? If you could do this it means that you could e.g. implement file writes so that the file appears atomically and fully formed. This appeals to the my compulsive neatness. ;)

If this is your only goal, you can achieve this in a much simpler and more widely used manner. If you are outputting to a.dat:

  1. Open a.dat.part for write.
  2. Write your data.
  3. Rename a.dat.part to a.dat.

I can understand wanting to be neat, but unlinking a file and relinking it just to be "neat" is kind of silly.

This question on serverfault seems to indicate that this kind of re-linking is unsafe and not supported.

like image 42
cdhowie Avatar answered Oct 14 '22 05:10

cdhowie