src/server/util/io.c

changeset 111
c93be34fde76
parent 106
b122f34ddc80
child 112
b962d83124bc
equal deleted inserted replaced
109:8a0a7754f123 111:c93be34fde76
32 32
33 #include <unistd.h> 33 #include <unistd.h>
34 #include <stdlib.h> 34 #include <stdlib.h>
35 #include <sys/uio.h> 35 #include <sys/uio.h>
36 #include <sys/uio.h> 36 #include <sys/uio.h>
37
37 #ifndef BSD 38 #ifndef BSD
38 #include <sys/sendfile.h> 39 #include <sys/sendfile.h>
39 #endif 40 #else
41 #if defined(__NetBSD__) || defined(__OpenBSD__)
42 #define WS_NO_SENDFILE
43 #define net_stream_sendfile net_fallback_sendfile
44 #endif
45 #endif
46
40 #include <limits.h> /* asprintf */ 47 #include <limits.h> /* asprintf */
41 48
42 #include "../daemon/vfs.h" 49 #include "../daemon/vfs.h"
43 #include "io.h" 50 #include "io.h"
44 #include "pool.h" 51 #include "pool.h"
143 ssize_t r = read(st->fd, buf, nbytes); 150 ssize_t r = read(st->fd, buf, nbytes);
144 st->read += r; 151 st->read += r;
145 return r; 152 return r;
146 } 153 }
147 154
155 #ifndef WS_NO_SENDFILE
148 ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) { 156 ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) {
149 ssize_t ret = 0; 157 ssize_t ret = 0;
150 off_t fileoffset = sfd->offset; 158 off_t fileoffset = sfd->offset;
151 if(sfd->fd->fd != -1) { 159 if(sfd->fd->fd != -1) {
152 #ifdef BSD 160 #ifdef BSD
189 fprintf(stderr, "sendfile not implemented for SYS_FILE\n"); 197 fprintf(stderr, "sendfile not implemented for SYS_FILE\n");
190 } 198 }
191 199
192 return ret; 200 return ret;
193 } 201 }
202 #endif
194 203
195 void net_stream_close(NetIOStream *st) { 204 void net_stream_close(NetIOStream *st) {
196 close(st->fd); 205 close(st->fd);
197 } 206 }
198 207
283 return IO_ERROR; 292 return IO_ERROR;
284 } 293 }
285 } else { 294 } else {
286 // stream/file does not support sendfile 295 // stream/file does not support sendfile
287 // do regular copy 296 // do regular copy
288 char *buf = malloc(4096); 297 return net_fallback_sendfile(fd, sfd);
289 if(!buf) {
290 // TODO: out of memory error
291 return IO_ERROR;
292 }
293 char *header = (char*)sfd->header;
294 int hlen = sfd->hlen;
295 char *trailer = (char*)sfd->trailer;
296 int tlen = sfd->tlen;
297 if(header == NULL) {
298 hlen = 0;
299 }
300 if(trailer == NULL) {
301 tlen = 0;
302 }
303
304 ssize_t r;
305 while(hlen > 0) {
306 r = out->st.write(fd, header, hlen);
307 header += r;
308 hlen -= r;
309 if(r <= 0) {
310 free(buf);
311 return IO_ERROR;
312 }
313 }
314
315 if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) {
316 free(buf);
317 return IO_ERROR;
318 }
319
320 size_t length = sfd->len;
321 while(length > 0) {
322 if((r = system_fread(sfd->fd, buf, 4096)) <= 0) {
323 break;
324 }
325 char *write_buf = buf;
326 while(r > 0) {
327 ssize_t w = out->st.write(fd, write_buf, r);
328 r -= w;
329 length -= w;
330 write_buf += w;
331 }
332 }
333 free(buf);
334 if(length > 0) {
335 return IO_ERROR;
336 }
337
338 while(tlen > 0) {
339 r = out->st.write(fd, trailer, tlen);
340 trailer += r;
341 tlen -= r;
342 if(r <= 0) {
343 return IO_ERROR;
344 }
345 }
346
347 return sfd->hlen + sfd->len + sfd->tlen;
348 } 298 }
349 return IO_ERROR; 299 return IO_ERROR;
350 } 300 }
351 301
352 int net_flush(SYS_NETFD sd) { 302 int net_flush(SYS_NETFD sd) {
358 ((IOStream*)fd)->close(fd); 308 ((IOStream*)fd)->close(fd);
359 } 309 }
360 310
361 void net_finish(SYS_NETFD fd) { 311 void net_finish(SYS_NETFD fd) {
362 ((IOStream*)fd)->finish(fd); 312 ((IOStream*)fd)->finish(fd);
313 }
314
315
316 ssize_t net_fallback_sendfile(NetIOStream *st, sendfiledata *sfd) {
317 SYS_NETFD fd = st;
318
319 char *buf = malloc(4096);
320 if(!buf) {
321 // TODO: out of memory error
322 return IO_ERROR;
323 }
324 char *header = (char*)sfd->header;
325 int hlen = sfd->hlen;
326 char *trailer = (char*)sfd->trailer;
327 int tlen = sfd->tlen;
328 if(header == NULL) {
329 hlen = 0;
330 }
331 if(trailer == NULL) {
332 tlen = 0;
333 }
334
335 ssize_t r;
336 while(hlen > 0) {
337 r = st->st.write(fd, header, hlen);
338 header += r;
339 hlen -= r;
340 if(r <= 0) {
341 free(buf);
342 return IO_ERROR;
343 }
344 }
345
346 if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) {
347 free(buf);
348 return IO_ERROR;
349 }
350
351 size_t length = sfd->len;
352 while(length > 0) {
353 if((r = system_fread(sfd->fd, buf, 4096)) <= 0) {
354 break;
355 }
356 char *write_buf = buf;
357 while(r > 0) {
358 ssize_t w = st->st.write(fd, write_buf, r);
359 r -= w;
360 length -= w;
361 write_buf += w;
362 }
363 }
364 free(buf);
365 if(length > 0) {
366 return IO_ERROR;
367 }
368
369 while(tlen > 0) {
370 r = st->st.write(fd, trailer, tlen);
371 trailer += r;
372 tlen -= r;
373 if(r <= 0) {
374 return IO_ERROR;
375 }
376 }
377
378 return sfd->hlen + sfd->len + sfd->tlen;
363 } 379 }
364 380
365 381
366 /* iovec buffer */ 382 /* iovec buffer */
367 iovec_buf_t *iovec_buf_create(pool_handle_t *pool) { 383 iovec_buf_t *iovec_buf_create(pool_handle_t *pool) {

mercurial