假设操作系统是linux。假设我打开了一个用于写入的文件并获取了文件描述符fdw
。是否可以获得另一个文件描述符fdr
,只读访问该文件而不再调用open
?我不想调用open
的原因是底层文件可能已被其他进程在文件系统中移动甚至取消链接,因此重复使用相同的文件名对此类操作不可靠。所以我的问题是:如果仅提供文件描述符,是否有打开具有不同访问权限的文件描述符?我认为dup
或dup2
并未改变访问权限。
答案 0 :(得分:12)
是的!诀窍是通过/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
获取文件内容。
感谢我的老板阿纳托利教我这个技巧,当我删除了一些重要文件时,幸运的是仍然被另一个进程追加!
答案 1 :(得分:6)
不,fcntl调用不允许您在打开的文件描述符上设置读/写位,并且从现有文件描述符获取新文件描述符的唯一方法是使用重复功能。对dup/dup2/dup3(和fcntl
)的调用不允许您更改文件访问模式。
注意:这适用于Linux,但对于其他一般的Unix则不然。例如,在HP-UX中,[请参阅(1)和(2)],您可以在打开的文件描述符上使用F_SETFL使用fcntl
更改读/写位。由于dup
创建的文件描述符共享相同的状态标志,因此更改一个的访问模式必然会为另一个更改它。