int SLNSessionGetFileInfo(SLNSessionRef const session, strarg_t const URI, SLNFileInfo *const info) { DB_env *db = NULL; int rc = SLNSessionDBOpen(session, SLN_RDONLY, &db); if(rc < 0) return rc; DB_txn *txn = NULL; rc = db_txn_begin(db, NULL, DB_RDONLY, &txn); if(rc < 0) { SLNSessionDBClose(session, &db); return rc; } DB_cursor *cursor; rc = db_txn_cursor(txn, &cursor); assert(!rc); DB_range fileIDs[1]; SLNURIAndFileIDRange1(fileIDs, txn, URI); DB_val URIAndFileID_key[1]; rc = db_cursor_firstr(cursor, fileIDs, URIAndFileID_key, NULL, +1); DB_val file_val[1]; if(rc >= 0) { strarg_t URI2; uint64_t fileID; SLNURIAndFileIDKeyUnpack(URIAndFileID_key, txn, &URI2, &fileID); assert(0 == strcmp(URI, URI2)); if(info) { DB_val fileID_key[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); rc = db_get(txn, fileID_key, file_val); } } if(rc < 0) { db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return rc; } if(info) { // Clear padding for later assert_zeroed. memset(info, 0, sizeof(*info)); strarg_t const internalHash = db_read_string(file_val, txn); strarg_t const type = db_read_string(file_val, txn); uint64_t const size = db_read_uint64(file_val); info->hash = strdup(internalHash); info->path = SLNRepoCopyInternalPath(SLNSessionGetRepo(session), internalHash); info->type = strdup(type); info->size = size; if(!info->hash || !info->path || !info->type) { SLNFileInfoCleanup(info); db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return DB_ENOMEM; } } db_txn_abort(txn); txn = NULL; SLNSessionDBClose(session, &db); return 0; }
int SLNFilterCopyURI(SLNFilterRef const filter, uint64_t const fileID, bool const meta, DB_txn *const txn, str_t **const out) { DB_val fileID_key[1], file_val[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); int rc = db_get(txn, fileID_key, file_val); if(rc < 0) return rc; strarg_t const hash = db_read_string(file_val, txn); db_assert(hash); str_t *URI = NULL; if(!meta) { URI = SLNFormatURI(SLN_INTERNAL_ALGO, hash); if(!URI) return DB_ENOMEM; } else { DB_val key[1], val[1]; SLNMetaFileByIDKeyPack(key, txn, fileID); rc = db_get(txn, key, val); if(rc < 0) return rc; uint64_t f; strarg_t target = NULL; SLNMetaFileByIDValUnpack(val, txn, &f, &target); db_assert(target); URI = aasprintf("hash://%s/%s -> %s", SLN_INTERNAL_ALGO, hash, target); if(!URI) return DB_ENOMEM; } *out = URI; URI = NULL; return 0; }
int SLNSubmissionStore(SLNSubmissionRef const sub, DB_txn *const txn) { assert(sub); assert(txn); assert(!sub->tmppath); // Session permissions were already checked when the sub was created. int64_t fileID = db_next_id(SLNFileByID, txn); int rc; DB_val dupFileID_val[1]; SLNFileIDByInfoValPack(dupFileID_val, txn, fileID); DB_val fileInfo_key[1]; SLNFileIDByInfoKeyPack(fileInfo_key, txn, sub->internalHash, sub->type); rc = db_put(txn, fileInfo_key, dupFileID_val, DB_NOOVERWRITE); if(rc >= 0) { DB_val fileID_key[1]; SLNFileByIDKeyPack(fileID_key, txn, fileID); DB_val file_val[1]; SLNFileByIDValPack(file_val, txn, sub->internalHash, sub->type, sub->size); rc = db_put(txn, fileID_key, file_val, DB_NOOVERWRITE_FAST); if(rc < 0) return rc; } else if(DB_KEYEXIST == rc) { fileID = db_read_uint64(dupFileID_val); } else return rc; for(size_t i = 0; sub->URIs[i]; ++i) { strarg_t const URI = sub->URIs[i]; DB_val null = { 0, NULL }; DB_val fwd[1]; SLNFileIDAndURIKeyPack(fwd, txn, fileID, URI); rc = db_put(txn, fwd, &null, DB_NOOVERWRITE_FAST); if(rc < 0 && DB_KEYEXIST != rc) return rc; DB_val rev[1]; SLNURIAndFileIDKeyPack(rev, txn, URI, fileID); rc = db_put(txn, rev, &null, DB_NOOVERWRITE_FAST); if(rc < 0 && DB_KEYEXIST != rc) return rc; } rc = SLNSubmissionParseMetaFile(sub, fileID, txn, &sub->metaFileID); if(rc < 0) { alogf("Submission meta-file error: %s\n", sln_strerror(rc)); return rc; } return 0; }