X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Ffs%2Ffs_dirmetascan.c;h=45d502c91859552f33206d4cedbee218338cfb45;hb=dd1927b960c7cea13733e061a11142274652ba27;hp=9ee69c860437e0955d4a3b3edbeea274c708f2ab;hpb=7a9cac25484d310cfe9da4a0c6c1887871538366;p=oweals%2Fgnunet.git diff --git a/src/fs/fs_dirmetascan.c b/src/fs/fs_dirmetascan.c index 9ee69c860..45d502c91 100644 --- a/src/fs/fs_dirmetascan.c +++ b/src/fs/fs_dirmetascan.c @@ -1,10 +1,10 @@ /* This file is part of GNUnet - (C) 2005-2012 Christian Grothoff (and other contributing authors) + Copyright (C) 2005-2012 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** @@ -53,13 +53,13 @@ struct GNUNET_FS_DirScanner * Second argument to helper process. */ char *ex_arg; - + /** * The function that will be called every time there's a progress * message. */ GNUNET_FS_DirScannerProgressCallback progress_callback; - + /** * A closure for progress_callback. */ @@ -68,7 +68,7 @@ struct GNUNET_FS_DirScanner /** * After the scan is finished, it will contain a pointer to the * top-level directory entry in the directory tree built by the - * scanner. + * scanner. */ struct GNUNET_FS_ShareTreeItem *toplevel; @@ -77,6 +77,11 @@ struct GNUNET_FS_DirScanner */ struct GNUNET_FS_ShareTreeItem *pos; + /** + * Task scheduled when we are done. + */ + struct GNUNET_SCHEDULER_Task * stop_task; + /** * Arguments for helper. */ @@ -85,9 +90,9 @@ struct GNUNET_FS_DirScanner }; - /** - * Abort the scan. + * Abort the scan. Must not be called from within the progress_callback + * function. * * @param ds directory scanner structure */ @@ -96,11 +101,13 @@ GNUNET_FS_directory_scan_abort (struct GNUNET_FS_DirScanner *ds) { /* terminate helper */ if (NULL != ds->helper) - GNUNET_HELPER_stop (ds->helper); - + GNUNET_HELPER_stop (ds->helper, GNUNET_NO); + /* free resources */ if (NULL != ds->toplevel) GNUNET_FS_share_tree_free (ds->toplevel); + if (NULL != ds->stop_task) + GNUNET_SCHEDULER_cancel (ds->stop_task); GNUNET_free_non_null (ds->ex_arg); GNUNET_free (ds->filename_expanded); GNUNET_free (ds); @@ -124,7 +131,7 @@ GNUNET_FS_directory_scan_get_result (struct GNUNET_FS_DirScanner *ds) GNUNET_assert (NULL == ds->helper); /* preserve result */ result = ds->toplevel; - ds->toplevel = NULL; + ds->toplevel = NULL; GNUNET_FS_directory_scan_abort (ds); return result; } @@ -141,10 +148,10 @@ static struct GNUNET_FS_ShareTreeItem * advance (struct GNUNET_FS_ShareTreeItem *pos) { int moved; - + GNUNET_assert (NULL != pos); moved = 0; /* must not terminate, even on file, otherwise "normal" */ - while ( (pos->is_directory) || + while ( (pos->is_directory == GNUNET_YES) || (0 == moved) ) { if ( (moved != -1) && @@ -187,20 +194,54 @@ expand_tree (struct GNUNET_FS_ShareTreeItem *parent, int is_directory) { struct GNUNET_FS_ShareTreeItem *chld; + size_t slen; - chld = GNUNET_malloc (sizeof (struct GNUNET_FS_ShareTreeItem)); + chld = GNUNET_new (struct GNUNET_FS_ShareTreeItem); chld->parent = parent; chld->filename = GNUNET_strdup (filename); - chld->short_filename = GNUNET_strdup (GNUNET_STRINGS_get_short_name (filename)); + GNUNET_asprintf (&chld->short_filename, + "%s%s", + GNUNET_STRINGS_get_short_name (filename), + is_directory == GNUNET_YES ? "/" : ""); + /* make sure we do not end with '//' */ + slen = strlen (chld->short_filename); + if ( (slen >= 2) && + (chld->short_filename[slen-1] == '/') && + (chld->short_filename[slen-2] == '/') ) + chld->short_filename[slen-1] = '\0'; chld->is_directory = is_directory; if (NULL != parent) GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail, - chld); + chld); return chld; } +/** + * Task run last to shut everything down. + * + * @param cls the 'struct GNUNET_FS_DirScanner' + * @param tc unused + */ +static void +finish_scan (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct GNUNET_FS_DirScanner *ds = cls; + + ds->stop_task = NULL; + if (NULL != ds->helper) + { + GNUNET_HELPER_stop (ds->helper, GNUNET_NO); + ds->helper = NULL; + } + ds->progress_callback (ds->progress_callback_cls, + NULL, GNUNET_SYSERR, + GNUNET_FS_DIRSCANNER_FINISHED); +} + + /** * Called every time there is data to read from the scanner. * Calls the scanner progress handler. @@ -209,8 +250,8 @@ expand_tree (struct GNUNET_FS_ShareTreeItem *parent, * @param client always NULL * @param msg message from the helper process */ -static void -process_helper_msgs (void *cls, +static int +process_helper_msgs (void *cls, void *client, const struct GNUNET_MessageHeader *msg) { @@ -218,6 +259,11 @@ process_helper_msgs (void *cls, const char *filename; size_t left; +#if 0 + fprintf (stderr, "DMS parses %u-byte message of type %u\n", + (unsigned int) ntohs (msg->size), + (unsigned int) ntohs (msg->type)); +#endif left = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader); filename = (const char*) &msg[1]; switch (ntohs (msg->type)) @@ -228,7 +274,7 @@ process_helper_msgs (void *cls, GNUNET_break (0); break; } - ds->progress_callback (ds->progress_callback_cls, + ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_NO, GNUNET_FS_DIRSCANNER_FILE_START); if (NULL == ds->toplevel) @@ -237,7 +283,7 @@ process_helper_msgs (void *cls, else (void) expand_tree (ds->pos, filename, GNUNET_NO); - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_PROGRESS_DIRECTORY: if (filename[left-1] != '\0') { @@ -252,25 +298,25 @@ process_helper_msgs (void *cls, break; } ds->pos = ds->pos->parent; - return; + return GNUNET_OK; } - ds->progress_callback (ds->progress_callback_cls, + ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_YES, GNUNET_FS_DIRSCANNER_FILE_START); ds->pos = expand_tree (ds->pos, filename, GNUNET_YES); if (NULL == ds->toplevel) ds->toplevel = ds->pos; - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR: break; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_SKIP_FILE: - if (filename[left-1] != '\0') + if ('\0' != filename[left-1]) break; - ds->progress_callback (ds->progress_callback_cls, + ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_FILE_IGNORED); - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE: if (0 != left) { @@ -282,18 +328,18 @@ process_helper_msgs (void *cls, GNUNET_break (0); break; } - ds->progress_callback (ds->progress_callback_cls, + ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_ALL_COUNTED); ds->pos = ds->toplevel; - if (ds->pos->is_directory) + if (GNUNET_YES == ds->pos->is_directory) ds->pos = advance (ds->pos); - return; + return GNUNET_OK; case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_META_DATA: { size_t nlen; const char *end; - + if (NULL == ds->pos) { GNUNET_break (0); @@ -314,7 +360,7 @@ process_helper_msgs (void *cls, GNUNET_break (0); break; } - ds->progress_callback (ds->progress_callback_cls, + ds->progress_callback (ds->progress_callback_cls, filename, GNUNET_YES, GNUNET_FS_DIRSCANNER_EXTRACT_FINISHED); if (0 < left) @@ -326,17 +372,19 @@ process_helper_msgs (void *cls, break; } /* having full filenames is too dangerous; always make sure we clean them up */ - GNUNET_CONTAINER_meta_data_delete (ds->pos->meta, + GNUNET_CONTAINER_meta_data_delete (ds->pos->meta, EXTRACTOR_METATYPE_FILENAME, NULL, 0); + /* instead, put in our 'safer' original filename */ GNUNET_CONTAINER_meta_data_insert (ds->pos->meta, "", - EXTRACTOR_METATYPE_FILENAME, + EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME, EXTRACTOR_METAFORMAT_UTF8, "text/plain", - ds->pos->short_filename, + ds->pos->short_filename, strlen (ds->pos->short_filename) + 1); } - ds->pos = advance (ds->pos); - return; + ds->pos->ksk_uri = GNUNET_FS_uri_ksk_create_from_meta_data (ds->pos->meta); + ds->pos = advance (ds->pos); + return GNUNET_OK; } case GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED: if (NULL != ds->pos) @@ -348,26 +396,42 @@ process_helper_msgs (void *cls, { GNUNET_break (0); break; - } + } if (NULL == ds->toplevel) { GNUNET_break (0); break; } - GNUNET_HELPER_stop (ds->helper); - ds->helper = NULL; - ds->progress_callback (ds->progress_callback_cls, - NULL, GNUNET_SYSERR, - GNUNET_FS_DIRSCANNER_FINISHED); - return; + ds->stop_task = GNUNET_SCHEDULER_add_now (&finish_scan, + ds); + return GNUNET_OK; default: GNUNET_break (0); break; } - ds->progress_callback (ds->progress_callback_cls, + ds->progress_callback (ds->progress_callback_cls, NULL, GNUNET_SYSERR, GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); + return GNUNET_OK; +} + +/** + * Function called if our helper process died. + * + * @param cls the 'struct GNUNET_FS_DirScanner' callback. + */ +static void +helper_died_cb (void *cls) +{ + struct GNUNET_FS_DirScanner *ds = cls; + + ds->helper = NULL; + if (NULL != ds->stop_task) + return; /* normal death, was finished */ + ds->progress_callback (ds->progress_callback_cls, + NULL, GNUNET_SYSERR, + GNUNET_FS_DIRSCANNER_INTERNAL_ERROR); } @@ -375,7 +439,7 @@ process_helper_msgs (void *cls, * Start a directory scanner thread. * * @param filename name of the directory to scan - * @param GNUNET_YES to not to run libextractor on files (only build a tree) + * @param disable_extractor #GNUNET_YES to not to run libextractor on files (only build a tree) * @param ex if not NULL, must be a list of extra plugins for extractor * @param cb the callback to call when there are scanning progress messages * @param cb_cls closure for 'cb' @@ -384,7 +448,7 @@ process_helper_msgs (void *cls, struct GNUNET_FS_DirScanner * GNUNET_FS_directory_scan_start (const char *filename, int disable_extractor, const char *ex, - GNUNET_FS_DirScannerProgressCallback cb, + GNUNET_FS_DirScannerProgressCallback cb, void *cb_cls) { struct stat sbuf; @@ -399,24 +463,25 @@ GNUNET_FS_directory_scan_start (const char *filename, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting to scan directory `%s'\n", filename_expanded); - ds = GNUNET_malloc (sizeof (struct GNUNET_FS_DirScanner)); + ds = GNUNET_new (struct GNUNET_FS_DirScanner); ds->progress_callback = cb; ds->progress_callback_cls = cb_cls; ds->filename_expanded = filename_expanded; - if (disable_extractor) + if (disable_extractor) ds->ex_arg = GNUNET_strdup ("-"); - else + else ds->ex_arg = (NULL != ex) ? GNUNET_strdup (ex) : NULL; ds->args[0] = "gnunet-helper-fs-publish"; ds->args[1] = ds->filename_expanded; ds->args[2] = ds->ex_arg; ds->args[3] = NULL; - ds->helper = GNUNET_HELPER_start ("gnunet-helper-fs-publish", + ds->helper = GNUNET_HELPER_start (GNUNET_NO, + "gnunet-helper-fs-publish", ds->args, &process_helper_msgs, - ds); + &helper_died_cb, ds); if (NULL == ds->helper) - { + { GNUNET_free (filename_expanded); GNUNET_free (ds); return NULL;