mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-19 21:27:57 +00:00
Append manifest into zip file comment
This commit is contained in:
parent
a5ff0ed2a3
commit
5636edfe20
@ -456,6 +456,13 @@ public class ServalDCommand
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ManifestResult rhizomeImportZipBundle(File payloadFile) throws ServalDFailureException {
|
||||
ManifestResult result = new ManifestResult();
|
||||
result.setResult(command(result, "rhizome", "import", "bundle", "--zip-comment",
|
||||
payloadFile.getAbsolutePath(), payloadFile.getAbsolutePath()));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ManifestResult rhizomeExtractBundle(BundleId manifestId, File manifestFile, File payloadFile) throws ServalDFailureException{
|
||||
ManifestResult result = new ManifestResult();
|
||||
result.setResult(command(result, "rhizome", "extract", "bundle",
|
||||
@ -465,6 +472,15 @@ public class ServalDCommand
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ManifestResult rhizomeExportZipBundle(BundleId manifestId, File payloadFile) throws ServalDFailureException{
|
||||
ManifestResult result = new ManifestResult();
|
||||
result.setResult(command(result, "rhizome", "export", "bundle", "--zip-comment",
|
||||
manifestId.toHex(),
|
||||
payloadFile.getAbsolutePath(),
|
||||
payloadFile.getAbsolutePath()));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ManifestResult rhizomeExportManifest(BundleId manifestId, File manifestFile) throws ServalDFailureException{
|
||||
ManifestResult result = new ManifestResult();
|
||||
result.setResult(command(result, "rhizome", "export", "manifest",
|
||||
|
221
rhizome.c
221
rhizome.c
@ -340,87 +340,184 @@ error:
|
||||
* containing the payload. The work is all done by rhizome_bundle_import() and
|
||||
* rhizome_store_manifest().
|
||||
*/
|
||||
enum rhizome_bundle_status rhizome_bundle_import_files(rhizome_manifest *m, rhizome_manifest **mout, const char *manifest_path, const char *filepath)
|
||||
enum rhizome_bundle_status rhizome_bundle_import_files(rhizome_manifest *m, rhizome_manifest **mout, const char *manifest_path, const char *filepath, int zip_comment)
|
||||
{
|
||||
DEBUGF(rhizome, "(manifest_path=%s, filepath=%s)",
|
||||
DEBUGF(rhizome, "(manifest_path=%s, filepath=%s, zip_comment=%d)",
|
||||
manifest_path ? alloca_str_toprint(manifest_path) : "NULL",
|
||||
filepath ? alloca_str_toprint(filepath) : "NULL");
|
||||
filepath ? alloca_str_toprint(filepath) : "NULL",
|
||||
zip_comment);
|
||||
|
||||
size_t buffer_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
// manifest has been appended to the end of the file.
|
||||
if (strcmp(manifest_path, filepath)==0){
|
||||
unsigned char marker[4];
|
||||
FILE *f = fopen(filepath, "r");
|
||||
|
||||
if (f == NULL)
|
||||
return WHYF_perror("Could not open manifest file %s for reading.", filepath);
|
||||
if (fseek(f, -sizeof(marker), SEEK_END))
|
||||
ret=WHY_perror("Unable to seek to end of file");
|
||||
if (ret==0){
|
||||
ret = fread(marker, 1, sizeof(marker), f);
|
||||
if (ret==sizeof(marker))
|
||||
ret=0;
|
||||
else
|
||||
ret=WHY_perror("Unable to read end of manifest marker");
|
||||
}
|
||||
if (ret==0){
|
||||
if (marker[2]!=0x41 || marker[3]!=0x10)
|
||||
ret=WHYF("Expected 0x4110 marker at end of file");
|
||||
}
|
||||
if (ret==0){
|
||||
buffer_len = read_uint16(marker);
|
||||
if (buffer_len < 1 || buffer_len > MAX_MANIFEST_BYTES)
|
||||
ret=WHYF("Invalid manifest length %zu", buffer_len);
|
||||
}
|
||||
if (ret==0){
|
||||
if (fseek(f, -(buffer_len+sizeof(marker)), SEEK_END))
|
||||
ret=WHY_perror("Unable to seek to end of file");
|
||||
}
|
||||
if (ret == 0 && fread(m->manifestdata, buffer_len, 1, f) != 1) {
|
||||
if (ferror(f))
|
||||
ret = WHYF("fread(%p,%zu,1,%s) error", m->manifestdata, buffer_len, alloca_str_toprint(filepath));
|
||||
else if (feof(f))
|
||||
ret = WHYF("fread(%p,%zu,1,%s) hit end of file", m->manifestdata, buffer_len, alloca_str_toprint(filepath));
|
||||
}
|
||||
fclose(f);
|
||||
} else {
|
||||
ssize_t size = read_whole_file(manifest_path, m->manifestdata, sizeof m->manifestdata);
|
||||
if (size == -1)
|
||||
ret = -1;
|
||||
buffer_len = (size_t) size;
|
||||
enum rhizome_bundle_status ret;
|
||||
int single_file = strcmp(manifest_path, filepath)==0;
|
||||
|
||||
int fd = open(manifest_path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return WHYF_perror("Could not open manifest file %s for reading.", filepath);
|
||||
|
||||
off_t file_len = lseek(fd, 0, SEEK_END);
|
||||
if (file_len==-1){
|
||||
ret=WHY_perror("Unable to determine file length");
|
||||
goto end;
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
m->manifest_all_bytes = buffer_len;
|
||||
|
||||
uint8_t buff[MAX_MANIFEST_BYTES + 22];
|
||||
off_t read_len = sizeof buff;
|
||||
|
||||
if (read_len > file_len)
|
||||
read_len = file_len;
|
||||
|
||||
if (lseek(fd, -read_len, SEEK_END)==-1){
|
||||
ret=WHYF_perror("lseek(%d, %d, SEEK_END) - Failed to seek to near the end of %s, len %u", fd, (int)-read_len, manifest_path, (int)file_len);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (read(fd, buff, read_len)!=read_len){
|
||||
ret=WHYF_perror("Failed to read %u bytes of the manifest", (int)read_len);
|
||||
goto end;
|
||||
}
|
||||
uint8_t *manifest_ptr;
|
||||
|
||||
// manifest has been appended to the end of the file.
|
||||
if (single_file){
|
||||
if (zip_comment){
|
||||
// scan backwards for EOCD marker 0x504b0506
|
||||
uint8_t *EOCD = &buff[read_len - 22];
|
||||
while(EOCD){
|
||||
if (EOCD[0]==0x50 && EOCD[1]==0x4b && EOCD[2]==0x05 && EOCD[3]==0x06)
|
||||
break;
|
||||
EOCD--;
|
||||
}
|
||||
|
||||
if (!EOCD){
|
||||
ret=WHY("Expected zip EOCD marker 0x504b0506 near end of file");
|
||||
goto end;
|
||||
}
|
||||
|
||||
m->manifest_all_bytes = EOCD[20] | (EOCD[21]<<8);
|
||||
manifest_ptr = &EOCD[22];
|
||||
|
||||
}else{
|
||||
if (buff[read_len-2]!=0x41 || buff[read_len-1]!=0x10){
|
||||
ret=WHYF("Expected 0x4110 marker at end of file");
|
||||
goto end;
|
||||
}
|
||||
m->manifest_all_bytes = read_uint16(&buff[read_len-4]);
|
||||
manifest_ptr = &buff[read_len - m->manifest_all_bytes - 4];
|
||||
}
|
||||
}else{
|
||||
manifest_ptr = buff;
|
||||
m->manifest_all_bytes = read_len;
|
||||
}
|
||||
|
||||
if (m->manifest_all_bytes < 1 || m->manifest_all_bytes > MAX_MANIFEST_BYTES){
|
||||
ret=WHYF("Invalid manifest length %zu", m->manifest_all_bytes);
|
||||
goto end;
|
||||
}
|
||||
if (manifest_ptr < buff || manifest_ptr + m->manifest_all_bytes > buff + read_len){
|
||||
ret=WHY("Invalid manifest offset");
|
||||
goto end;
|
||||
}
|
||||
bcopy(manifest_ptr, m->manifestdata, m->manifest_all_bytes);
|
||||
|
||||
if ( rhizome_manifest_parse(m) == -1
|
||||
|| !rhizome_manifest_validate(m)
|
||||
|| !rhizome_manifest_verify(m)
|
||||
)
|
||||
return RHIZOME_BUNDLE_STATUS_INVALID;
|
||||
enum rhizome_bundle_status status = rhizome_manifest_check_stored(m, mout);
|
||||
if (status != RHIZOME_BUNDLE_STATUS_NEW)
|
||||
return status;
|
||||
enum rhizome_payload_status pstatus = rhizome_import_payload_from_file(m, filepath);
|
||||
){
|
||||
ret = RHIZOME_BUNDLE_STATUS_INVALID;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = rhizome_manifest_check_stored(m, mout);
|
||||
if (ret != RHIZOME_BUNDLE_STATUS_NEW)
|
||||
goto end;
|
||||
|
||||
enum rhizome_payload_status pstatus = RHIZOME_PAYLOAD_STATUS_EMPTY;
|
||||
if (m->filesize > 0){
|
||||
|
||||
if (single_file){
|
||||
if (lseek(fd, 0, SEEK_SET)==-1){
|
||||
ret=WHY_perror("Unable to seek to start of file");
|
||||
goto end;
|
||||
}
|
||||
}else{
|
||||
close(fd);
|
||||
fd = open(filepath, O_RDONLY);
|
||||
if (fd==-1)
|
||||
return WHYF_perror("Could not open payload file %s for reading.", filepath);
|
||||
}
|
||||
|
||||
/* Import the file, checking the hash as we go */
|
||||
struct rhizome_write write;
|
||||
bzero(&write, sizeof(write));
|
||||
|
||||
pstatus = rhizome_open_write(&write, &m->filehash, m->filesize);
|
||||
if (pstatus == RHIZOME_PAYLOAD_STATUS_NEW){
|
||||
off_t read_len = m->filesize;
|
||||
uint8_t payload_buffer[RHIZOME_CRYPT_PAGE_SIZE];
|
||||
if (zip_comment)
|
||||
read_len -=2;
|
||||
while(write.file_offset < (uint64_t)read_len){
|
||||
size_t size = sizeof payload_buffer;
|
||||
if (write.file_offset + size > (uint64_t)read_len)
|
||||
size = read_len - write.file_offset;
|
||||
ssize_t r = read(fd, payload_buffer, size);
|
||||
if (r == -1) {
|
||||
ret = WHYF_perror("read(%d,%p,%zu)", fd, payload_buffer, size);
|
||||
rhizome_fail_write(&write);
|
||||
goto end;
|
||||
}
|
||||
if ((size_t) r != size) {
|
||||
ret = WHYF("file truncated - read(%d,%p,%zu) returned %zu", fd, payload_buffer, size, (size_t) r);
|
||||
rhizome_fail_write(&write);
|
||||
goto end;
|
||||
}
|
||||
if (r && rhizome_write_buffer(&write, payload_buffer, (size_t) r)) {
|
||||
ret = -1;
|
||||
rhizome_fail_write(&write);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (zip_comment){
|
||||
uint8_t comment_len[2] = {0,0};
|
||||
if (rhizome_write_buffer(&write, comment_len, sizeof comment_len)){
|
||||
ret = -1;
|
||||
rhizome_fail_write(&write);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
pstatus = rhizome_finish_write(&write);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (pstatus) {
|
||||
case RHIZOME_PAYLOAD_STATUS_EMPTY:
|
||||
case RHIZOME_PAYLOAD_STATUS_STORED:
|
||||
case RHIZOME_PAYLOAD_STATUS_NEW:
|
||||
if (rhizome_store_manifest(m) == -1)
|
||||
return -1;
|
||||
return status;
|
||||
ret = -1;
|
||||
break;
|
||||
case RHIZOME_PAYLOAD_STATUS_TOO_BIG:
|
||||
case RHIZOME_PAYLOAD_STATUS_EVICTED:
|
||||
return RHIZOME_BUNDLE_STATUS_NO_ROOM;
|
||||
ret = RHIZOME_BUNDLE_STATUS_NO_ROOM;
|
||||
break;
|
||||
case RHIZOME_PAYLOAD_STATUS_ERROR:
|
||||
case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL:
|
||||
return -1;
|
||||
ret = -1;
|
||||
break;
|
||||
case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE:
|
||||
case RHIZOME_PAYLOAD_STATUS_WRONG_HASH:
|
||||
return RHIZOME_BUNDLE_STATUS_INCONSISTENT;
|
||||
ret = RHIZOME_BUNDLE_STATUS_INCONSISTENT;
|
||||
break;
|
||||
default:
|
||||
FATALF("rhizome_import_payload_from_file() returned status = %d", pstatus);
|
||||
}
|
||||
FATALF("rhizome_import_payload_from_file() returned status = %d", pstatus);
|
||||
|
||||
end:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Sets the bundle key "BK" field of a manifest. Returns 1 if the field was set, 0 if not.
|
||||
|
@ -501,7 +501,7 @@ struct rhizome_bundle_result rhizome_manifest_add_file(int appending,
|
||||
const char *file_path,
|
||||
unsigned nassignments,
|
||||
const struct rhizome_manifest_field_assignment *assignments);
|
||||
int rhizome_bundle_import_files(rhizome_manifest *m, rhizome_manifest **m_out, const char *manifest_path, const char *filepath);
|
||||
int rhizome_bundle_import_files(rhizome_manifest *m, rhizome_manifest **m_out, const char *manifest_path, const char *filepath, int zip_files);
|
||||
|
||||
int rhizome_manifest_set_name_from_path(rhizome_manifest *m, const char *filepath);
|
||||
struct rhizome_bundle_result rhizome_fill_manifest(rhizome_manifest *m, const char *filepath, const sid_t *authorSidp);
|
||||
@ -915,7 +915,7 @@ int rhizome_write_buffer(struct rhizome_write *write_state, uint8_t *buffer, siz
|
||||
int rhizome_random_write(struct rhizome_write *write_state, uint64_t offset, uint8_t *buffer, size_t data_size);
|
||||
enum rhizome_payload_status rhizome_write_open_manifest(struct rhizome_write *write, rhizome_manifest *m);
|
||||
enum rhizome_payload_status rhizome_write_open_journal(struct rhizome_write *write, rhizome_manifest *m, uint64_t advance_by, uint64_t append_size);
|
||||
int rhizome_write_file(struct rhizome_write *write, const char *filename);
|
||||
int rhizome_write_file(struct rhizome_write *write, const char *filename, off_t offset, uint64_t length);
|
||||
void rhizome_fail_write(struct rhizome_write *write);
|
||||
enum rhizome_payload_status rhizome_finish_write(struct rhizome_write *write);
|
||||
enum rhizome_payload_status rhizome_finish_store(struct rhizome_write *write, rhizome_manifest *m, enum rhizome_payload_status status);
|
||||
|
@ -17,6 +17,7 @@
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include "cli.h"
|
||||
#include "conf.h"
|
||||
#include "keyring.h"
|
||||
@ -101,9 +102,59 @@ static int app_rhizome_hash_file(const struct cli_parsed *parsed, struct cli_con
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int append_manifest_zip_comment(const char *filepath, rhizome_manifest *m)
|
||||
{
|
||||
int fd = open(filepath, O_RDWR);
|
||||
if (fd==-1)
|
||||
return WHYF_perror("open(%s,O_RDWR)", alloca_str_toprint(filepath));
|
||||
int ret=0;
|
||||
uint8_t EOCD[22];
|
||||
|
||||
if (lseek(fd, -(sizeof EOCD), SEEK_END)==-1){
|
||||
ret = WHYF_perror("lseek(%d,%d,SEEK_END)", fd, -(sizeof EOCD));
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (read(fd, EOCD, sizeof EOCD)==-1){
|
||||
ret = WHYF_perror("read(%d,%p,%zu)", fd, EOCD, sizeof EOCD);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(EOCD[20] || EOCD[21]){
|
||||
ret = WHYF("Expected 0x00 0x00 at end of file, found 0x%02x 0x%02x", EOCD[20], EOCD[21]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if(EOCD[0]!=0x50 || EOCD[1]!=0x4b || EOCD[2]!=0x05 || EOCD[3]!=0x06){
|
||||
ret = WHYF("Expected zip EOCD marker 0x504b0506 near end of file");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (lseek(fd, -2, SEEK_END)==-1){
|
||||
ret = WHYF_perror("lseek(%d,-2,SEEK_END)", fd);
|
||||
goto end;
|
||||
}
|
||||
|
||||
uint8_t len[2];
|
||||
len[0]=m->manifest_all_bytes & 0xFF;
|
||||
len[1]=(m->manifest_all_bytes >> 8)& 0xFF;
|
||||
if (write(fd, len, sizeof len)==-1){
|
||||
ret = WHYF_perror("write(%d,%p,2)", fd, len);
|
||||
goto end;
|
||||
}
|
||||
if (write(fd, m->manifestdata, m->manifest_all_bytes)==-1){
|
||||
ret = WHYF_perror("write(%d,%p,%d)", fd, m->manifestdata, m->manifest_all_bytes);
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEFINE_CMD(app_rhizome_add_file, 0,
|
||||
"Add a file to Rhizome and optionally write its manifest to the given path",
|
||||
"rhizome","add","file" KEYRING_PIN_OPTIONS,"[--bundle=<bundleid>]","[--force-new]","<author_sid>","<filepath>","[<manifestpath>]","[<bsk>]","...");
|
||||
"rhizome","add","file" KEYRING_PIN_OPTIONS,"[--zip-comment]","[--bundle=<bundleid>]","[--force-new]","<author_sid>","<filepath>","[<manifestpath>]","[<bsk>]","...");
|
||||
DEFINE_CMD(app_rhizome_add_file, 0,
|
||||
"Append content to a journal bundle",
|
||||
"rhizome", "journal", "append" KEYRING_PIN_OPTIONS, "<author_sid>", "<bundleid>", "<filepath>", "[<bsk>]");
|
||||
@ -121,6 +172,7 @@ static int app_rhizome_add_file(const struct cli_parsed *parsed, struct cli_cont
|
||||
cli_arg(parsed, "bundleid", &bundleIdHex, cli_optional_bid, "");
|
||||
if (cli_arg(parsed, "bsk", &bsktext, cli_optional_bundle_secret_key, NULL) == -1)
|
||||
return -1;
|
||||
int zip_comment = 0 == cli_arg(parsed, "--zip-comment", NULL, NULL, NULL);
|
||||
|
||||
sid_t authorSid;
|
||||
if (!authorSidHex || !*authorSidHex)
|
||||
@ -294,6 +346,10 @@ static int app_rhizome_add_file(const struct cli_parsed *parsed, struct cli_cont
|
||||
case RHIZOME_BUNDLE_STATUS_OLD:
|
||||
assert(mout != NULL);
|
||||
cli_put_manifest(context, mout);
|
||||
|
||||
if (zip_comment)
|
||||
append_manifest_zip_comment(filepath, mout);
|
||||
|
||||
if ( manifestpath && *manifestpath
|
||||
&& rhizome_write_manifest_file(mout, manifestpath, 0) == -1
|
||||
)
|
||||
@ -329,20 +385,22 @@ finish:
|
||||
|
||||
DEFINE_CMD(app_rhizome_import_bundle, 0,
|
||||
"Import a payload/manifest pair into Rhizome",
|
||||
"rhizome","import","bundle","<filepath>","<manifestpath>");
|
||||
"rhizome","import","bundle","[--zip-comment]","<filepath>","<manifestpath>");
|
||||
static int app_rhizome_import_bundle(const struct cli_parsed *parsed, struct cli_context *context)
|
||||
{
|
||||
DEBUG_cli_parsed(verbose, parsed);
|
||||
const char *filepath, *manifestpath;
|
||||
cli_arg(parsed, "filepath", &filepath, NULL, "");
|
||||
cli_arg(parsed, "manifestpath", &manifestpath, NULL, "");
|
||||
int zip_comment = 0 == cli_arg(parsed, "--zip-comment", NULL, NULL, NULL);
|
||||
|
||||
if (rhizome_opendb() == -1)
|
||||
return -1;
|
||||
rhizome_manifest *m = rhizome_new_manifest();
|
||||
if (!m)
|
||||
return WHY("Out of manifests.");
|
||||
rhizome_manifest *m_out = NULL;
|
||||
enum rhizome_bundle_status status = rhizome_bundle_import_files(m, &m_out, manifestpath, filepath);
|
||||
enum rhizome_bundle_status status = rhizome_bundle_import_files(m, &m_out, manifestpath, filepath, zip_comment);
|
||||
switch (status) {
|
||||
case RHIZOME_BUNDLE_STATUS_NEW:
|
||||
cli_put_manifest(context, m);
|
||||
@ -368,7 +426,7 @@ static int app_rhizome_import_bundle(const struct cli_parsed *parsed, struct cli
|
||||
|
||||
DEFINE_CMD(app_rhizome_append_manifest, 0,
|
||||
"Append a manifest to the end of the file it belongs to.",
|
||||
"rhizome", "append", "manifest", "<filepath>", "<manifestpath>");
|
||||
"rhizome", "append", "manifest", "[--zip-comment]", "<filepath>", "<manifestpath>");
|
||||
static int app_rhizome_append_manifest(const struct cli_parsed *parsed, struct cli_context *UNUSED(context))
|
||||
{
|
||||
DEBUG_cli_parsed(verbose, parsed);
|
||||
@ -376,6 +434,8 @@ static int app_rhizome_append_manifest(const struct cli_parsed *parsed, struct c
|
||||
if ( cli_arg(parsed, "manifestpath", &manifestpath, NULL, "") == -1
|
||||
|| cli_arg(parsed, "filepath", &filepath, NULL, "") == -1)
|
||||
return -1;
|
||||
int zip_comment = 0 == cli_arg(parsed, "--zip-comment", NULL, NULL, NULL);
|
||||
|
||||
rhizome_manifest *m = rhizome_new_manifest();
|
||||
if (!m)
|
||||
return WHY("Out of manifests.");
|
||||
@ -384,8 +444,12 @@ static int app_rhizome_append_manifest(const struct cli_parsed *parsed, struct c
|
||||
&& rhizome_manifest_validate(m)
|
||||
&& rhizome_manifest_verify(m)
|
||||
) {
|
||||
if (rhizome_write_manifest_file(m, filepath, 1) != -1)
|
||||
ret = 0;
|
||||
if (zip_comment){
|
||||
append_manifest_zip_comment(filepath, m);
|
||||
}else{
|
||||
if (rhizome_write_manifest_file(m, filepath, 1) != -1)
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
rhizome_manifest_free(m);
|
||||
return ret;
|
||||
@ -488,7 +552,7 @@ static int app_rhizome_clean(const struct cli_parsed *parsed, struct cli_context
|
||||
DEFINE_CMD(app_rhizome_extract, 0,
|
||||
"Export a manifest and payload file to the given paths, without decrypting.",
|
||||
"rhizome","export","bundle" KEYRING_PIN_OPTIONS,
|
||||
"<manifestid>","[<manifestpath>]","[<filepath>]");
|
||||
"[--zip-comment]","<manifestid>","[<manifestpath>]","[<filepath>]");
|
||||
DEFINE_CMD(app_rhizome_extract, 0,
|
||||
"Export a manifest from Rhizome and write it to the given path",
|
||||
"rhizome","export","manifest" KEYRING_PIN_OPTIONS,
|
||||
@ -512,7 +576,8 @@ static int app_rhizome_extract(const struct cli_parsed *parsed, struct cli_conte
|
||||
return -1;
|
||||
|
||||
int extract = strcasecmp(parsed->args[1], "extract")==0;
|
||||
|
||||
int zip_comment = 0 == cli_arg(parsed, "--zip-comment", NULL, NULL, NULL);
|
||||
|
||||
/* Ensure the Rhizome database exists and is open */
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
@ -577,13 +642,18 @@ static int app_rhizome_extract(const struct cli_parsed *parsed, struct cli_conte
|
||||
}
|
||||
}
|
||||
|
||||
if (ret==0 && zip_comment && pstatus == RHIZOME_PAYLOAD_STATUS_STORED){
|
||||
if (append_manifest_zip_comment(filepath, m) == -1)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret==0 && manifestpath && *manifestpath){
|
||||
if (strcmp(manifestpath, "-") == 0) {
|
||||
// always extract a manifest to stdout, even if writing the file itself failed.
|
||||
cli_field_name(context, "manifest", ":");
|
||||
cli_write(context, m->manifestdata, m->manifest_all_bytes);
|
||||
cli_delim(context, "\n");
|
||||
} else {
|
||||
} else if (!zip_comment) {
|
||||
int append = (strcmp(manifestpath, filepath)==0)?1:0;
|
||||
// don't write out the manifest if we were asked to append it and writing the file failed.
|
||||
if (!append || (pstatus == RHIZOME_PAYLOAD_STATUS_EMPTY || pstatus == RHIZOME_PAYLOAD_STATUS_STORED)) {
|
||||
|
@ -127,7 +127,7 @@ static int rhizome_direct_import_end(struct http_request *hr)
|
||||
return 0;
|
||||
}
|
||||
struct rhizome_bundle_result result = INVALID_RHIZOME_BUNDLE_RESULT;
|
||||
result.status = rhizome_bundle_import_files(m, NULL, manifest_path, payload_path);
|
||||
result.status = rhizome_bundle_import_files(m, NULL, manifest_path, payload_path, 0);
|
||||
rhizome_manifest_free(m);
|
||||
rhizome_direct_clear_temporary_files(r);
|
||||
http_request_rhizome_bundle_status_response(r, result, NULL);
|
||||
|
@ -609,23 +609,29 @@ int rhizome_write_buffer(struct rhizome_write *write_state, uint8_t *buffer, siz
|
||||
/* If file_length is known, then expects file to be at least file_length in size, ignoring anything
|
||||
* longer than that. Returns 0 if successful, -1 if error (logged).
|
||||
*/
|
||||
int rhizome_write_file(struct rhizome_write *write, const char *filename)
|
||||
int rhizome_write_file(struct rhizome_write *write, const char *filename, off_t offset, uint64_t length)
|
||||
{
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return WHYF_perror("open(%s,O_RDONLY)", alloca_str_toprint(filename));
|
||||
unsigned char buffer[RHIZOME_CRYPT_PAGE_SIZE];
|
||||
int ret=0;
|
||||
while (write->file_length == RHIZOME_SIZE_UNSET || write->file_offset < write->file_length) {
|
||||
if (offset){
|
||||
if (lseek(fd, offset, SEEK_SET)==-1)
|
||||
return WHYF_perror("lseek(%d,%zu,SEEK_SET)", fd, (unsigned long long)offset);
|
||||
}
|
||||
if (length == RHIZOME_SIZE_UNSET || length > write->file_length)
|
||||
length = write->file_length;
|
||||
while (length == RHIZOME_SIZE_UNSET || write->file_offset < length) {
|
||||
size_t size = sizeof buffer;
|
||||
if (write->file_length != RHIZOME_SIZE_UNSET && write->file_offset + size > write->file_length)
|
||||
size = write->file_length - write->file_offset;
|
||||
if (length != RHIZOME_SIZE_UNSET && write->file_offset + size > length)
|
||||
size = length - write->file_offset;
|
||||
ssize_t r = read(fd, buffer, size);
|
||||
if (r == -1) {
|
||||
ret = WHYF_perror("read(%d,%p,%zu)", fd, buffer, size);
|
||||
break;
|
||||
}
|
||||
if (write->file_length != RHIZOME_SIZE_UNSET && (size_t) r != size) {
|
||||
if (length != RHIZOME_SIZE_UNSET && (size_t) r != size) {
|
||||
ret = WHYF("file truncated - read(%d,%p,%zu) returned %zu", fd, buffer, size, (size_t) r);
|
||||
break;
|
||||
}
|
||||
@ -847,7 +853,7 @@ enum rhizome_payload_status rhizome_import_payload_from_file(rhizome_manifest *m
|
||||
return status;
|
||||
|
||||
// file payload is not in the store yet
|
||||
if (rhizome_write_file(&write, filepath)){
|
||||
if (rhizome_write_file(&write, filepath, 0, RHIZOME_SIZE_UNSET)){
|
||||
rhizome_fail_write(&write);
|
||||
return RHIZOME_PAYLOAD_STATUS_ERROR;
|
||||
}
|
||||
@ -971,7 +977,7 @@ enum rhizome_payload_status rhizome_store_payload_file(rhizome_manifest *m, cons
|
||||
}
|
||||
if (!status_ok)
|
||||
FATALF("rhizome_write_open_manifest() returned status = %d", status);
|
||||
if (rhizome_write_file(&write, filepath) == -1)
|
||||
if (rhizome_write_file(&write, filepath, 0, RHIZOME_SIZE_UNSET) == -1)
|
||||
status = RHIZOME_PAYLOAD_STATUS_ERROR;
|
||||
else
|
||||
status = rhizome_finish_write(&write);
|
||||
@ -1382,7 +1388,7 @@ static int write_file(struct rhizome_read *read, const char *filepath){
|
||||
while((ret=rhizome_read(read, buffer, sizeof(buffer)))>0){
|
||||
if (fd!=-1){
|
||||
if (write(fd,buffer,ret)!=ret) {
|
||||
ret = WHY("Failed to write data to file");
|
||||
ret = WHY_perror("Failed to write data to file");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1677,7 +1683,7 @@ enum rhizome_payload_status rhizome_append_journal_file(rhizome_manifest *m, uin
|
||||
enum rhizome_payload_status status = rhizome_write_open_journal(&write, m, advance_by, stat.st_size);
|
||||
if (status != RHIZOME_PAYLOAD_STATUS_NEW)
|
||||
return status;
|
||||
if (stat.st_size != 0 && rhizome_write_file(&write, filename) == -1)
|
||||
if (stat.st_size != 0 && rhizome_write_file(&write, filename, 0, RHIZOME_SIZE_UNSET) == -1)
|
||||
status = RHIZOME_PAYLOAD_STATUS_ERROR;
|
||||
else
|
||||
status = rhizome_finish_write(&write);
|
||||
|
@ -1431,6 +1431,34 @@ test_ImportCombinedBundle() {
|
||||
assert diff fileA fileAx
|
||||
}
|
||||
|
||||
doc_ImportCombinedZipBundle="Create and import combined zip bundle"
|
||||
setup_ImportCombinedZipBundle() {
|
||||
# A "combined bundle" is a single file consisting of a payload with its
|
||||
# manifest appended to the end.
|
||||
setup_servald
|
||||
setup_rhizome
|
||||
echo "Hello from A" >fileA
|
||||
zip fileA.zip fileA
|
||||
}
|
||||
test_ImportCombinedZipBundle() {
|
||||
# Create the combined bundle
|
||||
executeOk_servald rhizome add file --zip-comment $SIDA fileA.zip fileA.manifest
|
||||
extract_manifest_id manifestid fileA.manifest
|
||||
extract_manifest_filehash filehash fileA.manifest
|
||||
extract_manifest_filesize filesize fileA.manifest
|
||||
# Import the combined bundle
|
||||
set_instance +B
|
||||
executeOk_servald rhizome import bundle --zip-comment fileA.zip fileA.zip
|
||||
assertStdoutGrep --matches=1 "^service:file$"
|
||||
assertStdoutGrep --matches=1 "^manifestid:$manifestid\$"
|
||||
assertStdoutGrep --matches=1 "^filehash:$filehash\$"
|
||||
assertStdoutGrep --matches=1 "^filesize:$filesize\$"
|
||||
executeOk_servald rhizome list
|
||||
assert_rhizome_list --fromhere=0 fileA.zip
|
||||
executeOk_servald rhizome export bundle --zip-comment $manifestid fileAx.zip fileAx.zip
|
||||
assert diff fileA.zip fileAx.zip
|
||||
}
|
||||
|
||||
doc_ImportJournal="Import a journal bundle"
|
||||
setup_ImportJournal() {
|
||||
B_IDENTITY_COUNT=1
|
||||
|
Loading…
Reference in New Issue
Block a user