Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rename from a file descriptor?

Tags:

posix

rename

A variant of the question Getting Filename from file descriptor in C. This is about Linux.

If I have a file descriptor that refers to a regular file, can I "save" the file descriptor by giving it a new file name (somewhere on the same device as where it lives, of course)? I'm looking for something similar to rename(2) or link(2) but that would accept a file descriptor as input instead of a file name.

The problem with rename(2) and link(2) is that even though you can attempt to go from the file descritor to the file name, this might fail. I'm thinking more precisely about the case where the opened file descriptor refers to a file that was already unlinked --- in this case, the file has no more name. It seems that there is no way to prevent the file from being deleted when we close() the file descriptor. But am I wrong? Can we, with the Posix or even Linux API, give it a name again?

Update: we can actually see the content of a deleted file on Linux in /proc/<pid>/fd/<fd>, even though it looks like a broken symbolic link. We can't use link(2) or ln(1) to rematerialize such a file, though, because it thinks we're trying to do a cross-device link.

like image 300
Armin Rigo Avatar asked Dec 13 '12 14:12

Armin Rigo


People also ask

How do you change a file name?

Right-click the file and select Rename. Enter a new file name and press Enter.

How do I rename a file in the directory?

Method one. Highlight the file or folder. Right-click the file with your mouse and select Rename from the menu that appears.

Is PID a file descriptor?

No it is not. PID is process identifier, and file descriptor is file handler identifier.


2 Answers

If the question is about linux, and about linux > 2.6.39, you can use the linkat command with the AT_EMPTY_PATH flag to give a name to a file descriptor. See the man page (http://man7.org/linux/man-pages/man2/link.2.html)

linkat(fd,"",destdirfd,"filename",AT_EMPTY_PATH);

Caveats:

  • You need to define _GNU_SOURCE to get the definition for AT_EMPTY_PATH,
  • For files with link count of zero this is not guaranteed to work. I'm not sure I understand what the manual page says about this. My guess is that when a file has zero link count the inode is already deleted on the filesystem, to avoid inconsistencies if the filesystem were to crash.
  • Of course I don't expect it to work if the old file is not on the same filesystem at the target directory.

If this were to fail, you have no other chance than to create a new file and copy the content over it using sendfile (error checking omitted, see man pages of each function for possible error values):

struct stat s;
off_t offset = 0;
int targetfd = open("target/filename", O_WRONLY | O_CREAT | O_EXCL);
fstat(fd,&s);
sendfile(targetfd,fd,&offset, s.st_size);
like image 180
pqnet Avatar answered Sep 22 '22 10:09

pqnet


Question: a hypothetical system call frename that takes a file descriptor existed, and if a file has multiple names (hard links), which of those names would get moved/renamed when this system call was used on a file descriptor that refers to this file?

There is no good answer to that question, and that's one of the reasons this system call does not exist.

rename deals with directory entries, which are pointers to files (inodes). An open file descriptor is not associated with any particular directory entry, only with the file itself (the inode). From that perspective, the system call you are asking for doesn't really make sense. There is no portable way to follow an inode back to the directory entry that points to it (and, again, there might be more than one of them). Some operating systems may provide various non-portable means for finding this backward link which may or may not be guaranteed to always come up with a result (usually not guaranteed), but these means don't answer the question of which directory entry to return when there is more than one, and to my knowledge none of them have been extended into a system call like what you're looking for.

like image 39
Celada Avatar answered Sep 25 '22 10:09

Celada