3

When stracing dd (from gnu coreutils) I found something that surprised me:

openat(AT_FDCWD, "/dev/zero", O_RDONLY) = 3                                                                                                                   
dup2(3, 0)                              = 0                                                                                                                   
close(3)                                = 0                                                                                                                   
lseek(0, 0, SEEK_CUR)                   = 0                                                                                                                   
openat(AT_FDCWD, "/dev/null", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
dup2(3, 1)                              = 1
close(3)                                = 0
mmap(NULL, 1060864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x681e58939000
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1048576) = 1048576
close(0)                                = 0
close(1)                                = 0

dd opens the files which it should read from / write to and then uses dup2 to change the filedescriptor to the filedescriptors 0 (stdin) and 1 (stdout).

I looked up the code to see if this is done by human or compiler optimization and it is indeed there:

static int
ifd_reopen (int desired_fd, char const *file, int flag, mode_t mode)
{
  int ret;

  do
    {
      process_signals ();
      ret = fd_reopen (desired_fd, file, flag, mode);
    }
  while (ret < 0 && errno == EINTR);

  return ret;
}


// ...

  if (input_file == NULL)
    {
      input_file = _("standard input");
      set_fd_flags (STDIN_FILENO, input_flags, input_file);
    }
  else
    {
      if (ifd_reopen (STDIN_FILENO, input_file, O_RDONLY | input_flags, 0) < 0)
        die (EXIT_FAILURE, errno, _("failed to open %s"),
             quoteaf (input_file));
    }

In the following code they use STDIN_FILENO (and STDOUT_FILENO) no matter if dd is told to read from stdin or an file. But the same could have been achieved by simply storing the fd in some variable and use this. Using 2 additional syscalls and a bunch of code just to save 1 int seems not reasonable. So what's the benefit or reusing the fd's of stdin/stdout?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Nudin
  • 351
  • 2
  • 11
  • 3
    Without asking the authors of the code, all we can do is guess. And one such guess is that it's simple thing that when added meant that other parts of the code didn't have to be rewritten. Add the duplication, keep major part of the code as it was. – Some programmer dude Oct 07 '18 at 14:32
  • 1
    It is/was a common unix idiom to write filters that read from stdin and wrote to stdout. The main() would then manipulate the fd’s based on the command line processing. What it lost in explicitness it gained in brevity, since you didn’t have to pass dummy fd/fps around. – mevets Oct 07 '18 at 16:35

0 Answers0