Пример #1
0
/* Take a "mode" indicator and fill in the files of 'state'.
 */
int
digest_mode(mode_t mode,
	    const char *pathname,
	    const char *name,
	    struct stat *pstat,
	    boolean leaf)
{
  /* If we know the type of the directory entry, and it is not a
   * symbolic link, we may be able to avoid a stat() or lstat() call.
   */
  if (mode)
    {
      if (S_ISLNK(mode) && following_links())
	{
	  /* mode is wrong because we should have followed the symlink. */
	  if (get_statinfo(pathname, name, pstat) != 0)
	    return 0;
	  mode = state.type = pstat->st_mode;
	  state.have_type = true;
	}
      else
	{
	  state.have_type = true;
	  pstat->st_mode = state.type = mode;
	}
    }
  else
    {
      /* Mode is not yet known; may have to stat the file unless we 
       * can deduce that it is not a directory (which is all we need to 
       * know at this stage)
       */
      if (leaf)
	{
	  state.have_stat = false;
	  state.have_type = false;;
	  state.type = 0;
	}
      else
	{
	  if (get_statinfo(pathname, name, pstat) != 0)
	    return 0;
	  
	  /* If -L is in effect and we are dealing with a symlink,
	   * st_mode is the mode of the pointed-to file, while mode is
	   * the mode of the directory entry (S_IFLNK).  Hence now
	   * that we have the stat information, override "mode".
	   */
	  state.type = pstat->st_mode;
	  state.have_type = true;
	}
    }

  /* success. */
  return 1;
}
Пример #2
0
/* Get the stat/type information for a file, if it is 
 * not already known. 
 */
int
get_info (const char *pathname,
	  struct stat *p,
	  struct predicate *pred_ptr)
{
  boolean todo = false;
  
  /* If we need the full stat info, or we need the type info but don't 
   * already have it, stat the file now.
   */
  if (pred_ptr->need_stat)
    todo = true;
  else if ((pred_ptr->need_type && (0 == state.have_type)))
    todo = true;
  
  if (todo)
    return get_statinfo(pathname, state.rel_pathname, p);
  else
    return 0;
}
Пример #3
0
static int
process_path (char *pathname, char *name, bool leaf, char *parent,
	      mode_t mode, ino_t inum)
{
  struct stat stat_buf;
  static dev_t root_dev;	/* Device ID of current argument pathname. */
  int i;
  struct predicate *eval_tree;

  eval_tree = get_eval_tree ();
  /* Assume it is a non-directory initially. */
  stat_buf.st_mode = 0;

  /* The caller usually knows the inode number, either from readdir or
   * a *stat call.  We use that value (the caller passes 0 to indicate
   * ignorance of the inode number).
   */
  stat_buf.st_ino = inum;

  state.rel_pathname = name;
  state.type = 0;
  state.have_stat = false;
  state.have_type = false;
  state.already_issued_stat_error_msg = false;

  if (!digest_mode (&mode, pathname, name, &stat_buf, leaf))
    return 0;

  if (!S_ISDIR (state.type))
    {
      if (state.curdepth >= options.mindepth)
	apply_predicate (pathname, &stat_buf, eval_tree);
      return 0;
    }

  /* From here on, we're working on a directory.  */


  /* Now we really need to stat the directory, even if we know the
   * type, because we need information like struct stat.st_rdev.
   */
  if (get_statinfo (pathname, name, &stat_buf) != 0)
    return 0;

  state.have_stat = true;
  mode = state.type = stat_buf.st_mode;	/* use full info now that we have it. */
  state.stop_at_current_level =
    options.maxdepth >= 0
    && state.curdepth >= options.maxdepth;

  /* If we've already seen this directory on this branch,
     don't descend it again.  */
  for (i = 0; i <= dir_curr; i++)
    if (stat_buf.st_ino == dir_ids[i].ino &&
	stat_buf.st_dev == dir_ids[i].dev)
      {
	state.stop_at_current_level = true;
	issue_loop_warning (name, pathname, i);
      }

  if (dir_alloc <= ++dir_curr)
    {
      dir_alloc += DIR_ALLOC_STEP;
      dir_ids = (struct dir_id *)
	xrealloc ((char *) dir_ids, dir_alloc * sizeof (struct dir_id));
    }
  dir_ids[dir_curr].ino = stat_buf.st_ino;
  dir_ids[dir_curr].dev = stat_buf.st_dev;

  if (options.stay_on_filesystem)
    {
      if (state.curdepth == 0)
	root_dev = stat_buf.st_dev;
      else if (stat_buf.st_dev != root_dev)
	state.stop_at_current_level = true;
    }

  if (options.do_dir_first && state.curdepth >= options.mindepth)
    apply_predicate (pathname, &stat_buf, eval_tree);

  if (options.debug_options & DebugSearch)
    fprintf (stderr, "pathname = %s, stop_at_current_level = %d\n",
	     pathname, state.stop_at_current_level);

  if (state.stop_at_current_level == false)
    {
      /* Scan directory on disk. */
      process_dir (pathname, name, strlen (pathname), &stat_buf, parent);
    }

  if (options.do_dir_first == false && state.curdepth >= options.mindepth)
    {
      /* The fields in 'state' are now out of date.  Correct them.
       */
      if (!digest_mode (&mode, pathname, name, &stat_buf, leaf))
	return 0;

      if (0 == dir_curr)
	{
	  at_top (pathname, mode, stat_buf.st_ino, &stat_buf,
		  do_process_predicate);
	}
      else
	{
	  do_process_predicate (pathname, name, mode, stat_buf.st_ino,
				&stat_buf);
	}
    }

  dir_curr--;

  return 1;
}