mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-29 15:43:56 +00:00
Overhaul rhizome datastore path code
Create datastore directory and all parent dirs if it does not exist More robust error checking and buffer overflow protection New mkdirs() and mkdirsn() functions
This commit is contained in:
parent
67e6c7ae2a
commit
b02e9b9ac4
41
dna.c
41
dna.c
@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <alloca.h>
|
||||
|
||||
char *gatewayspec=NULL;
|
||||
|
||||
@ -307,6 +308,46 @@ int create_serval_instance_dir() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdirs(const char *path)
|
||||
{
|
||||
return mkdirsn(path, strlen(path));
|
||||
}
|
||||
|
||||
int mkdirsn(const char *path, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return WHY("Bug: empty path");
|
||||
char *pathfrag = alloca(len + 1);
|
||||
strncpy(pathfrag, path, len);
|
||||
pathfrag[len] = '\0';
|
||||
if (mkdir(pathfrag, 0700) != -1)
|
||||
return 0;
|
||||
if (errno == EEXIST) {
|
||||
DIR *d = opendir(pathfrag);
|
||||
if (!d) {
|
||||
WHY_perror("opendir");
|
||||
return WHYF("cannot access %s", pathfrag);
|
||||
}
|
||||
closedir(d);
|
||||
return 0;
|
||||
}
|
||||
if (errno == ENOENT) {
|
||||
const char *lastsep = path + len - 1;
|
||||
while (lastsep != path && *--lastsep != '/')
|
||||
;
|
||||
while (lastsep != path && *--lastsep == '/')
|
||||
;
|
||||
if (lastsep != path) {
|
||||
if (mkdirsn(path, lastsep - path + 1) == -1)
|
||||
return -1;
|
||||
if (mkdir(pathfrag, 0700) != -1)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
WHY_perror("mkdir");
|
||||
return WHYF("cannot mkdir %s", pathfrag);
|
||||
}
|
||||
|
||||
int setVerbosity(const char *optarg) {
|
||||
long long old_debug=debug;
|
||||
debug=strtoll(optarg,NULL,10);
|
||||
|
@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
file and object buffers and lifetimes.
|
||||
*/
|
||||
|
||||
int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, char *bundle,
|
||||
int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, const char *bundle,
|
||||
char *groups[], int ttl,
|
||||
int verifyP, int checkFileP, int signP)
|
||||
{
|
||||
@ -36,10 +36,9 @@ int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, char
|
||||
|
||||
char filename[1024];
|
||||
char manifestname[1024];
|
||||
if (snprintf(filename, sizeof(filename), "%s/import/file.%s", rhizome_datastore_path, bundle) >= sizeof(filename)
|
||||
|| snprintf(manifestname, sizeof(manifestname), "%s/import/manifest.%s", rhizome_datastore_path, bundle) >= sizeof(manifestname)) {
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(filename, "import/file.%s", bundle)
|
||||
|| !FORM_RHIZOME_DATASTORE_PATH(manifestname, "import/manifest.%s", bundle))
|
||||
return WHY("Manifest bundle name too long");
|
||||
}
|
||||
|
||||
/* Read manifest file if no manifest was given */
|
||||
rhizome_manifest *m = m_in;
|
||||
|
@ -155,6 +155,13 @@ typedef struct rhizome_manifest {
|
||||
|
||||
extern long long rhizome_space;
|
||||
extern const char *rhizome_datastore_path;
|
||||
int form_rhizome_datastore_path(char * buf, size_t bufsiz, const char *fmt, ...);
|
||||
int create_rhizome_datastore_dir();
|
||||
|
||||
/* Handy statement for forming the path of a rhizome store file in a char buffer whose declaration
|
||||
* is in scope (so that sizeof(buf) will work). Evaluates to true if the pathname fitted into
|
||||
* the provided buffer, false (0) otherwise (after printing a message to stderr). */
|
||||
#define FORM_RHIZOME_DATASTORE_PATH(buf,fmt,...) (form_rhizome_datastore_path((buf), sizeof(buf), (fmt), ##__VA_ARGS__))
|
||||
|
||||
extern sqlite3 *rhizome_db;
|
||||
|
||||
@ -186,7 +193,7 @@ int rhizome_manifest_add_group(rhizome_manifest *m,char *groupid);
|
||||
int rhizome_store_file(const char *file,char *hash,int priortity);
|
||||
char *rhizome_safe_encode(unsigned char *in,int len);
|
||||
int rhizome_finish_sqlstatement(sqlite3_stmt *statement);
|
||||
int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, char *bundle,
|
||||
int rhizome_bundle_import(rhizome_manifest *m_in, rhizome_manifest **m_out, const char *bundle,
|
||||
char *groups[], int ttl,
|
||||
int verifyP, int checkFileP, int signP);
|
||||
int rhizome_add_manifest(rhizome_manifest *m_in, rhizome_manifest **m_out, const char *filename,
|
||||
|
@ -24,6 +24,41 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
long long rhizome_space=0;
|
||||
const char *rhizome_datastore_path = NULL;
|
||||
|
||||
int form_rhizome_datastore_path(char * buf, size_t bufsiz, const char *fmt, ...)
|
||||
{
|
||||
char *bufp = buf;
|
||||
char *bufe = bufp + bufsiz - 1;
|
||||
if (!rhizome_datastore_path) {
|
||||
WHY("Cannot open rhizome database -- no path specified");
|
||||
return 0;
|
||||
}
|
||||
bufp += snprintf(bufp, bufe - buf, "%s/", rhizome_datastore_path);
|
||||
if (bufp > bufe) {
|
||||
WHY("Path buffer overrun");
|
||||
return 0;
|
||||
}
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
va_list ap2;
|
||||
va_copy(ap2, ap);
|
||||
bufp += vsnprintf(bufp, bufe - bufp, fmt, ap2);
|
||||
va_end(ap);
|
||||
if (bufp > bufe) {
|
||||
WHY("Path buffer overrun");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int create_rhizome_datastore_dir()
|
||||
{
|
||||
if (!rhizome_datastore_path) {
|
||||
WHY("Cannot create rhizome database -- no path specified");
|
||||
return 0;
|
||||
}
|
||||
return mkdirs(rhizome_datastore_path);
|
||||
}
|
||||
|
||||
sqlite3 *rhizome_db=NULL;
|
||||
|
||||
/* XXX Requires a messy join that might be slow. */
|
||||
@ -36,16 +71,10 @@ int rhizome_manifest_priority(char *id)
|
||||
int rhizome_opendb()
|
||||
{
|
||||
if (rhizome_db) return 0;
|
||||
char dbname[1024];
|
||||
|
||||
if (!rhizome_datastore_path) {
|
||||
fprintf(stderr,"Cannot open rhizome database -- no path specified\n");
|
||||
char dbname[1024];
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(dbname, "rhizome.db"))
|
||||
exit(1);
|
||||
}
|
||||
if (snprintf(dbname, sizeof(dbname), "%s/rhizome.db", rhizome_datastore_path) >= sizeof(dbname)) {
|
||||
fprintf(stderr,"Cannot open rhizome database -- data store path is too long\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int r=sqlite3_open(dbname,&rhizome_db);
|
||||
if (r) {
|
||||
|
@ -335,11 +335,9 @@ int rhizome_queue_manifest_import(rhizome_manifest *m,
|
||||
peeraddr.sin_port=htons(RHIZOME_HTTP_PORT);
|
||||
int r=connect(sock,(struct sockaddr*)&peeraddr,sizeof(peeraddr));
|
||||
if ((errno!=EINPROGRESS)&&(r!=0)) {
|
||||
WHY_perror("connect");
|
||||
close (sock);
|
||||
if (debug&DEBUG_RHIZOME) {
|
||||
WHY("Failed to open socket to peer's rhizome web server");
|
||||
WHY_perror("connect");
|
||||
}
|
||||
if (debug&DEBUG_RHIZOME) WHY("Failed to open socket to peer's rhizome web server");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -361,19 +359,27 @@ int rhizome_queue_manifest_import(rhizome_manifest *m,
|
||||
/* XXX Don't forget to implement resume */
|
||||
#define RHIZOME_IDLE_TIMEOUT 10
|
||||
/* XXX We should stream file straight into the database */
|
||||
const char *id = rhizome_manifest_get(q->manifest, "id", NULL, 0);
|
||||
if (id == NULL) {
|
||||
close(sock);
|
||||
return WHY("Manifest missing ID");
|
||||
}
|
||||
char filename[1024];
|
||||
snprintf(filename,1024,"%s/import/file.%s",rhizome_datastore_path,
|
||||
rhizome_manifest_get(q->manifest,"id",NULL,0));
|
||||
q->manifest->dataFileName=strdup(filename);
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(filename, "import/file.%s", id)) {
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
q->manifest->dataFileName = strdup(filename);
|
||||
q->file=fopen(filename,"w");
|
||||
if (!q->file) {
|
||||
WHY_perror("fopen");
|
||||
if (debug&DEBUG_RHIZOME)
|
||||
fprintf(stderr,"Could not open '%s' to write received file.\n",
|
||||
filename);
|
||||
} else {
|
||||
rhizome_file_fetch_queue_count++;
|
||||
if (debug&DEBUG_RHIZOME) fprintf(stderr,"Queued file for fetching\n");
|
||||
DEBUGF("Could not open '%s' to write received file.", filename);
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
rhizome_file_fetch_queue_count++;
|
||||
if (debug&DEBUG_RHIZOME) DEBUGF("Queued file for fetching");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
@ -389,12 +395,14 @@ int rhizome_queue_manifest_import(rhizome_manifest *m,
|
||||
m->finalised=1;
|
||||
m->fileHashedP=1;
|
||||
m->manifest_bytes=m->manifest_all_bytes;
|
||||
const char *id = rhizome_manifest_get(m, "id", NULL, 0);
|
||||
if (id == NULL)
|
||||
return WHY("Manifest missing ID");
|
||||
char filename[1024];
|
||||
snprintf(filename,1024,"%s/import/manifest.%s",
|
||||
rhizome_datastore_path,
|
||||
rhizome_manifest_get(m,"id",NULL,0));
|
||||
if (!rhizome_write_manifest_file(m,filename)) {
|
||||
rhizome_bundle_import(m, NULL, rhizome_manifest_get(m,"id",NULL,0),
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH(filename, "import/manifest.%s", id))
|
||||
return -1;
|
||||
if (!rhizome_write_manifest_file(m, filename)) {
|
||||
rhizome_bundle_import(m, NULL, id,
|
||||
NULL /* no additional groups */,
|
||||
m->ttl-1 /* TTL */,
|
||||
1 /* do verify */,
|
||||
@ -507,10 +515,12 @@ int rhizome_fetch_poll()
|
||||
if (debug&DEBUG_RHIZOME) fprintf(stderr,"Received all of file via rhizome -- now to import it\n");
|
||||
{
|
||||
fclose(q->file);
|
||||
const char *id = rhizome_manifest_get(q->manifest, "id", NULL, 0);
|
||||
if (id == NULL)
|
||||
return WHY("Manifest missing ID");
|
||||
char filename[1024];
|
||||
snprintf(filename,1024,"%s/import/manifest.%s",
|
||||
rhizome_datastore_path,
|
||||
rhizome_manifest_get(q->manifest,"id",NULL,0));
|
||||
if (!FORM_RHIZOME_DATASTORE_PATH("import/manifest.%s", id))
|
||||
return -1;
|
||||
/* Do really write the manifest unchanged */
|
||||
if (debug&DEBUG_RHIZOME) {
|
||||
fprintf(stderr,"manifest has %d signatories\n",q->manifest->sig_count);
|
||||
@ -523,8 +533,7 @@ int rhizome_fetch_poll()
|
||||
q->manifest->finalised=1;
|
||||
q->manifest->manifest_bytes=q->manifest->manifest_all_bytes;
|
||||
if (!rhizome_write_manifest_file(q->manifest,filename)) {
|
||||
rhizome_bundle_import(q->manifest, NULL,
|
||||
rhizome_manifest_get(q->manifest, "id", NULL, 0),
|
||||
rhizome_bundle_import(q->manifest, NULL, id,
|
||||
NULL /* no additional groups */,
|
||||
q->manifest->ttl - 1 /* TTL */,
|
||||
1 /* do verify */,
|
||||
|
3
serval.h
3
serval.h
@ -1109,6 +1109,9 @@ const char *serval_instancepath();
|
||||
int form_serval_instance_path(char * buf, size_t bufsiz, const char *path);
|
||||
int create_serval_instance_dir();
|
||||
|
||||
int mkdirs(const char *path);
|
||||
int mkdirsn(const char *path, size_t len);
|
||||
|
||||
/* Handy statement for forming a path to an instance file in a char buffer whose declaration
|
||||
* is in scope (so that sizeof(buf) will work). Evaluates to true if the pathname fitted into
|
||||
* the provided buffer, false (0) otherwise (after printing a message to stderr). */
|
||||
|
Loading…
x
Reference in New Issue
Block a user