int SLNSubmissionCreate(SLNSessionRef const session, strarg_t const knownURI, SLNSubmissionRef *const out) { assert(out); if(!SLNSessionHasPermission(session, SLN_WRONLY)) return UV_EACCES; SLNSubmissionRef sub = calloc(1, sizeof(struct SLNSubmission)); if(!sub) return UV_ENOMEM; int rc = 0; sub->session = session; if(knownURI) { sub->knownURI = strdup(knownURI); if(!sub->knownURI) rc = UV_ENOMEM; if(rc < 0) goto cleanup; } sub->type = NULL; sub->tmppath = SLNRepoCopyTempPath(SLNSessionGetRepo(session)); if(!sub->tmppath) rc = UV_ENOMEM; if(rc < 0) goto cleanup; rc = async_fs_open_mkdirp(sub->tmppath, O_CREAT | O_EXCL | O_RDWR, 0400); if(rc < 0) goto cleanup; sub->tmpfile = rc; sub->hasher = SLNHasherCreate(sub->type); if(!sub->hasher) rc = UV_ENOMEM; if(rc < 0) goto cleanup; sub->metaFileID = 0; *out = sub; sub = NULL; cleanup: SLNSubmissionFree(&sub); return rc; }
int BlogGeneric(BlogRef const blog, SLNSessionRef const session, strarg_t const htmlpath, strarg_t const URI, SLNFileInfo const *const src) { str_t *tmp = NULL; uv_file html = -1; int rc = 0; tmp = SLNRepoCopyTempPath(blog->repo); if(!tmp) rc = UV_ENOMEM; if(rc < 0) goto cleanup; rc = async_fs_open_mkdirp(tmp, O_CREAT | O_EXCL | O_WRONLY, 0400); if(rc < 0) goto cleanup; html = rc; preview_state const state = { .blog = blog, .session = session, .fileURI = URI, }; rc = TemplateWriteFile(blog->preview, &preview_cbs, &state, html); if(rc < 0) goto cleanup; rc = async_fs_fdatasync(html); if(rc < 0) goto cleanup; rc = async_fs_link_mkdirp(tmp, htmlpath); if(rc < 0) goto cleanup; cleanup: async_fs_unlink(tmp); FREE(&tmp); if(html >= 0) { async_fs_close(html); html = -1; } assert(html < 0); return rc; }
static int convert(BlogRef const blog, SLNSessionRef const session, char const *const htmlpath, SLNSubmissionRef *const outmeta, strarg_t const URI, SLNFileInfo const *const src, BlogTypeCheck const types, BlogConverter const converter) { int rc = types(src->type); if(rc < 0) return UV_EINVAL; str_t *tmp = NULL; uv_file html = -1; uv_file file = -1; char const *buf = NULL; SLNSubmissionRef meta = NULL; yajl_gen json = NULL; tmp = SLNRepoCopyTempPath(blog->repo); if(!tmp) rc = UV_ENOMEM; if(rc < 0) goto cleanup; rc = async_fs_open_mkdirp(tmp, O_CREAT | O_EXCL | O_WRONLY, 0400); if(rc < 0) goto cleanup; html = rc; rc = async_fs_open(src->path, O_RDONLY, 0000); if(rc < 0) goto cleanup; file = rc; // We use size+1 to get nul-termination. Kind of a hack. buf = mmap(NULL, src->size+1, PROT_READ, MAP_SHARED, file, 0); if(MAP_FAILED == buf) rc = -errno; if(rc < 0) goto cleanup; if('\0' != buf[src->size]) rc = UV_EIO; // Slightly paranoid. if(rc < 0) goto cleanup; async_fs_close(file); file = -1; if(outmeta) { rc = SLNSubmissionCreate(session, NULL, URI, &meta); if(rc < 0) goto cleanup; rc = SLNSubmissionSetType(meta, SLN_META_TYPE); if(rc < 0) goto cleanup; } SLNSubmissionWrite(meta, (byte_t const *)URI, strlen(URI)); SLNSubmissionWrite(meta, (byte_t const *)STR_LEN("\n\n")); json = yajl_gen_alloc(NULL); if(!json) rc = UV_ENOMEM; if(rc < 0) goto cleanup; yajl_gen_config(json, yajl_gen_print_callback, (void (*)())SLNSubmissionWrite, meta); yajl_gen_config(json, yajl_gen_beautify, (int)true); async_pool_enter(NULL); yajl_gen_map_open(json); rc = converter(html, json, buf, src->size, src->type); yajl_gen_map_close(json); async_pool_leave(NULL); if(rc < 0) goto cleanup; rc = async_fs_fdatasync(html); if(rc < 0) goto cleanup; rc = async_fs_link_mkdirp(tmp, htmlpath); if(rc < 0) goto cleanup; rc = SLNSubmissionEnd(meta); if(rc < 0) goto cleanup; if(outmeta) { *outmeta = meta; meta = NULL; } cleanup: async_fs_unlink(tmp); FREE(&tmp); if(html >= 0) { async_fs_close(html); html = -1; } if(file >= 0) { async_fs_close(file); file = -1; } if(buf) { munmap((void *)buf, src->size+1); buf = NULL; } if(json) { yajl_gen_free(json); json = NULL; } SLNSubmissionFree(&meta); assert(html < 0); assert(file < 0); return rc; }