From a2caa5692f62a8e844d3045921ea90c30d618f08 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 11 Sep 2009 14:48:40 +0000 Subject: [PATCH] more work on fs --- src/fs/fs_publish.c | 30 ++---- src/fs/gnunet-service-fs.c | 167 ++++++++++++++++++++++++++++++++-- src/include/gnunet_disk_lib.h | 13 +++ src/util/disk.c | 36 ++++++++ 4 files changed, 216 insertions(+), 30 deletions(-) diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index db38b76da..bac0133f2 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -695,10 +695,6 @@ process_index_start_response (void *cls, } -#if LINUX -#include -#endif - /** * Function called once the hash computation over an * indexed file has completed. @@ -716,10 +712,8 @@ hash_for_index_cb (void *cls, struct IndexStartMessage *ism; size_t slen; struct GNUNET_CLIENT_Connection *client; -#if LINUX - struct stat sbuf; - struct statvfs fbuf; -#endif + uint32_t dev; + uint64_t ino; p = sc->fi_pos; if (NULL == res) @@ -762,22 +756,14 @@ hash_for_index_cb (void *cls, ism->header.size = htons(sizeof(struct IndexStartMessage) + slen); ism->header.type = htons(GNUNET_MESSAGE_TYPE_FS_INDEX_START); - /* FIXME: activate this on other OSes that - support it (or something very similar; make - sure to also adjust corresponding code - on the service-side) */ - /* FIXME: the block below should probably be - abstracted into a function in the DISK API */ -#if LINUX - if ( (0 == stat(p->data.file.filename, - &sbuf)) && - (0 == statvfs (p->data.file.filename, - &fbuf) ) ) + if (GNUNET_OK == + GNUNET_DISK_file_get_identifiers (p->data.file.filename, + &dev, + &ino)) { - ism->device = htonl ((uint32_t) fbuf.f_fsid); - ism->inode = GNUNET_htonll( (uint64_t) sbuf.st_ino); + ism->device = htonl (dev); + ism->inode = GNUNET_htonll(ino); } -#endif memcpy (&ism[1], p->data.file.filename, slen); diff --git a/src/fs/gnunet-service-fs.c b/src/fs/gnunet-service-fs.c index b85a63d4b..550c4d16d 100644 --- a/src/fs/gnunet-service-fs.c +++ b/src/fs/gnunet-service-fs.c @@ -25,7 +25,6 @@ * * TODO: * - INDEX_START handling - * - INDEX_LIST handling * - UNINDEX handling * - bloomfilter support (GET, CS-request with BF, etc.) * - all P2P messages @@ -52,6 +51,121 @@ static struct GNUNET_SCHEDULER_Handle *sched; */ const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * In-memory information about indexed files (also available + * on-disk). + */ +struct IndexInfo +{ + + /** + * This is a linked list. + */ + struct IndexInfo *next; + + /** + * Name of the indexed file. Memory allocated + * at the end of this struct (do not free). + */ + const char *filename; + + /** + * Context for tranmitting confirmation to client, + * NULL if we've done this already. + */ + struct GNUNET_SERVER_TransmitContext *tc; + + /** + * Hash of the contents of the file. + */ + GNUNET_HashCode file_id; + +}; + + +/** + * Linked list of indexed files. + */ +static struct IndexInfo *indexed_files; + + +/** + * Write the current index information list to disk. + */ +static void +write_index_list (void) +{ +} + + +/** + * Read index information from disk. + */ +static void +read_index_list (void) +{ + +} + + +/** + * We've validated the hash of the file we're about to + * index. Signal success to the client and update + * our internal data structures. + * + * @param ii the index info entry for the request + */ +static void +signal_index_ok (struct IndexInfo *ii) +{ + ii->next = indexed_files; + indexed_files = ii; + write_index_list (); + GNUNET_SERVER_transmit_context_append (ii->tc, + NULL, 0, + GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK); + GNUNET_SERVER_transmit_context_run (ii->tc, + GNUNET_TIME_UNIT_MINUTES); + ii->tc = NULL; +} + + + +/** + * Function called once the hash computation over an + * indexed file has completed. + * + * @param cls closure, our publishing context + * @param res resulting hash, NULL on error + */ +static void +hash_for_index_val (void *cls, + const GNUNET_HashCode * + res) +{ + struct IndexInfo *ii; + + if ( (res == NULL) || + (0 != memcmp (res, + &ii->file_id, + sizeof(GNUNET_HashCode))) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + _("Hash mismatch trying to index file `%s'\n"), + ii->filename); + GNUNET_SERVER_transmit_context_append (ii->tc, + NULL, 0, + GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED); + GNUNET_SERVER_transmit_context_run (ii->tc, + GNUNET_TIME_UNIT_MINUTES); + GNUNET_free (ii); + return; + } + signal_index_ok (ii); +} + + /** * Handle INDEX_START-message. * @@ -67,6 +181,12 @@ handle_index_start (void *cls, const struct IndexStartMessage *ism; const char *fn; uint16_t msize; + struct IndexInfo *ii; + size_t slen; + uint32_t dev; + uint64_t ino; + uint32_t mydev; + uint64_t myino; msize = ntohs(message->size); if ( (msize <= sizeof (struct IndexStartMessage)) || @@ -77,9 +197,37 @@ handle_index_start (void *cls, GNUNET_SYSERR); return; } - ism = (const struct IndexStartMessage*) message; + fn = (const char*) &ism[1]; - // FIXME: store fn, hash, check, respond to client, etc. + dev = ntohl (ism->device); + ino = GNUNET_ntohll (ism->inode); + ism = (const struct IndexStartMessage*) message; + slen = strlen (fn) + 1; + ii = GNUNET_malloc (sizeof (struct IndexInfo) + slen); + ii->filename = (const char*) &ii[1]; + memcpy (&ii[1], fn, slen); + ii->file_id = ism->file_id; + ii->tc = GNUNET_SERVER_transmit_context_create (client); + if ( ( (dev != 0) || + (ino != 0) ) && + (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn, + &mydev, + &myino)) && + ( (dev == mydev) && + (ino == myino) ) ) + { + /* fast validation OK! */ + signal_index_ok (ii); + return; + } + /* slow validation, need to hash full file (again) */ + GNUNET_CRYPTO_hash_file (sched, + GNUNET_SCHEDULER_PRIORITY_IDLE, + GNUNET_NO, + fn, + HASHING_BLOCKSIZE, + &hash_for_index_val, + ii); } @@ -99,18 +247,19 @@ handle_index_list_get (void *cls, struct IndexInfoMessage *iim; char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE]; size_t slen; - char *fn; + const char *fn; struct GNUNET_MessageHeader *msg; + struct IndexInfo *pos; tc = GNUNET_SERVER_transmit_context_create (client); iim = (struct IndexInfoMessage*) buf; msg = &iim->header; - while (0) + pos = indexed_files; + while (NULL != pos) { iim->reserved = 0; - // FIXME: read actual list of indexed files... - // iim->file_id = id; - fn = "FIXME"; + iim->file_id = pos->file_id; + fn = pos->filename; slen = strlen (fn) + 1; if (slen + sizeof (struct IndexInfoMessage) > GNUNET_SERVER_MAX_MESSAGE_SIZE) @@ -125,6 +274,7 @@ handle_index_list_get (void *cls, sizeof (struct IndexInfoMessage) - sizeof (struct GNUNET_MessageHeader) + slen, GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY); + pos = pos->next; } GNUNET_SERVER_transmit_context_append (tc, NULL, 0, @@ -717,6 +867,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, const struct GNUNET_CONFIGURATION_Handle *c) { + read_index_list (); sched = s; cfg = c; dsh = GNUNET_DATASTORE_connect (cfg, diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h index 72a24aecb..4d09d4c99 100644 --- a/src/include/gnunet_disk_lib.h +++ b/src/include/gnunet_disk_lib.h @@ -148,6 +148,19 @@ int GNUNET_DISK_file_size (const char *filename, int includeSymLinks); +/** + * FIXME. + * + * @param filename name of the file + * @param dev set to the device ID + * @param ino set to the inode ID + * @return GNUNET_OK on success + */ +int GNUNET_DISK_file_get_identifiers (const char *filename, + uint32_t *dev, + uint64_t *ino); + + /** * Create an (empty) temporary file on disk. * diff --git a/src/util/disk.c b/src/util/disk.c index 465bee6ea..fe117ad21 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -191,6 +191,42 @@ GNUNET_DISK_file_size (const char *filename, } + +#if LINUX +#include +#endif + + + +/** + * FIXME. + * + * @param filename name of the file + * @param dev set to the device ID + * @param ino set to the inode ID + * @return GNUNET_OK on success + */ +int GNUNET_DISK_file_get_identifiers (const char *filename, + uint32_t *dev, + uint64_t *ino) +{ +#if LINUX + struct stat sbuf; + struct statvfs fbuf; + + if ( (0 == stat(filename, + &sbuf)) && + (0 == statvfs (filename, + &fbuf) ) ) + { + *dev = (uint32_t) fbuf.f_fsid; + *ino = (uint64_t) sbuf.st_ino; + } +#endif + return GNUNET_SYSERR; +} + + /** * Create an (empty) temporary file on disk. * -- 2.25.1