Example #1
0
int async_fs_sync_dirname(const char* path) {
	async_pool_enter(NULL);
	int rc = async_fs_open_dirname(path, O_RDONLY, 0000);
	if(rc >= 0) {
		uv_file parent = rc;
		rc = async_fs_fdatasync(parent);
		async_fs_close(parent); parent = -1;
	}
	async_pool_leave(NULL);
	return rc;
}
Example #2
0
int SLNSubmissionEnd(SLNSubmissionRef const sub) {
	if(!sub) return 0;
	if(sub->size <= 0) return UV_EINVAL;
	assert(sub->tmppath);
	assert(sub->tmpfile >= 0);
	assert(sub->type);

	sub->URIs = SLNHasherEnd(sub->hasher);
	sub->internalHash = strdup(SLNHasherGetInternalHash(sub->hasher));
	SLNHasherFree(&sub->hasher);
	if(!sub->URIs || !sub->internalHash) return UV_ENOMEM;

	SLNRepoRef const repo = SLNSubmissionGetRepo(sub);
	str_t *internalPath = NULL;
	bool worker = false;
	int rc = 0;

	rc = verify(sub);
	if(rc < 0) goto cleanup;

	internalPath = SLNRepoCopyInternalPath(repo, sub->internalHash);
	if(!internalPath) rc = UV_ENOMEM;
	if(rc < 0) goto cleanup;

	async_pool_enter(NULL); worker = true;

	rc = async_fs_fdatasync(sub->tmpfile);
	if(rc < 0) goto cleanup;

	// We use link(2) rather than rename(2) because link gives an error
	// if there's a name collision, rather than overwriting. We want to
	// keep the oldest file for any given hash, rather than the newest.
	rc = async_fs_link_mkdirp(sub->tmppath, internalPath);
	if(UV_EEXIST == rc) {
		rc = 0;
		goto cleanup;
	}
	if(rc < 0) {
		alogf("SLNSubmission couldn't move '%s' to '%s' (%s)\n", sub->tmppath, internalPath, sln_strerror(rc));
		goto cleanup;
	}

	rc = async_fs_sync_dirname(internalPath);

cleanup:
	if(worker) { async_pool_leave(NULL); worker = false; }
	FREE(&internalPath);

	async_fs_unlink(sub->tmppath);
	FREE(&sub->tmppath);
	return rc;
}
Example #3
0
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;
}
Example #4
0
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;
}