Why is Linux's sendfile() incompatible with /dev/zero?

Viewed 99

why is sendfile incompatible with /dev/zero ? why does this code

#include <iostream>
#include <sys/sendfile.h>
#include <fcntl.h>
#include <string.h>
int main(){
    int f1 = fileno(tmpfile());
    int devzero = open("/dev/zero", O_RDONLY);
    if(f1 < 0 || devzero < 0){
        throw std::runtime_error("Failed to open files");
    }
    ssize_t sent = sendfile(f1, devzero, 0, 1);
    std::cout << "sent " << sent << " bytes. errno " << errno << " strerror " << strerror(errno) << std::endl;
    return 0;
}

consistently output

sent -1 bytes. errno 22 strerror Invalid argument

?

1 Answers

/dev/zero is a special file. It doesn’t represent an on disk file.

From sendfile documentation:

The in_fd argument must correspond to a file which supports mmap(2)-like operations (i.e., it cannot be a socket).
...
EINVAL Descriptor is not valid or locked, or an mmap(2)-like operation is not available for in_fd, or count is negative.
EINVAL out_fd has the O_APPEND flag set.  This is not currently supported by sendfile().

These section of kernel source is reporting the error:

if (unlikely(out->f_flags & O_APPEND))
        return -EINVAL;
ret = rw_verify_area(WRITE, out, opos, len);

I performed some testing. Reading from a tmpfile(), a regular file, and /dev/zero works. Writing to a regular file works, but writing to /dev/zero fails one of those checks (O_APPEND permissions or rw_verify_area() ).

Related