diff --git a/rhizome.c b/rhizome.c index 96a53711..f0c9a3f4 100644 --- a/rhizome.c +++ b/rhizome.c @@ -99,15 +99,17 @@ int rhizome_fetch_delay_ms() * operation will create it using the fields supplied. Also, the caller can supply a clear-text * payload with the 'crypt=1' field to cause it to be stored encrypted. * + * - if 'appending' is true then the new bundle will be a journal bundle, otherwise it will be a + * normal bundle. Any existing manifest must be consistent; eg, an append will fail if a bundle + * with the same Bundle Id already exists in the store and is not a journal. + * * - 'm' must point to a manifest structure into which any supplied partial manifest has already * been parsed. If the caller supplied no (partial) manifest at all, then the manifest 'm' will * be blank. * - * - 'bsk' must point to a supplied bundle secret parameter, or NULL if none was supplied. + * - 'mout' must point to a manifest pointer which is updated to hold the constructed manifest. * - * - if 'appending' is true then the new bundle will be a journal bundle, otherwise it will be a - * normal bundle. Any existing manifest must be consistent; eg, an append will fail if a bundle - * with the same Bundle Id already exists in the store and is not a journal. + * - 'bsk' must point to a supplied bundle secret parameter, or NULL if none was supplied. * * - 'author' must point to a supplied author parameter, or NULL if none was supplied. * @@ -155,7 +157,13 @@ const char * rhizome_bundle_add_file(int appending, existing_manifest = NULL; break; case RHIZOME_BUNDLE_STATUS_SAME: - // Found a manifest with the same bundle ID. Overwrite it with the supplied manifest. + // Found a manifest with the same bundle ID. Unset its 'version', 'filesize' and 'filehash' + // fields unless appending, then overwrite it with the supplied manifest. + if (!appending) { + rhizome_manifest_del_version(existing_manifest); + rhizome_manifest_del_filesize(existing_manifest); + rhizome_manifest_del_filehash(existing_manifest); + } if (rhizome_manifest_overwrite(existing_manifest, m) == -1) { WHY(reason = "Existing manifest could not be overwritten"); goto error; @@ -182,18 +190,21 @@ const char * rhizome_bundle_add_file(int appending, // If no existing bundle has been identified, we are building a bundle from scratch. if (!new_manifest) { new_manifest = m; - // A new journal manifest needs these fields set so that the first append can succeed. + // A new journal manifest needs the 'filesize' and 'tail' fields set so that the first append can + // succeed. if (appending) { - rhizome_manifest_set_filesize(new_manifest, 0); - rhizome_manifest_set_tail(new_manifest, 0); + if (new_manifest->filesize == RHIZOME_SIZE_UNSET) + rhizome_manifest_set_filesize(new_manifest, 0); + if (new_manifest->tail == RHIZOME_SIZE_UNSET) + rhizome_manifest_set_tail(new_manifest, 0); } } - if (appending && !m->is_journal){ + if (appending && !new_manifest->is_journal){ // TODO: return a special status code for this case WHY(reason = "Cannot append to a non-journal"); goto error; } - if (!appending && m->is_journal) { + if (!appending && new_manifest->is_journal) { // TODO: return a special status code for this case WHY(reason = "Cannot add a journal bundle (use append instead)"); goto error; diff --git a/rhizome.h b/rhizome.h index babe587b..d4959692 100644 --- a/rhizome.h +++ b/rhizome.h @@ -251,8 +251,11 @@ typedef struct rhizome_manifest */ #define rhizome_manifest_set_id(m,v) _rhizome_manifest_set_id(__WHENCE__,(m),(v)) #define rhizome_manifest_set_version(m,v) _rhizome_manifest_set_version(__WHENCE__,(m),(v)) +#define rhizome_manifest_del_version(m) _rhizome_manifest_del_version(__WHENCE__,(m)) #define rhizome_manifest_set_filesize(m,v) _rhizome_manifest_set_filesize(__WHENCE__,(m),(v)) +#define rhizome_manifest_del_filesize(m) _rhizome_manifest_del_filesize(__WHENCE__,(m)) #define rhizome_manifest_set_filehash(m,v) _rhizome_manifest_set_filehash(__WHENCE__,(m),(v)) +#define rhizome_manifest_del_filehash(m) _rhizome_manifest_del_filehash(__WHENCE__,(m)) #define rhizome_manifest_set_tail(m,v) _rhizome_manifest_set_tail(__WHENCE__,(m),(v)) #define rhizome_manifest_set_bundle_key(m,v) _rhizome_manifest_set_bundle_key(__WHENCE__,(m),(v)) #define rhizome_manifest_del_bundle_key(m) _rhizome_manifest_del_bundle_key(__WHENCE__,(m)) @@ -274,8 +277,11 @@ typedef struct rhizome_manifest void _rhizome_manifest_set_id(struct __sourceloc, rhizome_manifest *, const rhizome_bid_t *); void _rhizome_manifest_set_version(struct __sourceloc, rhizome_manifest *, uint64_t); +void _rhizome_manifest_del_version(struct __sourceloc, rhizome_manifest *); void _rhizome_manifest_set_filesize(struct __sourceloc, rhizome_manifest *, uint64_t); +void _rhizome_manifest_del_filesize(struct __sourceloc, rhizome_manifest *); void _rhizome_manifest_set_filehash(struct __sourceloc, rhizome_manifest *, const rhizome_filehash_t *); +void _rhizome_manifest_del_filehash(struct __sourceloc, rhizome_manifest *); void _rhizome_manifest_set_tail(struct __sourceloc, rhizome_manifest *, uint64_t); void _rhizome_manifest_set_bundle_key(struct __sourceloc, rhizome_manifest *, const rhizome_bk_t *); void _rhizome_manifest_del_bundle_key(struct __sourceloc, rhizome_manifest *); diff --git a/rhizome_bundle.c b/rhizome_bundle.c index 9dd38311..359453fa 100644 --- a/rhizome_bundle.c +++ b/rhizome_bundle.c @@ -156,6 +156,11 @@ void _rhizome_manifest_set_version(struct __sourceloc __whence, rhizome_manifest m->finalised = 0; } +void _rhizome_manifest_del_version(struct __sourceloc __whence, rhizome_manifest *m) +{ + _rhizome_manifest_set_version(__whence, m, 0); +} + void _rhizome_manifest_set_filesize(struct __sourceloc __whence, rhizome_manifest *m, uint64_t size) { if (size == RHIZOME_SIZE_UNSET) { @@ -168,6 +173,11 @@ void _rhizome_manifest_set_filesize(struct __sourceloc __whence, rhizome_manifes m->finalised = 0; } +void _rhizome_manifest_del_filesize(struct __sourceloc __whence, rhizome_manifest *m) +{ + _rhizome_manifest_set_filesize(__whence, m, RHIZOME_SIZE_UNSET); +} + /* Must always set file size before setting the file hash, to avoid assertion failures. */ void _rhizome_manifest_set_filehash(struct __sourceloc __whence, rhizome_manifest *m, const rhizome_filehash_t *hash) @@ -185,6 +195,11 @@ void _rhizome_manifest_set_filehash(struct __sourceloc __whence, rhizome_manifes m->finalised = 0; } +void _rhizome_manifest_del_filehash(struct __sourceloc __whence, rhizome_manifest *m) +{ + _rhizome_manifest_set_filehash(__whence, m, NULL); +} + void _rhizome_manifest_set_tail(struct __sourceloc __whence, rhizome_manifest *m, uint64_t tail) { if (tail == RHIZOME_SIZE_UNSET) { @@ -193,9 +208,9 @@ void _rhizome_manifest_set_tail(struct __sourceloc __whence, rhizome_manifest *m } else { const char *v = rhizome_manifest_set_ui64(m, "tail", tail); assert(v); // TODO: remove known manifest fields from vars[] - m->tail = tail; m->is_journal = 1; } + m->tail = tail; m->finalised = 0; } diff --git a/tests/rhizomeops b/tests/rhizomeops index 2db21db4..023a24a7 100755 --- a/tests/rhizomeops +++ b/tests/rhizomeops @@ -765,17 +765,29 @@ test_AddUpdateDiscoverAuthor() { doc_AddUpdateNoAuthor="Cannot add new payload to authorless manifest" setup_AddUpdateNoAuthor() { - setup_AddUpdateNewVersion - $SED -i -e '/^BK=/d' file1_2.manifest + setup_servald + setup_rhizome + executeOk_servald rhizome list + assert_rhizome_list + echo "A test file" >file1 + echo "A test file, second version" >file1_2 + # Add first file + executeOk_servald rhizome add file '' file1 file1.manifest + extract_stdout_secret file1_secret + assert_manifest_fields file1.manifest !BK + # Create second manifest + cp file1.manifest file1_2.manifest + strip_signatures file1_2.manifest + $SED -i -e '/^date=/d;/^filehash=/d;/^filesize=/d;/^version=/d' file1_2.manifest + tfw_cat -v file1_2.manifest } test_AddUpdateNoAuthor() { - tfw_cat -v file1_2.manifest execute $servald rhizome add file $SIDB1 file1_2 file1_2.manifest tfw_cat --stderr assertExitStatus '!=' 0 - # Rhizome store contents have old payload, with the original author. + # Rhizome store contents still have old payload executeOk_servald rhizome list - assert_rhizome_list --fromhere=1 --author=$SIDB1 file1 file2 + assert_rhizome_list --fromhere=0 file1 } doc_AddUpdateNoAuthorWithSecret="Add new payload to authorless manifest with bundle secret" @@ -783,13 +795,12 @@ setup_AddUpdateNoAuthorWithSecret() { setup_AddUpdateNoAuthor } test_AddUpdateNoAuthorWithSecret() { - tfw_cat -v file1_2.manifest executeOk_servald rhizome add file $SIDB1 file1_2 file1_2.manifest "$file1_secret" tfw_cat --stderr # Rhizome store contents have new payload, but it has lost its author (no BK # field any more). executeOk_servald rhizome list - assert_rhizome_list --fromhere=0 file1_2 --fromhere=1 --author=$SIDB1 file2 + assert_rhizome_list --fromhere=0 file1_2 } doc_AddUpdateAutoVersion="Add new payload to existing manifest with automatic version"