Reopen a file descriptor with another access?

前端 未结 2 1042
栀梦
栀梦 2020-12-03 11:23

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

相关标签:
2条回答
  • 2020-12-03 12:00

    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.

    0 讨论(0)
  • 2020-12-03 12:06

    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[sizeof("/proc/self/fd/2147483647")];
        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 */
        if (snprintf(dev_fd_path, sizeof(dev_fd_path), "/proc/self/fd/%d", fileno(out_file)) >= sizeof(dev_fd_path)) {
            fprintf(stderr, "file descriptor too large\n");
            return 1;
        }
    
        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!

    0 讨论(0)
提交回复
热议问题