diff --git a/rhizome.h b/rhizome.h index 1984d09f..efe8f531 100644 --- a/rhizome.h +++ b/rhizome.h @@ -413,6 +413,12 @@ struct rhizome_write{ sqlite3_blob *sql_blob; }; +struct rhizome_read_buffer{ + uint64_t offset; + unsigned char data[RHIZOME_CRYPT_PAGE_SIZE]; + int len; +}; + struct rhizome_read{ char id[SHA512_DIGEST_STRING_LENGTH+1]; @@ -685,6 +691,7 @@ int rhizome_exists(const char *fileHash); int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int64_t file_length, int priority); int rhizome_write_buffer(struct rhizome_write *write_state, unsigned char *buffer, int data_size); int rhizome_random_write(struct rhizome_write *write_state, int64_t offset, unsigned char *buffer, int data_size); +int rhizome_write_open_manifest(struct rhizome_write *write, rhizome_manifest *m); int rhizome_write_file(struct rhizome_write *write, const char *filename); int rhizome_fail_write(struct rhizome_write *write); int rhizome_finish_write(struct rhizome_write *write); @@ -701,6 +708,7 @@ int rhizome_crypt_xor_block(unsigned char *buffer, int buffer_size, int64_t stre const unsigned char *key, const unsigned char *nonce); int rhizome_open_read(struct rhizome_read *read, const char *fileid, int hash); int rhizome_read(struct rhizome_read *read, unsigned char *buffer, int buffer_length); +int rhizome_read_buffered(struct rhizome_read *read, struct rhizome_read_buffer *buffer, unsigned char *data, int len); int rhizome_read_close(struct rhizome_read *read); int rhizome_store_delete(const char *id); int rhizome_open_decrypt_read(rhizome_manifest *m, rhizome_bk_t *bsk, struct rhizome_read *read_state, int hash); diff --git a/rhizome_store.c b/rhizome_store.c index c66132f9..eda05322 100644 --- a/rhizome_store.c +++ b/rhizome_store.c @@ -598,6 +598,16 @@ static int rhizome_write_derive_key(rhizome_manifest *m, rhizome_bk_t *bsk, stru return 0; } +int rhizome_write_open_manifest(struct rhizome_write *write, rhizome_manifest *m) +{ + if (rhizome_open_write(write, NULL, m->fileLength, RHIZOME_PRIORITY_DEFAULT)) + return -1; + + if (rhizome_write_derive_key(m, NULL, write)) + return -1; + return 0; +} + // import a file for a new bundle with an unknown file hash // update the manifest with the details of the file int rhizome_add_file(rhizome_manifest *m, const char *filepath) @@ -606,16 +616,10 @@ int rhizome_add_file(rhizome_manifest *m, const char *filepath) struct rhizome_write write; bzero(&write, sizeof(write)); - if (rhizome_open_write(&write, NULL, m->fileLength, RHIZOME_PRIORITY_DEFAULT)) - return -1; - - if (rhizome_write_derive_key(m, NULL, &write)) - return -1; - - if (rhizome_write_file(&write, filepath)){ - rhizome_fail_write(&write); - return -1; - } + if (rhizome_write_open_manifest(&write, m)) + goto failure; + if (rhizome_write_file(&write, filepath)) + goto failure; if (rhizome_finish_write(&write)) goto failure; @@ -740,6 +744,51 @@ int rhizome_read(struct rhizome_read *read_state, unsigned char *buffer, int buf OUT(); } +/* Read len bytes from read->offset into data, using *buffer to cache any reads */ +int rhizome_read_buffered(struct rhizome_read *read, struct rhizome_read_buffer *buffer, unsigned char *data, int len) +{ + while (len>0){ + // if we can supply either the beginning or end of the data from cache, do that first. + uint64_t ofs=read->offset - buffer->offset; + if (ofs>=0 && ofs<=buffer->len){ + int size=len; + if (size > buffer->len - ofs) + size = buffer->len - ofs; + if (size>0){ + // copy into the start of the data buffer + bcopy(buffer->data + ofs, data, size); + data+=size; + len-=size; + read->offset+=size; + continue; + } + } + + ofs = (read->offset+len) - buffer->offset; + if (ofs>0 && ofs<=buffer->len){ + int size=len; + if (size > ofs) + size = ofs; + if (size>0){ + // copy into the end of the data buffer + bcopy(buffer->data + ofs - size, data + len - size, size); + len-=size; + continue; + } + } + + // ok, so we need to read a new buffer to fulfill the request. + // remember the requested read offset so we can put it back + ofs = read->offset; + buffer->offset = read->offset = ofs & ~(RHIZOME_CRYPT_PAGE_SIZE -1); + buffer->len = rhizome_read(read, buffer->data, sizeof(buffer->data)); + read->offset = ofs; + if (buffer->len<=0) + return buffer->len; + } + return 0; +} + int rhizome_read_close(struct rhizome_read *read) { if (read->blob_fd >=0){