FileRecord *Dir_find_file(bstring path, bstring default_type) { FileRecord *fr = calloc(sizeof(FileRecord), 1); const char *p = bdata(path); check_mem(fr); // We set the number of users here. If we cache it, we can add one later fr->users = 1; int rc = stat(p, &fr->sb); check(rc == 0, "File stat failed: %s", bdata(path)); if(S_ISDIR(fr->sb.st_mode)) { fr->full_path = path; fr->is_dir = 1; return fr; } fr->fd = open(p, O_RDONLY); check(fr->fd >= 0, "Failed to open file but stat worked: %s", bdata(path)); fr->loaded = time(NULL); fr->last_mod = bStrfTime(RFC_822_TIME, gmtime(&fr->sb.st_mtime)); check(fr->last_mod, "Failed to format last modified time."); // TODO: get this from a configuration fr->content_type = MIME_match_ext(path, default_type); check(fr->content_type, "Should always get a content type back."); // we own this now, not the caller fr->full_path = path; time_t now = time(NULL); fr->date = bStrfTime(RFC_822_TIME, gmtime(&now)); fr->etag = bformat("%x-%x", fr->sb.st_mtime, fr->sb.st_size); fr->header = bformat(RESPONSE_FORMAT, bdata(fr->date), bdata(fr->content_type), fr->sb.st_size, bdata(fr->last_mod), bdata(fr->etag)); check(fr->header != NULL, "Failed to create response header."); return fr; error: FileRecord_destroy(fr); return NULL; }
void FileRecord_release(FileRecord *file) { if(file) { file->users--; check(file->users >= 0, "User count on file record somehow fell below 0"); if(file->users <= 0) FileRecord_destroy(file); } error: return; }
char *test_Dir_find_file() { bstring ctype = NULL; FileRecord *file = Dir_find_file(bfromcstr("tests/sample.json"), ctype = bfromcstr("text/plain")); mu_assert(file != NULL, "Failed to find the file."); FileRecord_destroy(file); bdestroy(ctype); return NULL; }
char *test_Dir_find_file_isdir(){ bstring ctype = NULL; FileRecord *file = Dir_find_file(bfromcstr("tests/"), ctype = bfromcstr("text/plain")); mu_assert(file != NULL, "Failed to find the directory."); mu_assert(file->is_dir == 1, "Did not recognized it's a directory"); FileRecord_destroy(file); bdestroy(ctype); return NULL; }