Assume the OS is linux. Suppose I opened a file for write and get a file descriptor fdw
. Is it possible to get another file descriptor fdr
, with read-only access to the file without calling open
again? The reason I don't want to call open
is the underlying file may have been moved or even unlinked in the file system by other processes, so re-use the same file name is not reliable against such actions. So my question is: is there anyway to open a file descriptor with different access right if given only a file descriptor? dup
or dup2
doesn't change the access right, I think.

- 8,557
- 8
- 53
- 93
2 Answers
Yes! The trick is to access the deleted file via /proc/self/fd/n
. It’s a linux-only trick, as far as I know.
Run this program:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
FILE* out_file;
FILE* in_file;
char* dev_fd_path;
char buffer[128];
/* Write “hi!” to test.txt */
out_file = fopen("test.txt", "w");
fputs("hi!\n", out_file);
fflush(out_file);
/* Delete the file */
unlink("test.txt");
/* Verify that the file is gone */
system("ls test.txt");
/* Reopen the filehandle in read-mode from /proc */
asprintf(&dev_fd_path, "/proc/self/fd/%d", fileno(out_file));
in_file = fopen(dev_fd_path, "r");
if (!in_file) {
perror("in_file is NULL");
exit(1);
}
printf("%s", fgets(buffer, sizeof(buffer), in_file));
return 0;
}
It writes some text to a file, deletes it, but keeps the file descriptor open and and then reopens it via a different route. Files aren’t actually deleted until the last process holding the last file descriptor closes it, and until then, you can get at the file contents via /proc
.
Thanks to my old boss Anatoly for teaching me this trick when I deleted some important files that were fortunately still being appended to by another process!

- 32,721
- 10
- 101
- 130
-
1That's cheating since he explicitly said "without calling open again" - though I suppose if you really wanted to do it, that's a constraint that you would relax. And he probably meant "without calling open with the same path" anyway. – tvanfosson Jan 25 '13 at 04:50
-
What's `/dev/proc/fd/n`, is that a typo? It seems to be `/proc/self/fd/%d` according to your code. – user541686 May 10 '13 at 04:45
-
1Whoops, you’re right! I’ve fixed it. I was confused because the mac doesn’t have `/proc/self`, but does have `/dev/fd/n`, though this trick doesn’t work there. – andrewdotn May 10 '13 at 13:45
-
NO NEED!!! I can just do this: char fname[14] = "/tmp/.zXXXXXX"; int f=mkostemp(fname, O_WRONLY); chmod(fname, S_IRUSR | S_IXUSR); int f_ro = open(fname, O_RDONLY); unlink( fname ); then write to f, close it and execute f_ro – Zibri Apr 21 '18 at 15:38
-
@Zibri That's a different problem than what OP is asking about. – melpomene May 18 '19 at 13:55
-
Cool! This explains why `echo foo > in; bash -c 'echo bar > /dev/fd/0' < in; cat in` works (prints "bar"), despite `python3 -c 'import os; print(os.write(0, b"bar\n"))' < in` failing ("[Errno 9] Bad file descriptor") – Beni Cherniavsky-Paskin Sep 13 '20 at 16:39
No, the fcntl call will not let you set the read/write bits on an open file descriptor and the only way to get a new file descriptor from an existing one is by using the duplicate functionality. The calls to dup/dup2/dup3 (and fcntl
) do not allow you to change the file access mode.
NOTE: this is true for Linux, but not true for other Unixes in general. In HP-UX, for example, [see (1) and (2)] you are able to change the read/write bits with fcntl
using F_SETFL on an open file descriptor. Since file descriptors created by dup
share the same status flags, however, changing the access mode for one will necessarily change it for the other.

- 524,688
- 99
- 697
- 795
-
Also noting that `freopen` has a similar functionality for `FILE *` streams, in that whether access modes are changeable depends on the OS implementation. – CMCDragonkai Jul 18 '17 at 11:33