mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-20 17:33:08 +00:00
Add "rhizome extract manifest" command
This commit is contained in:
parent
c9e429e36b
commit
146eb7cdfd
@ -1024,6 +1024,48 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cli_manifestid(const char *arg)
|
||||
{
|
||||
return rhizome_str_is_manifest_id(arg);
|
||||
}
|
||||
|
||||
int app_rhizome_extract_manifest(int argc, const char *const *argv, struct command_line_option *o)
|
||||
{
|
||||
const char *manifestid, *manifestpath;
|
||||
cli_arg(argc, argv, o, "manifestid", &manifestid, cli_manifestid, NULL);
|
||||
cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "");
|
||||
/* Ensure the Rhizome database exists and is open */
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
rhizome_datastore_path = serval_instancepath();
|
||||
rhizome_opendb();
|
||||
/* Extract the manifest from the database */
|
||||
rhizome_manifest *m = NULL;
|
||||
int ret = -1;
|
||||
switch (rhizome_retrieve_manifest(manifestid, &m)) {
|
||||
case 0:
|
||||
ret = 0;
|
||||
break;
|
||||
case 1:
|
||||
ret = 0;
|
||||
if (manifestpath[0]) {
|
||||
if (rhizome_manifest_finalise(m, 1) == -1)
|
||||
ret = WHY("Could not overwrite manifest file.");
|
||||
else if (rhizome_write_manifest_file(m, manifestpath) == -1)
|
||||
ret = WHY("Could not overwrite manifest file.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (m)
|
||||
rhizome_manifest_free(m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int app_rhizome_extract_file(int argc, const char *const *argv, struct command_line_option *o)
|
||||
{
|
||||
return WHY("Not implemented");
|
||||
}
|
||||
|
||||
int cli_uint(const char *arg)
|
||||
{
|
||||
register const char *s = arg;
|
||||
@ -1328,6 +1370,10 @@ command_line_option command_line_options[]={
|
||||
"Add a file to Rhizome and optionally write its manifest to the given path"},
|
||||
{app_rhizome_list,{"rhizome","list","[<offset>]","[<limit>]",NULL},CLIFLAG_STANDALONE,
|
||||
"List all manifests and files in Rhizome"},
|
||||
{app_rhizome_extract_manifest,{"rhizome","extract","manifest","<manifestid>","<manifestpath>",NULL},CLIFLAG_STANDALONE,
|
||||
"Extract a manifest from Rhizome and write it to the given path"},
|
||||
{app_rhizome_extract_file,{"rhizome","extract","file","<fileid>","<filepath>",NULL},CLIFLAG_STANDALONE,
|
||||
"Extract a file from Rhizome and write it to the given path"},
|
||||
{app_keyring_create,{"keyring","create",NULL},0,
|
||||
"Create a new keyring file."},
|
||||
{app_keyring_list,{"keyring","list","[<pin,pin ...>]",NULL},CLIFLAG_STANDALONE,
|
||||
|
@ -303,7 +303,7 @@ int chartonybl(int c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rhizome_hex_to_bytes(char *in,unsigned char *out,int hexChars)
|
||||
int rhizome_hex_to_bytes(const char *in,unsigned char *out,int hexChars)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -160,6 +160,8 @@ extern sqlite3 *rhizome_db;
|
||||
|
||||
int rhizome_opendb();
|
||||
int rhizome_manifest_createid(rhizome_manifest *m);
|
||||
int rhizome_strn_is_manifest_id(const char *id);
|
||||
int rhizome_str_is_manifest_id(const char *id);
|
||||
int rhizome_write_manifest_file(rhizome_manifest *m, const char *filename);
|
||||
int rhizome_manifest_sign(rhizome_manifest *m);
|
||||
int rhizome_drop_stored_file(char *id,int maximum_priority);
|
||||
@ -190,7 +192,7 @@ int rhizome_add_manifest(rhizome_manifest *m_in, rhizome_manifest **m_out, const
|
||||
int verifyP, int checkFileP, int signP);
|
||||
int rhizome_manifest_finalise(rhizome_manifest *m,int signP);
|
||||
char *rhizome_bytes_to_hex(unsigned char *in,int byteCount);
|
||||
int rhizome_hex_to_bytes(char *in,unsigned char *out,int hexChars);
|
||||
int rhizome_hex_to_bytes(const char *in,unsigned char *out,int hexChars);
|
||||
int rhizome_store_keypair_bytes(unsigned char *p,unsigned char *s);
|
||||
int rhizome_find_keypair_bytes(unsigned char *p,unsigned char *s);
|
||||
rhizome_signature *rhizome_sign_hash(unsigned char *hash,unsigned char *publicKeyBytes);
|
||||
@ -214,6 +216,7 @@ int rhizome_manifest_to_bar(rhizome_manifest *m,unsigned char *bar);
|
||||
char nybltochar(int n);
|
||||
int rhizome_queue_manifest_import(rhizome_manifest *m,struct sockaddr_in *peerip);
|
||||
int rhizome_list_manifests(int limit, int offset);
|
||||
int rhizome_retrieve_manifest(const char *id, rhizome_manifest **mp);
|
||||
|
||||
#define RHIZOME_DONTVERIFY 0
|
||||
#define RHIZOME_VERIFY 1
|
||||
|
@ -20,6 +20,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include "serval.h"
|
||||
#include "rhizome.h"
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int rhizome_strn_is_manifest_id(const char *id)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i != crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES * 2; ++i)
|
||||
if (!isxdigit(id[i]))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rhizome_str_is_manifest_id(const char *id)
|
||||
{
|
||||
size_t len = strlen(id);
|
||||
return len == crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES * 2 && rhizome_strn_is_manifest_id(id);
|
||||
}
|
||||
|
||||
int rhizome_manifest_createid(rhizome_manifest *m)
|
||||
{
|
||||
|
@ -840,3 +840,80 @@ int rhizome_find_duplicate(const rhizome_manifest *m, rhizome_manifest **found)
|
||||
sqlite3_finalize(statement);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Retrieve a manifest from the database, given its manifest ID.
|
||||
|
||||
Returns 1 if manifest is found (new manifest is allocated and assigned to *m, caller is
|
||||
responsible for freeing).
|
||||
|
||||
Returns 0 if manifest is not found (*m is unchanged).
|
||||
|
||||
Returns -1 on error (*m is unchanged).
|
||||
*/
|
||||
int rhizome_retrieve_manifest(const char *id, rhizome_manifest **mp)
|
||||
{
|
||||
char sqlcmd[1024];
|
||||
int n = snprintf(sqlcmd, sizeof(sqlcmd), "SELECT id, manifest, version, inserttime FROM manifests WHERE id = ?");
|
||||
if (n >= sizeof(sqlcmd))
|
||||
return WHY("SQL command too long");
|
||||
sqlite3_stmt *statement;
|
||||
const char *cmdtail;
|
||||
int ret = 0;
|
||||
rhizome_manifest *m = NULL;
|
||||
if (sqlite3_prepare_v2(rhizome_db, sqlcmd, strlen(sqlcmd) + 1, &statement, &cmdtail) != SQLITE_OK) {
|
||||
sqlite3_finalize(statement);
|
||||
ret = WHY(sqlite3_errmsg(rhizome_db));
|
||||
} else {
|
||||
sqlite3_bind_text(statement, 1, id, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES * 2, SQLITE_STATIC);
|
||||
while (sqlite3_step(statement) == SQLITE_ROW) {
|
||||
if (!( sqlite3_column_count(statement) == 4
|
||||
&& sqlite3_column_type(statement, 0) == SQLITE_TEXT
|
||||
&& sqlite3_column_type(statement, 1) == SQLITE_BLOB
|
||||
&& sqlite3_column_type(statement, 2) == SQLITE_INTEGER
|
||||
&& sqlite3_column_type(statement, 3) == SQLITE_INTEGER
|
||||
)) {
|
||||
ret = WHY("Incorrect statement column");
|
||||
break;
|
||||
}
|
||||
const char *manifestblob = (char *) sqlite3_column_blob(statement, 1);
|
||||
size_t manifestblobsize = sqlite3_column_bytes(statement, 1); // must call after sqlite3_column_blob()
|
||||
m = rhizome_read_manifest_file(manifestblob, manifestblobsize, 0);
|
||||
if (m == NULL) {
|
||||
ret = WHY("Invalid manifest blob from database");
|
||||
} else {
|
||||
rhizome_hex_to_bytes(id, m->cryptoSignPublic, crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES*2);
|
||||
const char *filehashq = rhizome_manifest_get(m, "filehash", NULL, 0);
|
||||
if (filehashq == NULL)
|
||||
ret = WHY("Manifest is missing filehash line");
|
||||
else {
|
||||
memcpy(m->fileHexHash, filehashq, SHA512_DIGEST_STRING_LENGTH);
|
||||
m->fileHashedP = 1;
|
||||
}
|
||||
long long versionq = rhizome_manifest_get_ll(m, "version");
|
||||
if (versionq == -1)
|
||||
ret = WHY("Manifest is missing version line");
|
||||
else
|
||||
m->version = versionq;
|
||||
long long lengthq = rhizome_manifest_get_ll(m, "filesize");
|
||||
if (lengthq == -1)
|
||||
ret = WHY("Manifest is missing filesize line");
|
||||
else
|
||||
m->fileLength = lengthq;
|
||||
cli_puts("manifestid"); cli_delim(":");
|
||||
cli_puts((const char *)sqlite3_column_text(statement, 0)); cli_delim("\n");
|
||||
cli_puts("version"); cli_delim(":");
|
||||
cli_printf("%lld", (long long) sqlite3_column_int64(statement, 2)); cli_delim("\n");
|
||||
cli_puts("inserttime"); cli_delim(":");
|
||||
cli_printf("%lld", (long long) sqlite3_column_int64(statement, 3)); cli_delim("\n");
|
||||
// Could write the manifest blob to the CLI output here, but that would require the output to
|
||||
// support byte[] fields as well as String fields.
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
if (ret > 0)
|
||||
*mp = m;
|
||||
return ret;
|
||||
}
|
||||
|
@ -34,15 +34,17 @@ assert_rhizome_list() {
|
||||
local filename
|
||||
for filename; do
|
||||
local filehash='[^:]\+'
|
||||
local manifestid='[^:]\+'
|
||||
# If there is a manifest file that looks like it matches this payload
|
||||
# file, then use its file hash to check the rhizome list output.
|
||||
if [ -r "$filename.manifest" ]; then
|
||||
local name=$(sed -n -e '/^name=/s///p' "$filename.manifest")
|
||||
if [ "$name" == "$filename" ]; then
|
||||
filehash=$(sed -n -e '/^filehash=/s///p' "$filename.manifest")
|
||||
manifestid=$(sed -n -e '/^id=/s///p' "$filename.manifest")
|
||||
fi
|
||||
fi
|
||||
assertStdoutGrep --matches=1 "^$filehash:.*:$filename\$"
|
||||
assertStdoutGrep --matches=1 "^$filehash:$manifestid:.*:$filename\$"
|
||||
done
|
||||
}
|
||||
|
||||
@ -65,6 +67,14 @@ strip_signatures() {
|
||||
done
|
||||
}
|
||||
|
||||
extract_manifest_id() {
|
||||
local _var="$1"
|
||||
local _manifestfile="$2"
|
||||
local _id=$(sed -n -e '/^id=[0-9a-fA-F]\{64\}$/s/^id=//p' "$_manifestfile")
|
||||
assert --message="$_manifestfile contains valid 'id=' line" [ -n "$_id" ]
|
||||
[ -n "$_var" ] && eval $_var=$_id
|
||||
}
|
||||
|
||||
extract_manifest_version() {
|
||||
local _var="$1"
|
||||
local _manifestfile="$2"
|
||||
@ -116,7 +126,7 @@ test_AddNonExistManifest() {
|
||||
assertGrep file1.manifest '^name=file1$'
|
||||
assertGrep file1.manifest '^date=[0-9]\+$'
|
||||
assertGrep file1.manifest '^version=[0-9]\+$'
|
||||
assertGrep file1.manifest '^id=[0-9a-fA-F]\+$'
|
||||
assertGrep file1.manifest '^id=[0-9a-fA-F]\{64\}$'
|
||||
assertGrep file1.manifest "^filesize=$size\$"
|
||||
assertGrep file1.manifest "^first_byte=0$"
|
||||
assertGrep file1.manifest "^last_byte=$size\$"
|
||||
@ -136,10 +146,10 @@ test_AddManifest() {
|
||||
tfw_cat --stderr
|
||||
tfw_cat -v file1.manifest
|
||||
local size=$(( $(cat file1 | wc -c) + 0 ))
|
||||
assertGrep file1.manifest '^id=[0-9a-fA-F]\{64\}$'
|
||||
assertGrep file1.manifest '^name=wah$'
|
||||
assertGrep file1.manifest '^date=12345$'
|
||||
assertGrep file1.manifest '^version=[0-9]\+$'
|
||||
assertGrep file1.manifest '^id=[0-9a-fA-F]\+$'
|
||||
assertGrep file1.manifest '^date=12345$'
|
||||
assertGrep file1.manifest "^filesize=$size\$"
|
||||
assertGrep file1.manifest "^first_byte=0$"
|
||||
assertGrep file1.manifest "^last_byte=$size\$"
|
||||
@ -161,6 +171,19 @@ test_AddThenList() {
|
||||
assert_rhizome_list file1 file2
|
||||
}
|
||||
|
||||
doc_ExtractManifest="Extract manifest after one add"
|
||||
setup_ExtractManifest() {
|
||||
setup_dna_rhizome
|
||||
echo "A test file" >file1
|
||||
executeOk $dna rhizome add file file1 file1.manifest
|
||||
assert_rhizome_list file1
|
||||
extract_manifest_id manifestid file1.manifest
|
||||
}
|
||||
test_ExtractManifest() {
|
||||
executeOk $dna rhizome extract manifest $manifestid file1x.manifest
|
||||
assert cmp file1.manifest file1x.manifest
|
||||
}
|
||||
|
||||
doc_AddDuplicate="Add same manifest detects duplicate"
|
||||
setup_AddDuplicate() {
|
||||
setup_dna_rhizome
|
||||
|
Loading…
x
Reference in New Issue
Block a user