#include #include #include #include #include #include #include #include #include #include #include #include #include static void usage(void) { fprintf(stderr, "Usage: sf_copy \n"); exit(1); } static int parent(int sockfd, int filefd) { off_t sent; int rc; rc = sendfile(filefd, sockfd, 0, 0, NULL, &sent, SF_NOCACHE); if (rc < 0) warn("sendfile"); return (rc); } static int child_null(int sockfd) { static unsigned char junk[1 << 20]; off_t off = 0; int ret; for (;;) { ret = read(sockfd, junk, sizeof(junk)); if (ret < 0) { if (errno == ECONNRESET) break; err(1, "read, off=%jd", off); } off += ret; if (ret == 0) break; } return 0; } int main(int argc, const char **argv) { int error, ifd, sockfds[2], status; pid_t child; if (argc != 2) usage(); ifd = open(argv[1], O_RDONLY); if (ifd == -1) err(errno, "open(%s)", argv[1]); if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds) == -1) err(errno, "socketpair"); child = fork(); if (child == -1) err(1, "fork"); if (child > 0) { close(sockfds[0]); error = parent(sockfds[1], ifd); if (error) err(errno, "parent"); /* close writer socket now */ close(sockfds[1]); close(ifd); waitpid(child, &status, 0); if (error == -1) err(errno, "waitpid"); error = WEXITSTATUS(status); } else { close(ifd); close(sockfds[1]); child_null(sockfds[0]); close(sockfds[0]); } return (error); }