Esempio n. 1
0
static bool
process_all_startpoints (int argc, char *argv[])
{
  int i;

  /* figure out how many start points there are */
  for (i = 0; i < argc && !looks_like_expression (argv[i], true); i++)
    {
      state.starting_path_length = strlen (argv[i]); /* TODO: is this redundant? */
      if (!find (argv[i]))
	return false;
    }

  if (i == 0)
    {
      /*
       * We use a temporary variable here because some actions modify
       * the path temporarily.  Hence if we use a string constant,
       * we get a coredump.  The best example of this is if we say
       * "find -printf %H" (note, not "find . -printf %H").
       */
      char defaultpath[2] = ".";
      return find (defaultpath);
    }
  return true;
}
Esempio n. 2
0
/* CAUTION: this is the entry point for the oldfind executable, which is not the binary that
 * will actually get installed.   See ftsfind.c. */
int
main (int argc, char **argv)
{
  int i;
  int end_of_leading_options = 0; /* First arg after any -H/-L etc. */
  struct predicate *eval_tree;

  if (argv[0])
    set_program_name (argv[0]);
  else
    set_program_name ("find");

  state.exit_status = 0;

  if (fd_leak_check_is_enabled ())
    {
      remember_non_cloexec_fds ();
    }

  record_initial_cwd ();

  state.already_issued_stat_error_msg = false;
  state.shared_files = sharefile_init ("w");
  if (NULL == state.shared_files)
    {
      error (EXIT_FAILURE, errno,
	     _("Failed to initialize shared-file hash table"));
    }

  /* Set the option defaults before we do the locale
   * initialisation as check_nofollow () needs to be executed in the
   * POSIX locale.
   */
  set_option_defaults (&options);

#ifdef HAVE_SETLOCALE
  setlocale (LC_ALL, "");
#endif
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);
  if (atexit (close_stdin))
    {
      error (EXIT_FAILURE, errno, _("The atexit library function failed"));
    }

  /* Check for -P, -H or -L options. */
  end_of_leading_options = process_leading_options (argc, argv);

  if (options.debug_options & DebugStat)
    options.xstat = debug_stat;

#ifdef DEBUG
  fprintf (stderr, "cur_day_start = %s", ctime (&options.cur_day_start));
