diff options
Diffstat (limited to 'download.c')
-rw-r--r-- | download.c | 136 |
1 files changed, 91 insertions, 45 deletions
@@ -76,94 +76,140 @@ build_download_url(struct kreq * r, struct file * file) } static char * -strsplit(char * str, char c) { - char *right, *result; - size_t right_len; +strsplit(char *str, char c) +{ + char *right, *result; + size_t right_len; right = strrchr(str, c); - if(!right || right == str) + if (!right || right == str) return NULL; - // move right part to new buffer + /* move right part to new buffer */ right_len = strlen(right); result = malloc(sizeof(char) * right_len); - if(result == NULL) + if (result == NULL) return NULL; - if(strlcpy(result, right + 1, right_len) >= right_len) { + if (strlcpy(result, right + 1, right_len) >= right_len) { free(result); return NULL; } - - // remove right part from src buffer + /* remove right part from src buffer */ *right = '\0'; return result; } -void +struct http_ret download(struct kreq * r) { char *file_name; void *buffer; - struct file* f; - int fd; + struct file *f; + int fd; char file_path[PATH_MAX], request_path[PATH_MAX]; size_t path_size; + struct http_ret ret; + + /* initialize empty file and return struct to success */ + f = NULL; + ret = (struct http_ret) { + KHTTP_200, "" + }; /* check that the requested URL can be safely processed */ - if (strlen(r->path) == 0 || !check_request_path(r->path, r->suffix)) - http_exit(r, KHTTP_400, "download: invalid request path"); - - /* build requested file path */ - if(strlen(r->suffix) > 0) { - /* request with suffix */ - if(snprintf(request_path, sizeof(request_path), "%s.%s", r->path, r->suffix) - >= (int) sizeof(request_path)) - http_exit(r, KHTTP_414, NULL); + if (strlen(r->path) == 0 || !check_request_path(r->path, r->suffix)) { + ret = (struct http_ret) { + KHTTP_400, + "download: invalid request path" + }; + goto end; } - else { - if(snprintf(request_path, sizeof(request_path), "%s", r->path) >= (int) sizeof(request_path)) - http_exit(r, KHTTP_414, NULL); + /* build requested file path, with suffix or without */ + if (strlen(r->suffix) > 0) { + if (snprintf(request_path, sizeof(request_path), "%s.%s", r->path, r->suffix) + >= (int) sizeof(request_path)) { + ret = (struct http_ret) { + KHTTP_414, + "download: request too long" + }; + goto end; + } + } else { + if (snprintf(request_path, sizeof(request_path), "%s", r->path) + >= (int) sizeof(request_path)) { + ret = (struct http_ret) { + KHTTP_414, + "download: request too long" + }; + goto end; + } } path_size = url_build(file_path, PATH_MAX, DATA_DIR, request_path, NULL); - if (path_size == 0) - http_exit(r, KHTTP_404, "download: unable to build file path"); - if (path_size >= PATH_MAX) - http_exit(r, KHTTP_414, NULL); - + if (path_size == 0) { + ret = (struct http_ret) { + KHTTP_404, + "download: unable to build file path" + }; + goto end; + } + if (path_size >= PATH_MAX) { + ret = (struct http_ret) { + KHTTP_414, + "download: request too long" + }; + goto end; + } /* build file metadata */ file_name = strsplit(request_path, '/'); - if(file_name == NULL) - f = file_new("/", 1, request_path, strlen(request_path)); /* ROOT file */ + if (file_name == NULL) + f = file_new("/", 1, request_path, strlen(request_path)); /* ROOT file */ else { f = file_new(request_path, strlen(request_path), file_name, - strlen(file_name)); - free(file_name); /* copied in file_new */ + strlen(file_name)); + free(file_name);/* copied in file_new */ + } + if (f == NULL) { + ret = (struct http_ret) { + KHTTP_404, + "download: file metadata failure" + }; + goto end; } - if(f == NULL) - http_exit(r, KHTTP_404, "download: file metadata failure"); - /* memory map the file */ fd = open(file_path, O_RDONLY); - if(fd < 0) - http_exit(r, KHTTP_404, "download: unable to open file"); + if (fd < 0) { + ret = (struct http_ret) { + KHTTP_404, + "download: unable to open file" + }; + goto end; + } /* mmap does not work with empty file: st_size = 0 */ - if(f->size > 0) { + if (f->size > 0) { buffer = mmap(NULL, f->size, PROT_READ, MAP_PRIVATE, fd, 0); - if (buffer == MAP_FAILED) - http_exit(r, KHTTP_500, "download: mmap failed"); + if (buffer == MAP_FAILED) { + ret = (struct http_ret) { + KHTTP_500, + "download: mmap failed" + }; + goto end; + } } - /* write the file */ http_open_file(r, KHTTP_200, f); - if(f->size > 0) + if (f->size > 0) K_OK(khttp_write(r, (const char *) buffer, f->size), r); /* cleanup */ - if(f->size > 0) +end: + if (f != NULL && f->size > 0) munmap(buffer, f->size); - free(f); + if (f != NULL) + free(f); + + return ret; } |