예제 #1
0
파일: index.c 프로젝트: prachpub/doodle
/**
 * @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 */
}
예제 #2
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 *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;
}