#include #include #include #include #include #include #include #include #include #include #define _GNU_SOURCE #include #ifndef F_GETPIPE_SZ # define F_GETPIPE_SZ 1032 /* The Linux number for the option */ #endif const char *this_name = "agent-fifo"; static void usage(void) { printf("usage: %s dev bigfile\n" "\n",this_name); exit(-1); } static void __vdie(const char *fmt, va_list ap, int err) { int ret = errno; const char *p = this_name; if (err && errno) perror(p); else ret = -1; fprintf(stderr, " "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); exit(ret); } void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); __vdie(fmt, ap, 0); va_end(ap); } void pdie(const char *fmt, ...) { va_list ap; va_start(ap, fmt); __vdie(fmt, ap, 1); va_end(ap); } static unsigned long long time() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; } static void print_time(unsigned long long time) { unsigned long long seconds; unsigned long long usecs; seconds = time / 1000000; usecs = time - (seconds * 1000000); printf("time: %llu.%06llu\n", seconds, usecs); } int main(int argc, char *argv[]) { unsigned long long start; unsigned long long end; struct stat st; off_t size; char *file; char *port; int page_size; int pipe_size; int brass[2]; int ret; int cfd; int fd; if (argc < 3) usage(); port = argv[1]; file = argv[2]; fd = open(file, O_RDONLY); if (fd < 0) pdie("Opening %s", file); if (pipe(brass) < 0) pdie("pipe"); if (fstat(fd, &st) < 0) pdie("stat %s", file); size = st.st_size; if (size < 1) die("%s must have size found by stat"); page_size = getpagesize(); if (page_size <= 0) pdie("getting page size"); ret = fcntl(brass[0], F_GETPIPE_SZ, &pipe_size); if (ret < 0 || !pipe_size) pipe_size = page_size; start = time(); cfd = open(port, O_WRONLY); if (cfd < 0) pdie("Writing to %s", argv[2]); start = time(); do { if (size < page_size) { char buf[page_size]; ret = read(fd, buf, size); if (ret < 0) pdie("reading %s", file); size -= ret; write(cfd, buf, ret); continue; } if (size < pipe_size) pipe_size = size & ~(page_size - 1); ret = splice(fd, NULL, brass[1], NULL, pipe_size, 1 /* SPLICE_F_MOVE */); if (ret < 0) pdie("splice read of %s", file); size -= ret; ret = splice(brass[0], NULL, cfd, NULL, pipe_size, 3 /* and NON_BLOCK */); if (ret < 0) pdie("splice write"); } while (size); end = time(); print_time(end - start); exit(0); }