src/server/safs/service.c

changeset 428
ab58e46b50a5
parent 415
d938228c382e
child 429
25c8e8021156
equal deleted inserted replaced
427:a327cb6cc868 428:ab58e46b50a5
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <sys/file.h> 30 #include <sys/file.h>
31 #include <sys/stat.h> 31 #include <sys/stat.h>
32 32
33 #include "service.h" 33 #include "service.h"
34 #include "objecttype.h"
34 #include "../util/io.h" 35 #include "../util/io.h"
35 #include "../util/pblock.h" 36 #include "../util/pblock.h"
36 #include "../util/util.h" 37 #include "../util/util.h"
37 #include "../daemon/protocol.h" 38 #include "../daemon/protocol.h"
38 #include "../daemon/vfs.h" 39 #include "../daemon/vfs.h"
49 * 50 *
50 * adds content-length header 51 * adds content-length header
51 * 52 *
52 * return the opened file 53 * return the opened file
53 */ 54 */
54 SYS_FILE prepare_service_file(Session *sn, Request *rq, VFSContext *vfs, struct stat *s) { 55 SYS_FILE prepare_service_file(Session *sn, Request *rq, VFSContext *vfs, struct stat *s, int *ret) {
55 char *path = pblock_findkeyval(pb_key_path, rq->vars); 56 char *path = pblock_findkeyval(pb_key_path, rq->vars);
56 57
57 // open the file 58 // open the file
58 SYS_FILE fd = vfs_open(vfs, path, O_RDONLY); 59 SYS_FILE fd = vfs_open(vfs, path, O_RDONLY);
59 if(!fd) { 60 if(!fd) {
68 return NULL; 69 return NULL;
69 } 70 }
70 71
71 // check if the file is a directory 72 // check if the file is a directory
72 if(S_ISDIR(s->st_mode)) { 73 if(S_ISDIR(s->st_mode)) {
73 pblock_nvinsert("content-length", "0", rq->srvhdrs);
74 pblock_removekey(pb_key_content_type, rq->srvhdrs); 74 pblock_removekey(pb_key_content_type, rq->srvhdrs);
75 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); 75 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
76 size_t urilen = strlen(uri); 76 size_t urilen = strlen(uri);
77 char *location = pool_malloc(sn->pool, urilen + 2); 77 if(urilen > 0 && uri[urilen-1] != '/') {
78 memcpy(location, uri, urilen); 78 pblock_nvinsert("content-length", "0", rq->srvhdrs);
79 location[urilen] = '/'; 79 char *location = pool_malloc(sn->pool, urilen + 2);
80 location[urilen+1] = '\0'; 80 memcpy(location, uri, urilen);
81 pblock_kvinsert(pb_key_location, location, urilen + 1, rq->srvhdrs); 81 location[urilen] = '/';
82 protocol_status(sn, rq, 302, NULL); 82 location[urilen+1] = '\0';
83 http_start_response(sn, rq); 83 pblock_kvinsert(pb_key_location, location, urilen + 1, rq->srvhdrs);
84 protocol_status(sn, rq, 302, NULL);
85 http_start_response(sn, rq);
86 *ret = REQ_PROCEED;
87 } else {
88 // set content-type to "internal/directory" and ret to REQ_NOACTION
89 // maybe a SAF will respond to that
90 pblock_kvinsert(
91 pb_key_content_type,
92 OBJTYPE_INTERNAL_DIRECTORY,
93 sizeof(OBJTYPE_INTERNAL_DIRECTORY)-1,
94 rq->srvhdrs);
95 *ret = REQ_NOACTION;
96 }
84 vfs_close(fd); 97 vfs_close(fd);
85 return NULL; 98 return NULL;
86 } 99 }
87 100
88 // sets last-modified, content-length and checks conditions 101 // sets last-modified, content-length and checks conditions
89 const char *etag = vfs_getetag(fd); // optionally, get etag from file 102 const char *etag = vfs_getetag(fd); // optionally, get etag from file
90 if(http_set_finfo_etag(sn, rq, s, etag) != REQ_PROCEED) { 103 if(http_set_finfo_etag(sn, rq, s, etag) != REQ_PROCEED) {
91 vfs_close(fd); 104 vfs_close(fd);
105 *ret = REQ_ABORTED;
92 return NULL; 106 return NULL;
93 } 107 }
94 108
95 // TODO: check if vfs can seek 109 // TODO: check if vfs can seek
96 pblock_kvinsert(pb_key_accept_ranges, "bytes", 5, rq->srvhdrs); 110 pblock_kvinsert(pb_key_accept_ranges, "bytes", 5, rq->srvhdrs);
572 pool_free(sn->pool, r); 586 pool_free(sn->pool, r);
573 return 0; 587 return 0;
574 } 588 }
575 589
576 int send_file(pblock *pb, Session *sn, Request *rq) { 590 int send_file(pblock *pb, Session *sn, Request *rq) {
591 int ret = REQ_NOACTION;
577 struct stat s; 592 struct stat s;
578 VFSContext *vfs = vfs_request_context(sn, rq); 593 VFSContext *vfs = vfs_request_context(sn, rq);
579 SYS_FILE fd = prepare_service_file(sn, rq, vfs, &s); 594 SYS_FILE fd = prepare_service_file(sn, rq, vfs, &s, &ret);
580 if(!fd) { 595 if(!fd) {
581 // if an error occurs, prepare_service_file sets the http status code 596 // if an error occurs, prepare_service_file sets the http status code
582 // we can just return REQ_ABORTED 597 // in case fd is a directory and the uri already ends with an trailing
583 return REQ_ABORTED; 598 // '/', ret is set to REQ_NOACTION
599 return ret;
584 } 600 }
585 601
586 // get and validate range header 602 // get and validate range header
587 char *range_header = pblock_findkeyval(pb_key_range, rq->headers); 603 char *range_header = pblock_findkeyval(pb_key_range, rq->headers);
588 HttpRange *range = NULL; 604 HttpRange *range = NULL;
635 } else { 651 } else {
636 offset = 0; 652 offset = 0;
637 length = s.st_size; 653 length = s.st_size;
638 } 654 }
639 655
640 int ret = REQ_NOACTION;
641 if(single_range) { 656 if(single_range) {
642 // send response header 657 // send response header
643 http_start_response(sn, rq); 658 http_start_response(sn, rq);
644 // send content 659 // send content
645 // TODO: fix: send_range_aio is unstable #96 660 // TODO: fix: send_range_aio is unstable #96

mercurial