#endif /* DEBUG */

  /* state.cwd_dir_fd has to be initialized before we call build_expression_tree ()
   * because command-line parsing may lead us to stat some files.
   */
  state.cwd_dir_fd = AT_FDCWD;

  /* We are now processing the part of the "find" command line
   * after the -H/-L options (if any).
   */
  eval_tree = build_expression_tree (argc, argv, end_of_leading_options);


  /* safely_chdir () needs to check that it has ended up in the right place.
   * To avoid bailing out when something gets automounted, it checks if
   * the target directory appears to have had a directory mounted on it as
   * we chdir ()ed.  The problem with this is that in order to notice that
   * a file system was mounted, we would need to lstat () all the mount points.
   * That strategy loses if our machine is a client of a dead NFS server.
   *
   * Hence if safely_chdir () and wd_sanity_check () can manage without needing
   * to know the mounted device list, we do that.
   */
  if (!options.open_nofollow_available)
    {
#ifdef STAT_MOUNTPOINTS
      init_mounted_dev_list (0);
#endif
    }


  set_stat_placeholders (&starting_stat_buf);
  if ((*options.xstat) (".", &starting_stat_buf) != 0)
    error (EXIT_FAILURE, errno, _("cannot stat current directory"));

  /* If no paths are given, default to ".".  */
  for (i = end_of_leading_options; i < argc && !looks_like_expression (argv[i], true); i++)
    {
      process_top_path (argv[i], 0, starting_stat_buf.st_ino);
    }

  /* If there were no path arguments, default to ".". */
  if (i == end_of_leading_options)
    {
      /*
       * We use a temporary variable here because some actions modify
       * the path temporarily.  Hence if we use a string constant,
       * we get a coredump.  The best example of this is if we say
       * "find -printf %H" (note, not "find . -printf %H").
       */
      char defaultpath[2] = ".";
      process_top_path (defaultpath, 0, starting_stat_buf.st_ino);
    }

  /* If "-exec ... {} +" has been used, there may be some
   * partially-full command lines which have been built,
   * but which are not yet complete.   Execute those now.
   */
  show_success_rates (eval_tree);
  cleanup ();
  return state.exit_status;
}
Esempio n. 3
0
struct predicate*
build_expression_tree (int argc, char *argv[], int end_of_leading_options)
{
  const struct parser_table *parse_entry; /* Pointer to the parsing table entry for this expression. */
  char *predicate_name;		/* Name of predicate being parsed. */
  struct predicate *cur_pred;
  const struct parser_table *entry_close, *entry_print, *entry_open;
  int i, oldi;

  predicates = NULL;

  /* Find where in ARGV the predicates begin by skipping the list of
   * start points.  As a side effect, also figure out which is the
   * first and last start point.
   */
  start_points = argv + end_of_leading_options;
  for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++)
    {
      ++num_start_points;
    }

  /* Enclose the expression in `( ... )' so a default -print will
     apply to the whole expression. */
  entry_open  = find_parser ("(");
  entry_close = find_parser (")");
  entry_print = find_parser ("print");
  assert (entry_open  != NULL);
  assert (entry_close != NULL);
  assert (entry_print != NULL);

  parse_openparen (entry_open, argv, &argc);
  last_pred->p_name = "(";
  predicates->artificial = true;
  parse_begin_user_args (argv, argc, last_pred, predicates);
  pred_sanity_check (last_pred);

  /* Build the input order list. */
  while (i < argc )
    {
      state.already_issued_stat_error_msg = false;
      if (!looks_like_expression (argv[i], false))
	{
	  error (0, 0, _("paths must precede expression: %s"), argv[i]);
	  usage (stderr, 1, NULL);
	}

      predicate_name = argv[i];
      parse_entry = find_parser (predicate_name);
      if (parse_entry == NULL)
	{
	  /* Command line option not recognized */
	  error (EXIT_FAILURE, 0, _("unknown predicate `%s'"), predicate_name);
	}

      /* We have recognised a test of the form -foo.  Eat that,
       * unless it is a predicate like -newerXY.
       */
      if (parse_entry->type != ARG_SPECIAL_PARSE)
	{
	  i++;
	}
      oldi = i;
      if (!(*(parse_entry->parser_func)) (parse_entry, argv, &i))
	{
	  if (argv[i])
	    {
	      if ( (ARG_SPECIAL_PARSE == parse_entry->type) && (i == oldi) )
		{
		  /* The special parse function spat out the
		   * predicate.  It must be invalid, or not tasty.
		   */
		  error (EXIT_FAILURE, 0, _("invalid predicate `%s'"),
			 predicate_name);
		}
	      else
		{
		  error (EXIT_FAILURE, 0, _("invalid argument `%s' to `%s'"),
			 argv[i], predicate_name);
		}
	    }
	  else
	    {
	      /* Command line option requires an argument */
	      error (EXIT_FAILURE, 0,
		     _("missing argument to `%s'"), predicate_name);
	    }
	}
      else
	{
	  last_pred->p_name = predicate_name;

	  /* If the parser consumed an argument, save it. */
	  if (i != oldi)
	    last_pred->arg_text = argv[oldi];
	  else
	    last_pred->arg_text = NULL;
	}
      pred_sanity_check(last_pred);
      pred_sanity_check(predicates); /* XXX: expensive */
    }
  parse_end_user_args (argv, argc, last_pred, predicates);
  if (predicates->pred_next == NULL)
    {
      /* No predicates that do something other than set a global variable
	 were given; remove the unneeded initial `(' and add `-print'. */
      cur_pred = predicates;
      predicates = last_pred = predicates->pred_next;
      free (cur_pred);
      parse_print (entry_print, argv, &argc);
      last_pred->p_name = "-print";
      pred_sanity_check(last_pred);
      pred_sanity_check(predicates); /* XXX: expensive */
    }
  else if (!default_prints (predicates->pred_next))
    {
      /* One or more predicates that produce output were given;
	 remove the unneeded initial `('. */
      cur_pred = predicates;
      predicates = predicates->pred_next;
      pred_sanity_check (predicates); /* XXX: expensive */
      free (cur_pred);
    }
  else
    {
      /* `( user-supplied-expression ) -print'. */
      parse_closeparen (entry_close, argv, &argc);
      last_pred->p_name = ")";
      last_pred->artificial = true;
      pred_sanity_check (last_pred);
      parse_print (entry_print, argv, &argc);
      last_pred->p_name = "-print";
      last_pred->artificial = true;
      pred_sanity_check (last_pred);
      pred_sanity_check (predicates); /* XXX: expensive */
    }

  if (options.debug_options & (DebugExpressionTree|DebugTreeOpt))
    {
      fprintf (stderr, "Predicate List:\n");
      print_list (stderr, predicates);
    }

  /* do a sanity check */
  check_option_combinations (predicates);
  pred_sanity_check (predicates);

  /* Done parsing the predicates.  Build the evaluation tree. */
  cur_pred = predicates;
  eval_tree = get_expr (&cur_pred, NO_PREC, NULL);
  calculate_derived_rates (eval_tree);

  /* Check if we have any left-over predicates (this fixes
   * Debian bug #185202).
   */
  if (cur_pred != NULL)
    {
      /* cur_pred->p_name is often NULL here */
      if (pred_is (cur_pred, pred_closeparen))
	{
	  /* e.g. "find \( -true \) \)" */
	  error (EXIT_FAILURE, 0, _("you have too many ')'"));
	}
      else
	{
	  if (cur_pred->p_name)
	    error (EXIT_FAILURE, 0,
		   _("unexpected extra predicate '%s'"), cur_pred->p_name);
	  else
	    error (EXIT_FAILURE, 0, _("unexpected extra predicate"));
	}
    }

  if (options.debug_options & (DebugExpressionTree|DebugTreeOpt))
    {
      fprintf (stderr, "Eval Tree:\n");
      print_tree (stderr, eval_tree, 0);
    }

  estimate_costs (eval_tree);

  /* Rearrange the eval tree in optimal-predicate order. */
  opt_expr (&eval_tree);

  /* Check that the tree is in normalised order (opt_expr does this) */
  check_normalization (eval_tree, true);

  do_arm_swaps (eval_tree);

  /* Check that the tree is still in normalised order */
  check_normalization (eval_tree, true);

  if (options.debug_options & (DebugExpressionTree|DebugTreeOpt))
    {
      fprintf (stderr, "Optimized Eval Tree:\n");
      print_tree (stderr, eval_tree, 0);
      fprintf (stderr, "Optimized command line:\n");
      print_optlist (stderr, eval_tree);
      fprintf (stderr, "\n");
    }

  return eval_tree;
}