Skip to content

Instantly share code, notes, and snippets.

@metadaddy
Forked from anonymous/server.c
Created July 23, 2012 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save metadaddy/3165080 to your computer and use it in GitHub Desktop.
Save metadaddy/3165080 to your computer and use it in GitHub Desktop.
sendfile
/* receive e-mail */
void receive_mail(char *filename, int sock_fd)
{
/* file descriptor for destination file */
int destination_fd;
/* byte offset used by sendfile */
off_t offset = 0;
size_t total_bytes_sent = 0;
struct stat stat_buf;
/* open destination file */
destination_fd = open(filename, O_WRONLY | O_CREAT);
/* checking for "open" errors */
if (destination_fd < 0)
{ exit(EXIT_FAILURE); }
fstat(destination_fd, &stat_buf);
(void)fprintf(stdout, "File size: %jd\n", (intmax_t)stat_buf.st_size);
/* receive file */
total_bytes_sent = do_recvfile(1, sock_fd, offset, /* HERE I NEED THE FILE SIZE: ON SERVER-SIDE IT IS UNKNOWN */);
(void)fprintf(stdout, "Total bytes sent: %d\n", total_bytes_sent);
close(destination_fd);
}
/* receive file */
ssize_t do_recvfile(int output_fd, int sock_fd, off_t offset, size_t count)
{
ssize_t bytes;
ssize_t bytes_sent;
ssize_t bytes_in_pipe;
size_t total_bytes_sent = 0;
/* pipe */
int pipefd[2];
/* setup the pipe */
if (pipe(pipefd) < 0)
{
err_num = errno;
(void)fprintf(stderr, "\"pipe\" error:%s\n", strerror(err_num));
exit(EXIT_FAILURE);
}
/* splice the data from "sock_fd" into the pipe */
while (total_bytes_sent < count)
{
if ((bytes_sent = splice(sock_fd, NULL, pipefd[1], NULL,
MIN(count - total_bytes_sent, 16384),
SPLICE_F_MORE | SPLICE_F_MOVE)) <= 0) {
if (errno == EINTR || errno == EAGAIN)
{ continue; }
err_num = errno;
(void)fprintf(stderr, "\"splice\" error (bytes_sent): %s\n", strerror(err_num));
return (-1);
}
bytes_in_pipe = bytes_sent;
while (bytes_in_pipe > 0)
{
if ((bytes = splice(pipefd[0], NULL, output_fd, &offset, bytes_in_pipe, SPLICE_F_MORE | SPLICE_F_MOVE)) <= 0)
{
if (errno == EINTR || errno == EAGAIN)
{ continue; }
err_num = errno;
(void)fprintf(stderr, "\"splice\" error (bytes): %s\n", strerror(err_num));
return (-1);
}
bytes_in_pipe -= bytes;
}
total_bytes_sent += bytes_sent;
}
return (total_bytes_sent);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment