int EFSConfigurationCreate(uv_file const fd, EFSConfigurationRef *const out) { assert(out); if(fd < 0) return UV_EINVAL; EFSConfigurationRef conf = calloc(1, sizeof(struct EFSConfiguration)); if(!conf) return UV_ENOMEM; int rc = 0; uv_buf_t buf[1]; buf->base = malloc(BUF_LEN); if(!buf->base) { rc = UV_ENOMEM; goto cleanup; } buf->len = BUF_LEN; ssize_t len; int64_t pos = 0; for(;;) { len = async_fs_read(fd, buf, 1, pos); if(len < 0) { rc = len; goto cleanup; } } *out = conf; cleanup: if(rc < 0) EFSConfigurationFree(&conf); return rc; }
ssize_t async_fs_readall_simple(uv_file const file, uv_buf_t const *const buf) { async_pool_enter(NULL); size_t pos = 0; ssize_t rc; for(;;) { uv_buf_t b2 = uv_buf_init(buf->base+pos, buf->len-pos); rc = async_fs_read(file, &b2, 1, -1); if(rc < 0) break; if(0 == rc) { rc = pos; break; } pos += rc; if(pos >= buf->len) { rc = pos; break; } } async_pool_leave(NULL); return rc; }
int SLNSubmissionParseMetaFile(SLNSubmissionRef const sub, uint64_t const fileID, DB_txn *const txn, uint64_t *const out) { assert(out); if(!sub) return DB_EINVAL; if(!fileID) return DB_EINVAL; if(!txn) return DB_EINVAL; strarg_t const type = SLNSubmissionGetType(sub); if(!type) return 0; if(0 != strcasecmp(SLN_META_TYPE, type) && 0 != strcasecmp("text/x-sln-meta+json; charset=utf-8", type) && 0 != strcasecmp("text/efs-meta+json; charset=utf-8", type)) return 0; // TODO: Get rid of these obsolete types. uv_file const fd = SLNSubmissionGetFile(sub); if(fd < 0) return DB_EINVAL; int rc = 0; uv_buf_t buf[1] = {}; DB_txn *subtxn = NULL; parser_t ctx[1] = {}; yajl_handle parser = NULL; buf->base = malloc(BUF_LEN); if(!buf->base) { rc = DB_ENOMEM; goto cleanup; } buf->len = URI_MAX; int64_t pos = 0; ssize_t len = async_fs_read(fd, buf, 1, pos); if(len < 0) { fprintf(stderr, "Submission meta-file read error (%s)\n", sln_strerror(len)); rc = DB_EIO; goto cleanup; } size_t i; for(i = 0; i < len; i++) { char const c = buf->base[i]; if('\r' == c || '\n' == c) break; } if(i >= len) { fprintf(stderr, "Submission meta-file parse error (invalid target URI)\n"); rc = DB_EIO; goto cleanup; } assert(i < len); str_t targetURI[URI_MAX]; memcpy(targetURI, buf->base, i); targetURI[i] = '\0'; pos += i; // TODO: Support sub-transactions in LevelDB backend. // TODO: db_txn_begin should support NULL env. // rc = db_txn_begin(NULL, txn, DB_RDWR, &subtxn); // if(rc < 0) goto cleanup; subtxn = txn; uint64_t const metaFileID = add_metafile(subtxn, fileID, targetURI); if(!metaFileID) goto cleanup; // Duplicate meta-file, not an error. // TODO: Unless the previous version wasn't actually a meta-file. ctx->txn = subtxn; ctx->metaFileID = metaFileID; ctx->targetURI = targetURI; ctx->depth = -1; parser = yajl_alloc(&callbacks, NULL, ctx); if(!parser) rc = DB_ENOMEM; if(rc < 0) goto cleanup; yajl_config(parser, yajl_allow_partial_values, (int)true); yajl_status status = yajl_status_ok; for(;;) { buf->len = MIN(BUF_LEN, PARSE_MAX-pos); if(!buf->len) break; len = async_fs_read(fd, buf, 1, pos); if(len < 0) { fprintf(stderr, "Submission meta-file read error (%s)\n", sln_strerror(len)); rc = DB_EIO; goto cleanup; } if(0 == len) break; status = yajl_parse(parser, (byte_t const *)buf->base, len); if(yajl_status_ok != status) break; pos += len; } status = yajl_complete_parse(parser); if(yajl_status_ok != status) { unsigned char *msg = yajl_get_error(parser, true, (byte_t const *)buf->base, len); fprintf(stderr, "%s", msg); yajl_free_error(parser, msg); msg = NULL; rc = DB_EIO; goto cleanup; } assert(-1 == ctx->depth); // rc = db_txn_commit(subtxn); subtxn = NULL; if(rc < 0) goto cleanup; *out = metaFileID; cleanup: // db_txn_abort(subtxn); subtxn = NULL; FREE(&buf->base); if(parser) yajl_free(parser); parser = NULL; assert_zeroed(ctx->fields, DEPTH_MAX); return rc; }