假设操作系统是Linux。 假设我已经打开了一个文件并获得了一个文件描述符 fdw 用于写入。 是否可能通过不再调用
open 来获取另一个具有只读访问权限的文件描述符
fdr ? 我不想调用
open 的原因是底层文件可能已被其他进程在文件系统中移动甚至取消链接,因此重新使用同一文件名对于这些操作不可靠。 因此,我的问题是:如果只给定一个文件描述符,是否有任何方式可以打开具有不同访问权限的文件描述符? 我认为
dup 或
dup2 不会更改访问权限。
没错!诀窍是通过/proc/self/fd/n
访问已删除的文件。据我所知,这是仅适用于linux的技巧。
运行此程序:
#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;
}
它向文件写入一些文本,删除它,但保留文件描述符并通过不同的路径重新打开它。 直到持有最后一个文件描述符的进程关闭它之前,文件实际上并没有被删除,并且在此期间,您可以通过 /proc
访问文件内容。
感谢我的老板Anatoly在我误删一些重要文件时教给我这个技巧,幸运的是这些文件仍然被另一个进程追加!
不,fcntl 调用不能让你在打开的文件描述符上设置读/写位,而从现有的文件描述符获取新的文件描述符的唯一方法是使用复制功能。调用 dup/dup2/dup3(和 fcntl
)不能让你更改文件访问模式。
注意:这对于Linux是正确的,但通常不适用于其他Unix。例如,在HP-UX中,[请参见(1)和(2)],您可以使用fcntl
在打开的文件描述符上使用F_SETFL更改读/写位。然而,由dup
创建的文件描述符共享相同的状态标志,因此更改一个的访问模式必然会更改另一个的访问模式。
freopen
在 FILE *
流的功能上与此类似,因为访问模式是否可变取决于操作系统的实现。 - CMCDragonkai
/proc/self
,但是有/dev/fd/n
,不过这个技巧在那里行不通。 - andrewdotnchar 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 );
然后写入f,关闭它并执行f_ro。 - Zibriecho foo > in; bash -c 'echo bar > /dev/fd/0' < in; cat in
能够正常工作(输出 "bar"),尽管python3 -c 'import os; print(os.write(0, b"bar\n"))' < in
失败了("[Errno 9] Bad file descriptor")。 - Beni Cherniavsky-Paskin