public
Created — forked from /server.c

sendfile

  • Download Gist
server.c
C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
 
/* 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);
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.