Skip to content

Instantly share code, notes, and snippets.

@voutilad
Last active August 28, 2019 22:54
Show Gist options
  • Save voutilad/c18379d94276183603a57ca8e762c10f to your computer and use it in GitHub Desktop.
Save voutilad/c18379d94276183603a57ca8e762c10f to your computer and use it in GitHub Desktop.
A quick/crappy sendfile(2) stub example for OpenBSD
// 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