Last active
August 28, 2019 22:54
-
-
Save voutilad/c18379d94276183603a57ca8e762c10f to your computer and use it in GitHub Desktop.
A quick/crappy sendfile(2) stub example for OpenBSD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2019 Dave Voutila <[email protected]> | |
// Under no circumstances should you consider this safe/correct code. | |
// Use at your own risk. | |
// | |
// Consider it under ISC license. | |
#include <stdio.h> | |
#include <fcntl.h> | |
#include <err.h> | |
#include <netdb.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#define HOST "127.0.0.1" | |
#define PORT "9999" | |
#define BUF_SIZE 512 | |
int sendfile (int fd, int s, off_t offset, size_t nbytes, void *hdr, off_t *sbytes, int flags) { | |
int cnt = 0; | |
ssize_t r = 0; | |
off_t pos = offset; | |
char buf[BUF_SIZE]; | |
memset(&buf, 0, BUF_SIZE); | |
while ((r = pread(fd, &buf, BUF_SIZE, pos)) != -1) { | |
pos += r; | |
printf("[[ read %ld bytes from file ]]\n", r); | |
if (r == 0) { | |
printf("[done reading from file]\n"); | |
break; | |
} | |
printf("[[ sending %ld via socket ]]\n", r); | |
ssize_t sock_result = send(s, &buf, r, flags); | |
if (sock_result == -1) { | |
printf("[err sending to socket]\n"); | |
return -1; | |
} | |
if (sbytes != NULL) { | |
*sbytes += sock_result; | |
} | |
memset(&buf, 0, BUF_SIZE); | |
cnt++; | |
printf("[[ iteration %d ]]\n", cnt); | |
} | |
return 0; | |
} | |
int main (int argc, char **argv) { | |
int r = 0; | |
off_t skip = 0; | |
if (argc < 2) { | |
printf("Usage: sendfile [file] [skip=0]\n"); | |
return 0; | |
} | |
char *file = argv[1]; | |
if (argc > 2) { | |
skip = strtonum(argv[2], 0, INT32_MAX, NULL); | |
printf("skipping %lld bytes...", skip); | |
} | |
printf("opening %s...\n", file); | |
int fd = open(file, O_RDONLY); | |
if (fd == -1) { | |
err(1, "can't open %s", file); | |
} | |
int s = socket(AF_INET, SOCK_STREAM, 0); | |
if (s == -1) { | |
close(fd); | |
err(2, "can't create socket"); | |
} | |
printf("connecting to %s:%s...\n", HOST, PORT); | |
struct addrinfo *addr; | |
if ((r = getaddrinfo(HOST, PORT, NULL, &addr)) != 0) { | |
close(fd); | |
err(3, "getaddrinfo failed for %s:%s", HOST, PORT); | |
} | |
if ((r = connect(s, addr->ai_addr, addr->ai_addrlen)) == -1) { | |
close(fd); | |
err(4, "failed to connect to %s:%s", HOST, PORT); | |
} | |
printf("connected.\n"); | |
printf("sending file...\n"); | |
off_t sent = 0; | |
if ((r = sendfile(fd, s, skip, 0, NULL, &sent, 0)) == -1) { | |
close(s); | |
close(fd); | |
err(5, "failed to send file"); | |
} else { | |
printf("sent %lld bytes.\n", sent); | |
} | |
close(s); | |
close(fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment