/** * @return 0 on success, 1 on error. */ static int do_fork(struct EXTRACT_Process * proc) { int filedes1[2]; int filedes2[2]; char buffer[FILENAME_MAX+2]; size_t pos; ssize_t ret; size_t slen; struct EXTRACTOR_PluginList * list; char * filename; struct AccuCtx acc_ctx; #if DEBUG_IPC fprintf(stderr, "Forking!\n"); #endif if (0 != pipe(filedes1)) { proc->my_log(proc->log_ctx, DOODLE_LOG_CRITICAL, _("Call to '%s' failed: %s\n"), "pipe", strerror(errno)); return 1; } if (0 != pipe(filedes2)) { proc->my_log(proc->log_ctx, DOODLE_LOG_CRITICAL, _("Call to '%s' failed: %s\n"), "pipe", strerror(errno)); close(filedes1[0]); close(filedes1[1]); return 1; } /* log before fork, just to avoid out-of-process problems with my_log */ if (proc->do_default) proc->my_log(proc->log_ctx, DOODLE_LOG_VERY_VERBOSE, (_("Loading default set of libextractor plugins.\n"))); if (proc->libs != NULL) proc->my_log(proc->log_ctx, DOODLE_LOG_VERY_VERBOSE, _("Loading libextractor plugins: '%s'\n"), proc->libs); proc->pid = fork(); if (proc->pid == -1) { proc->my_log(proc->log_ctx, DOODLE_LOG_CRITICAL, _("Call to '%s' failed: %s\n"), "fork", strerror(errno)); close(filedes1[0]); close(filedes1[1]); close(filedes2[0]); close(filedes2[1]); return 1; } if (proc->pid != 0) { close(filedes1[1]); close(filedes2[0]); proc->send_pipe = filedes2[1]; proc->read_pipe = filedes1[0]; return 0; } /* we're now in the forked process! */ close(filedes1[0]); close(filedes2[1]); list = NULL; if (proc->do_default) list = EXTRACTOR_plugin_add_defaults(EXTRACTOR_OPTION_DEFAULT_POLICY); if (proc->libs != NULL) list = EXTRACTOR_plugin_add_config(list, proc->libs, EXTRACTOR_OPTION_DEFAULT_POLICY); pos = 0; buffer[FILENAME_MAX + 1] = '\0'; ret = read(filedes2[0], &buffer[pos], FILENAME_MAX + 1 - pos); while ( (-1 != ret) && (ret != 0) ) { pos += ret; slen = strlen(buffer) + 1; if (slen <= pos) { filename = strdup(buffer); memmove(buffer, &buffer[slen], pos - slen); pos = pos - slen; acc_ctx.count = 0; acc_ctx.size = 0; acc_ctx.keywords = NULL; acc_ctx.types = NULL; EXTRACTOR_extract(list, filename, NULL, 0, &accumulator, &acc_ctx); DO_WRITE(filedes1[1], &acc_ctx.count, sizeof(unsigned int)); while (0 != acc_ctx.count--) { DO_WRITE(filedes1[1], &acc_ctx.types[acc_ctx.count], sizeof(enum EXTRACTOR_MetaType)); slen = strlen(acc_ctx.keywords[acc_ctx.count]); if (slen > MAX_SLEN) slen = MAX_SLEN; /* cut off -- far too large! */ DO_WRITE(filedes1[1], &slen, sizeof(size_t)); DO_WRITE(filedes1[1], acc_ctx.keywords[acc_ctx.count], slen); free(acc_ctx.keywords[acc_ctx.count]); } free (acc_ctx.keywords); free (acc_ctx.types); acc_ctx.keywords = NULL; acc_ctx.types = NULL; acc_ctx.size = 0; } ret = read(filedes2[0], &buffer[pos], FILENAME_MAX + 1 - pos); } /* exit / cleanup */ ERROR: free (acc_ctx.keywords); free (acc_ctx.types); EXTRACTOR_plugin_remove_all (list); close(filedes2[0]); close(filedes1[1]); /* never return - we were forked! */ exit(0); return 1; /* eh, dead */ }
/** * Main function of the helper process to extract meta data. * * @param argc should be 3 * @param argv [0] our binary name * [1] name of the file or directory to process * [2] "-" to disable extraction, NULL for defaults, * otherwise custom plugins to load from LE * @return 0 on success */ int main (int argc, char *const *argv) { const char *filename_expanded; const char *ex; struct ScanTreeNode *root; #if WINDOWS /* We're using stdout to communicate binary data back to the parent; use * binary mode. */ _setmode (1, _O_BINARY); /* Get utf-8-encoded arguments */ if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) return 5; output_stream = 1; /* stdout */ #else ignore_sigpipe (); /* move stdout to some other FD for IPC, bind stdout/stderr to /dev/null */ output_stream = dup (1); make_dev_zero (1, O_WRONLY); make_dev_zero (2, O_WRONLY); #endif /* parse command line */ if ( (3 != argc) && (2 != argc) ) { FPRINTF (stderr, "%s", "gnunet-helper-fs-publish needs exactly one or two arguments\n"); #if WINDOWS GNUNET_free ((void*) argv); #endif return 1; } filename_expanded = argv[1]; ex = argv[2]; if ( (NULL == ex) || (0 != strcmp (ex, "-")) ) { #if HAVE_LIBEXTRACTOR plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); if (NULL != ex) plugins = EXTRACTOR_plugin_add_config (plugins, ex, EXTRACTOR_OPTION_DEFAULT_POLICY); #endif } /* scan tree to find out how much work there is to be done */ if (GNUNET_OK != preprocess_file (filename_expanded, &root)) { (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); #if HAVE_LIBEXTRACTOR EXTRACTOR_plugin_remove_all (plugins); #endif #if WINDOWS GNUNET_free ((void*) argv); #endif return 2; } /* signal that we're done counting files, so that a percentage of progress can now be calculated */ if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE, NULL, 0)) { #if HAVE_LIBEXTRACTOR EXTRACTOR_plugin_remove_all (plugins); #endif #if WINDOWS GNUNET_free ((void*) argv); #endif return 3; } if (NULL != root) { if (GNUNET_OK != extract_files (root)) { (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); free_tree (root); #if HAVE_LIBEXTRACTOR EXTRACTOR_plugin_remove_all (plugins); #endif #if WINDOWS GNUNET_free ((void*) argv); #endif return 4; } free_tree (root); } /* enable "clean" shutdown by telling parent that we are done */ (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED, NULL, 0); #if HAVE_LIBEXTRACTOR EXTRACTOR_plugin_remove_all (plugins); #endif #if WINDOWS GNUNET_free ((void*) argv); #endif return 0; }
/** * Main function of the helper process to extract meta data. * * @param argc should be 3 * @param argv [0] our binary name * [1] name of the file or directory to process * [2] "-" to disable extraction, NULL for defaults, * otherwise custom plugins to load from LE * @return 0 on success */ int main(int argc, char **argv) { const char *filename_expanded; const char *ex; struct ScanTreeNode *root; #if WINDOWS /* We're using stdout to communicate binary data back to the parent; use * binary mode. */ _setmode (1, _O_BINARY); #endif /* parse command line */ if ( (3 != argc) && (2 != argc) ) { FPRINTF (stderr, "%s", "gnunet-helper-fs-publish needs exactly one or two arguments\n"); return 1; } filename_expanded = argv[1]; ex = argv[2]; if ( (NULL == ex) || (0 != strcmp (ex, "-")) ) { plugins = EXTRACTOR_plugin_add_defaults (EXTRACTOR_OPTION_DEFAULT_POLICY); if (NULL != ex) plugins = EXTRACTOR_plugin_add_config (plugins, ex, EXTRACTOR_OPTION_DEFAULT_POLICY); } /* scan tree to find out how much work there is to be done */ if (GNUNET_OK != preprocess_file (filename_expanded, &root)) { (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); return 2; } /* signal that we're done counting files, so that a percentage of progress can now be calculated */ if (GNUNET_OK != write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_COUNTING_DONE, NULL, 0)) return 3; if (NULL != root) { if (GNUNET_OK != extract_files (root)) { (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_ERROR, NULL, 0); free_tree (root); return 4; } free_tree (root); } /* enable "clean" shutdown by telling parent that we are done */ (void) write_message (GNUNET_MESSAGE_TYPE_FS_PUBLISH_HELPER_FINISHED, NULL, 0); if (NULL != plugins) EXTRACTOR_plugin_remove_all (plugins); return 0; }