Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicating file descriptor and seeking through both of them independently

I have an open file descriptor which I want to duplicate in order to perform reading and seeking through both of them independently. I looked at the

int dup(int old_fd)

syscall. The problem is it does not really fit here. Man page states the following http://man7.org/linux/man-pages/man2/dup.2.html :

After a successful return, the old and new file descriptors may be used interchangeably. They refer to the same open file description (see open(2)) and thus share file offset and file status flags; for example, if the file offset is modified by using lseek(2) on one of the file descriptors, the offset is also changed for the other.

Is there a way to duplicate a file descriptor so they are completely independent?

like image 563
Some Name Avatar asked Jan 27 '23 17:01

Some Name


1 Answers

In Linux, opening /proc/<pid>/fd/<n> opens the file that's currently open at fd N, but this is a new copy, not a linked duplicate like the one you get with dup() and friends.

This should create a file that contains bar, a bunch of zero bytes, then foo. Contrast with the version using dup().

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(void)
{
    int fd1, fd2;
    char buffer[50];

    fd1 = open("testfile", O_CREAT | O_TRUNC | O_RDWR, 0600);
    sprintf(buffer, "/proc/self/fd/%d", fd1);
#ifndef USE_DUP
    fd2 = open(buffer, O_RDWR);
    if (fd2 == -1) {
        perror("open");
    }
#else
    fd2 = dup(fd1);
#endif
    if (lseek(fd1, 16, SEEK_SET) == -1) {
        perror("lseek");
    }
    if (write(fd1, "foo", 3) == -1) {
        perror("write(fd1)");
    }
    if (write(fd2, "bar", 3) == -1) {
        perror("write(fd2)");
    }
}
like image 190
ilkkachu Avatar answered Feb 05 '23 18:02

ilkkachu