Home > Blockchain >  | vs < for stdin and stdout with splice, pipe and tee command in C
| vs < for stdin and stdout with splice, pipe and tee command in C

Time:04-15

#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h> 
#include <stdio.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
int main(int argc, char ** argv) {
    int fd[2];
    int len,slen,len_out,slen_out;
    pipe(fd);
  
    int f=open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);

    len=tee(STDIN_FILENO,fd[1],INT_MAX,SPLICE_F_MOVE);
    
    while (len > 0) {
        slen = splice(fd[0], NULL, f, NULL, len, SPLICE_F_MOVE);
        len -= slen;
        if(slen==0)
            break;
    }   

    len_out = tee(STDIN_FILENO,fd[1],INT_MAX,SPLICE_F_MOVE);    

    while (len_out > 0) {
        slen_out = splice(fd[0], NULL, STDOUT_FILENO, NULL, len_out, SPLICE_F_MOVE);
            len_out -= slen_out;
            if(slen_out==0)
                break;
    }

    close(fd[1]);
    close(fd[0]);
    close(f);  
    
    return 0;
}

When I run my program with a pipe ex: cat test.txt| ./a.out result.txt The content from test.txt goes into result.txt

But with the other method, ex: ./a.out result.txt <test.txt nothing happens. Isn't it suppose to act the same ?

Also, when I splice to the STDOUT_FILENO, it never print on the standard output, and I do not understand why.

Thank you for your help

CodePudding user response:

The two methods are not equivalent:

  • cat in.txt | will actually create a pipe to feed your program
  • < in.txt will just open the given file and serve it a fd 0

On second case, tee returns -1, and perror complains about an invalid argument.

You can check the nature of fd 0 using fstat and checking the st_mode value:

    struct stat statbuf;
    fstat(STDIN_FILENO, &statbuf);
    
    if (statbuf.st_mode & S_IFREG) 
        printf("regular file");
    
    if (statbuf.st_mode & S_IFIFO) 
        printf("pipe");

  • Related