Improve "rhizome add file" for empty payloads

Accept the empty string for a payload pathname to mean a zero-length
payload.
This commit is contained in:
Andrew Bettison 2012-06-05 15:45:53 +09:30
parent a9ad1b6afc
commit b14db5c28b
5 changed files with 83 additions and 43 deletions

View File

@ -105,7 +105,7 @@ int rhizome_manifest_check_sanity(rhizome_manifest *m_in)
return WHY("Manifest missing 'date' field");
if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) {
const char *name = rhizome_manifest_get(m_in, "name", NULL, 0);
if (name == NULL || !name[0])
if (name == NULL)
return WHY("Manifest missing 'name' field");
} else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) {
if (sender == NULL || !sender[0])
@ -178,11 +178,14 @@ int rhizome_manifest_bind_file(rhizome_manifest *m_in,const char *filename,int e
if (encryptP) rhizome_manifest_set_ll(m_in,"crypt",1);
else rhizome_manifest_set_ll(m_in,"crypt",0);
/* Get length of payload */
struct stat stat;
if (lstat(filename,&stat))
return WHYF("Could not stat() payload file '%s'",filename);
m_in->fileLength = stat.st_size;
/* Get length of payload. An empty filename means empty payload. */
if (filename[0]) {
struct stat stat;
if (lstat(filename,&stat))
return WHYF("Could not stat() payload file '%s'",filename);
m_in->fileLength = stat.st_size;
} else
m_in->fileLength = 0;
if (debug & DEBUG_RHIZOME)
DEBUGF("filename=%s, fileLength=%lld", filename, m_in->fileLength);
rhizome_manifest_set_ll(m_in,"filesize",m_in->fileLength);
@ -214,10 +217,13 @@ int rhizome_manifest_check_file(rhizome_manifest *m_in)
/* Check payload file is accessible and discover its length, then check that it matches
the file size stored in the manifest */
struct stat stat;
if (lstat(m_in->dataFileName,&stat))
return WHYF("Could not stat() payload file '%s'",m_in->dataFileName);
m_in->fileLength = stat.st_size;
if (m_in->dataFileName[0]) {
struct stat stat;
if (lstat(m_in->dataFileName,&stat))
return WHYF("Could not stat() payload file '%s'",m_in->dataFileName);
m_in->fileLength = stat.st_size;
} else
m_in->fileLength = 0;
if (debug & DEBUG_RHIZOME)
DEBUGF("filename=%s, fileLength=%lld", m_in->dataFileName, m_in->fileLength);
long long mfilesize = rhizome_manifest_get_ll(m_in, "filesize");

View File

@ -202,31 +202,33 @@ int rhizome_hash_file(rhizome_manifest *m,const char *filename,char *hash_out)
and may be very resource constrained. Thus we need a streamable SHA-512
implementation.
*/
#warning need to implement encryption
if (m&&m->payloadEncryption)
// TODO encrypted payloads
if (m && m->payloadEncryption)
return WHY("Encryption of payloads not implemented");
FILE *f = fopen(filename, "r");
if (!f) {
WHY_perror("fopen");
return WHYF("Could not open %s to calculate SHA512 hash.", filename);
}
SHA512_CTX context;
SHA512_Init(&context);
while (!feof(f)) {
unsigned char buffer[8192];
int r = fread(buffer, 1, 8192, f);
if (r == -1) {
WHY_perror("fread");
fclose(f);
return WHYF("Error reading %s to calculate SHA512 hash", filename);
if (filename[0]) {
FILE *f = fopen(filename, "r");
if (!f) {
WHY_perror("fopen");
return WHYF("Could not open %s to calculate SHA512 hash.", filename);
}
if (r > 0)
SHA512_Update(&context, buffer, r);
while (!feof(f)) {
unsigned char buffer[8192];
int r = fread(buffer, 1, 8192, f);
if (r == -1) {
WHY_perror("fread");
fclose(f);
return WHYF("Error reading %s to calculate SHA512 hash", filename);
}
if (r > 0)
SHA512_Update(&context, buffer, r);
}
fclose(f);
}
SHA512_End(&context, (char *)hash_out);
str_toupper_inplace(hash_out);
fclose(f);
return 0;
}
@ -543,11 +545,15 @@ int rhizome_manifest_finalise(rhizome_manifest *m)
m->fileHashedP=1;
/* set fileLength */
struct stat stat;
if (lstat(m->dataFileName,&stat)) {
return WHY("Could not stat() associated file");
}
m->fileLength=stat.st_size;
if (m->dataFileName[0]) {
struct stat stat;
if (lstat(m->dataFileName, &stat)) {
WHY_perror("lstat");
return WHY("Could not stat() associated file");
}
m->fileLength = stat.st_size;
} else
m->fileLength = 0;
}
/* Set file hash and size information */

View File

@ -514,7 +514,7 @@ int rhizome_store_bundle(rhizome_manifest *m)
// we should add the file in the same transaction, but closing the blob seems to cause some issues.
/* Store the file */
#warning need to implement passing of encryption key for file here
// TODO encrypted payloads - pass encryption key here
if (m->fileLength>0){
if (rhizome_store_file(m,NULL)){
WHY("Could not store file");
@ -724,10 +724,14 @@ int rhizome_store_file(rhizome_manifest *m,const unsigned char *key)
return WHY("Cannot store bundle file until it has been hashed");
int fd=open(file,O_RDONLY);
if (fd<0) return WHY("Could not open associated file");
if (fd == -1) {
WHY_perror("open");
return WHY("Could not open associated file");
}
struct stat stat;
if (fstat(fd,&stat)) {
WHY_perror("fstat");
close(fd);
return WHY("Could not stat() associated file");
}
@ -737,9 +741,9 @@ int rhizome_store_file(rhizome_manifest *m,const unsigned char *key)
WARNF("File has grown by %lld bytes. I will just store the original number of bytes so that the hash (hopefully) matches",stat.st_size-m->fileLength);
}
unsigned char *addr =
mmap(NULL, m->fileLength, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
unsigned char *addr = mmap(NULL, m->fileLength, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0);
if (addr==MAP_FAILED) {
WHY_perror("mmap");
close(fd);
return WHY("mmap() of associated file failed.");
}

View File

@ -865,11 +865,10 @@ _tfw_failexit() {
_tfw_errormsg() {
[ $# -eq 0 ] && set -- "(no message)"
local -i up=1
while true; do
case ${FUNCNAME[$up]} in
_tfw_*) let up=up+1;;
*) break;;
esac
local -i top=${#FUNCNAME[*]}
let top=top-1
while [ $up -lt $top -a "${BASH_SOURCE[$up]}" == "${BASH_SOURCE[0]}" ]; do
let up=up+1
done
echo "ERROR in ${FUNCNAME[$up]}: $*"
}

View File

@ -69,7 +69,8 @@ assert_rhizome_list() {
}
assert_stdout_add_file() {
local filename="$1"
[ $# -ge 1 ] || error "missing filename arg"
local filename="${1}"
unpack_manifest_for_grep "$filename"
assertStdoutLineCount '==' 6
assertStdoutGrep --matches=1 "^service:$re_service\$"
@ -83,7 +84,11 @@ assert_stdout_add_file() {
unpack_manifest_for_grep() {
local filename="$1"
re_service="$rexp_service"
re_size=$(( $(cat "$filename" | wc -c) + 0 ))
if [ -n "$filename" ]; then
re_size=$(( $(cat "$filename" | wc -c) + 0 ))
else
re_size=0
fi
compute_filehash re_filehash "$filename"
re_manifestid="$rexp_manifestid"
re_secret="$rexp_bundlesecret"
@ -279,6 +284,26 @@ test_AddManifest() {
assertGrep file1.manifest "^filesize=$re_size\$"
}
doc_AddEmpty="Add with empty payload"
setup_AddEmpty() {
setup_servald_rhizome
executeOk $servald rhizome list
assert_rhizome_list
}
test_AddEmpty() {
executeOk $servald rhizome add file $sid '' '' .manifest
tfw_cat --stdout --stderr -v .manifest
assert_stdout_add_file ''
assertGrep .manifest '^service=file$'
assertGrep .manifest "^BK=$rexp_bundlekey\$"
assertGrep .manifest '^name=$'
assertGrep .manifest "^version=$rexp_version\$"
assertGrep .manifest "^date=$rexp_date\$"
assertGrep .manifest "^id=$re_manifestid\$"
assertGrep .manifest "^filehash=$re_filehash\$"
assertGrep .manifest '^filesize=0$'
}
doc_AddThenList="List contains one file after one add"
setup_AddThenList() {
setup_servald_rhizome