Exemplo n.º 1
0
/* Recursively scan the given directory DIR.
   DEVICE is the device number where DIR resides (for --one-file-system).
   If CMDLINE is true, the directory name was explicitly listed in the
   command line.
   Unless *PDIR is NULL, store there a pointer to the struct directory
   describing DIR. */
struct directory *
scan_directory (char *dir, dev_t device, bool cmdline)
{
  char *dirp = savedir (dir);	/* for scanning directory */
  namebuf_t nbuf;
  char *tmp;
  struct stat stat_data;
  struct directory *directory;
  char ch;
  
  if (! dirp)
    savedir_error (dir);

  tmp = xstrdup (dir);
  zap_slashes (tmp);
  
  if (deref_stat (dereference_option, tmp, &stat_data))
    {
      dir_removed_diag (tmp, cmdline, stat_diag);
      free (tmp);
      free (dirp);
      return NULL;
    }

  directory = procdir (tmp, &stat_data, device,
		       (cmdline ? PD_FORCE_INIT : 0),
		       &ch);
  
  free (tmp);

  nbuf = namebuf_create (dir);

  if (dirp && directory->children != NO_CHILDREN)
    {
      char *entry;	/* directory entry being scanned */
      dumpdir_iter_t itr;

      makedumpdir (directory, dirp);

      for (entry = dumpdir_first (directory->dump, 1, &itr);
	   entry;
	   entry = dumpdir_next (itr))
	{
	  char *full_name = namebuf_name (nbuf, entry + 1);

	  if (*entry == 'I') /* Ignored entry */
	    *entry = 'N';
	  else if (excluded_name (full_name))
	    *entry = 'N';
	  else
	    {
	      if (deref_stat (dereference_option, full_name, &stat_data))
		{
		  file_removed_diag (full_name, false, stat_diag);
		  *entry = 'N';
		  continue;
		}

	      if (S_ISDIR (stat_data.st_mode))
		{
		  int pd_flag = 0;
		  if (!recursion_option)
		    pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
		  else if (directory->children == ALL_CHILDREN)
		    pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
		  *entry = 'D';
		  procdir (full_name, &stat_data, device, pd_flag, entry);
		}

	      else if (one_file_system_option && device != stat_data.st_dev)
		*entry = 'N';

	      else if (*entry == 'Y')
		/* New entry, skip further checks */;

	      /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */

	      else if (OLDER_STAT_TIME (stat_data, m)
		       && (!after_date_option
			   || OLDER_STAT_TIME (stat_data, c)))
		*entry = 'N';
	      else
		*entry = 'Y';
	    }
	}
      free (itr);
    }

  namebuf_free (nbuf);

  if (dirp)
    free (dirp);

  return directory;
}
Exemplo n.º 2
0
/* Recursively scan the directory identified by ST.  */
struct directory *
scan_directory (struct tar_stat_info *st)
{
  char const *dir = st->orig_file_name;
  char *dirp = get_directory_entries (st);
  dev_t device = st->stat.st_dev;
  bool cmdline = ! st->parent;
  namebuf_t nbuf;
  char *tmp;
  struct directory *directory;
  char ch;

  if (! dirp)
    savedir_error (dir);

  info_attach_exclist (st);

  tmp = xstrdup (dir);
  zap_slashes (tmp);

  directory = procdir (tmp, st,
		       (cmdline ? PD_FORCE_INIT : 0),
		       &ch);

  free (tmp);

  nbuf = namebuf_create (dir);

  if (dirp)
    {
      if (directory->children != NO_CHILDREN)
	{
	  char *entry;	/* directory entry being scanned */
	  struct dumpdir_iter *itr;

	  makedumpdir (directory, dirp);

	  for (entry = dumpdir_first (directory->dump, 1, &itr);
	       entry;
	       entry = dumpdir_next (itr))
	    {
	      char *full_name = namebuf_name (nbuf, entry + 1);

	      if (*entry == 'I') /* Ignored entry */
		*entry = 'N';
	      else if (excluded_name (full_name, st))
		*entry = 'N';
	      else
		{
		  int fd = st->fd;
		  void (*diag) (char const *) = 0;
		  struct tar_stat_info stsub;
		  tar_stat_init (&stsub);

		  if (fd < 0)
		    {
		      errno = - fd;
		      diag = open_diag;
		    }
		  else if (fstatat (fd, entry + 1, &stsub.stat,
				    fstatat_flags) != 0)
		    diag = stat_diag;
		  else if (S_ISDIR (stsub.stat.st_mode))
		    {
		      int subfd = subfile_open (st, entry + 1,
						open_read_flags);
		      if (subfd < 0)
			diag = open_diag;
		      else
			{
			  stsub.fd = subfd;
			  if (fstat (subfd, &stsub.stat) != 0)
			    diag = stat_diag;
			}
		    }

		  if (diag)
		    {
		      file_removed_diag (full_name, false, diag);
		      *entry = 'N';
		    }
		  else if (S_ISDIR (stsub.stat.st_mode))
		    {
		      int pd_flag = 0;
		      if (!recursion_option)
			pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
		      else if (directory->children == ALL_CHILDREN)
			pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
		      *entry = 'D';

		      stsub.parent = st;
		      procdir (full_name, &stsub, pd_flag, entry);
		      restore_parent_fd (&stsub);
		    }
		  else if (one_file_system_option &&
			   device != stsub.stat.st_dev)
		    *entry = 'N';
		  else if (*entry == 'Y')
		    /* New entry, skip further checks */;
		  /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */
		  else if (OLDER_STAT_TIME (stsub.stat, m)
			   && (!after_date_option
			       || OLDER_STAT_TIME (stsub.stat, c)))
		    *entry = 'N';
		  else
		    *entry = 'Y';

		  tar_stat_destroy (&stsub);
		}
	    }
	  free (itr);
	}
      else if (directory->tagfile)
	maketagdumpdir (directory);
    }

  namebuf_free (nbuf);

  free (dirp);

  return directory;
}
Exemplo n.º 3
0
static struct directory *
procdir (const char *name_buffer, struct stat *stat_data,
	 dev_t device,
	 int flag,
	 char *entry)
{
  struct directory *directory;
  bool nfs = NFS_FILE_STAT (*stat_data);

  if ((directory = find_directory (name_buffer)) != NULL)
    {
      if (DIR_IS_INITED (directory))
	{
	  if (flag & PD_FORCE_INIT)
	    {
	      assign_string (&directory->name, name_buffer);
	    }
	  else
	    {
	      *entry = 'N'; /* Avoid duplicating this directory */
	      return directory;
	    }
	}

      if (strcmp (directory->name, name_buffer))
	{
	  *entry = 'N';
	  return directory;
	}
      
      /* With NFS, the same file can have two different devices
	 if an NFS directory is mounted in multiple locations,
	 which is relatively common when automounting.
	 To avoid spurious incremental redumping of
	 directories, consider all NFS devices as equal,
	 relying on the i-node to establish differences.  */
      
      if (! ((!check_device_option
	      || (DIR_IS_NFS (directory) && nfs)
	      || directory->device_number == stat_data->st_dev)
	     && directory->inode_number == stat_data->st_ino))
	{
	  /* FIXME: find_directory_meta ignores nfs */
	  struct directory *d = find_directory_meta (stat_data->st_dev,
						     stat_data->st_ino);
	  if (d)
	    {
	      if (strcmp (d->name, name_buffer))
		{
		  WARNOPT (WARN_RENAME_DIRECTORY,
			   (0, 0,
			    _("%s: Directory has been renamed from %s"),
			    quotearg_colon (name_buffer),
			    quote_n (1, d->name)));
		  directory->orig = d;
		  DIR_SET_FLAG (directory, DIRF_RENAMED);
		  dirlist_replace_prefix (d->name, name_buffer);
		}
	      directory->children = CHANGED_CHILDREN;
	    }
	  else
	    {
	      WARNOPT (WARN_RENAME_DIRECTORY,
		       (0, 0, _("%s: Directory has been renamed"),
			quotearg_colon (name_buffer)));
	      directory->children = ALL_CHILDREN;
	      directory->device_number = stat_data->st_dev;
	      directory->inode_number = stat_data->st_ino;
	    }
	  if (nfs)
	    DIR_SET_FLAG (directory, DIRF_NFS);
	}
      else
	directory->children = CHANGED_CHILDREN;
      
      DIR_SET_FLAG (directory, DIRF_FOUND);
    }
  else
    {
      struct directory *d = find_directory_meta (stat_data->st_dev,
						 stat_data->st_ino);
      
      directory = note_directory (name_buffer,
				  get_stat_mtime(stat_data),
				  stat_data->st_dev,
				  stat_data->st_ino,
				  nfs,
				  true,
				  NULL);

      if (d)
	{
	  if (strcmp (d->name, name_buffer))
	    {
	      WARNOPT (WARN_RENAME_DIRECTORY,
		       (0, 0, _("%s: Directory has been renamed from %s"),
			quotearg_colon (name_buffer),
			quote_n (1, d->name)));
	      directory->orig = d;
	      DIR_SET_FLAG (directory, DIRF_RENAMED);
	      dirlist_replace_prefix (d->name, name_buffer);
	    }
	  directory->children = CHANGED_CHILDREN;
	}
      else
	{
	  DIR_SET_FLAG (directory, DIRF_NEW);
	  WARNOPT (WARN_NEW_DIRECTORY,
		   (0, 0, _("%s: Directory is new"),
		    quotearg_colon (name_buffer)));
	  directory->children =
	    (listed_incremental_option
	     || (OLDER_STAT_TIME (*stat_data, m)
		 || (after_date_option
		     && OLDER_STAT_TIME (*stat_data, c))))
	    ? ALL_CHILDREN
	    : CHANGED_CHILDREN;
	}
    }

  /* If the directory is on another device and --one-file-system was given,
     omit it... */
  if (one_file_system_option && device != stat_data->st_dev
      /* ... except if it was explicitely given in the command line */
      && !is_individual_file (name_buffer))
    /* FIXME: 
	WARNOPT (WARN_XDEV,
		 (0, 0,
		  _("%s: directory is on a different filesystem; not dumped"),
		  quotearg_colon (directory->name)));
    */
    directory->children = NO_CHILDREN;
  else if (flag & PD_FORCE_CHILDREN)
    {
      directory->children = PD_CHILDREN(flag);
      if (directory->children == NO_CHILDREN)
	*entry = 'N';
    }
	  
  DIR_SET_FLAG (directory, DIRF_INIT);

  if (directory->children != NO_CHILDREN)
    {
      const char *tag_file_name;

      switch (check_exclusion_tags (name_buffer, &tag_file_name))
	{
	case exclusion_tag_all:
	  /* This warning can be duplicated by code in dump_file0, but only
	     in case when the topmost directory being archived contains
	     an exclusion tag. */
	  exclusion_tag_warning (name_buffer, tag_file_name,
				 _("directory not dumped"));
	  *entry = 'N';
	  directory->children = NO_CHILDREN;
	  break;

	case exclusion_tag_contents:
	  exclusion_tag_warning (name_buffer, tag_file_name,
				 _("contents not dumped"));
	  directory->children = NO_CHILDREN;
	  break;
	  
	case exclusion_tag_under:
	  exclusion_tag_warning (name_buffer, tag_file_name,
				 _("contents not dumped"));
	  directory->tagfile = tag_file_name;
	  break;
	  
	case exclusion_tag_none:
	  break;
	}
    }

  return directory;
}
Exemplo n.º 4
0
Arquivo: incremen.c Projeto: xrg/tar
/* Recursively scan the given directory. */
static const char *
scan_directory (char *dir, dev_t device)
{
  char *dirp = savedir (dir);	/* for scanning directory */
  char *name_buffer;		/* directory, `/', and directory member */
  size_t name_buffer_size;	/* allocated size of name_buffer, minus 2 */
  size_t name_length;		/* used length in name_buffer */
  struct stat stat_data;
  struct directory *directory;
  
  if (! dirp)
    savedir_error (dir);

  name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;
  name_buffer = xmalloc (name_buffer_size + 2);
  strcpy (name_buffer, dir);
  if (! ISSLASH (dir[strlen (dir) - 1]))
    strcat (name_buffer, "/");
  name_length = strlen (name_buffer);

  if (deref_stat (dereference_option, name_buffer, &stat_data))
    {
      stat_diag (name_buffer);
      /* FIXME: used to be
           children = CHANGED_CHILDREN;
	 but changed to: */
      free (name_buffer);
      free (dirp);
      return NULL;
    }

  directory = procdir (name_buffer, &stat_data, device, 0, NULL);

  if (dirp && directory->children != NO_CHILDREN)
    {
      char *entry;	/* directory entry being scanned */
      size_t entrylen;	/* length of directory entry */
      dumpdir_iter_t itr;

      makedumpdir (directory, dirp);

      for (entry = dumpdir_first (directory->dump, 1, &itr);
	   entry;
	   entry = dumpdir_next (itr))
	{
	  entrylen = strlen (entry);
	  if (name_buffer_size <= entrylen - 1 + name_length)
	    {
	      do
		name_buffer_size += NAME_FIELD_SIZE;
	      while (name_buffer_size <= entrylen - 1 + name_length);
	      name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
	    }
	  strcpy (name_buffer + name_length, entry + 1);

	  if (*entry == 'I') /* Ignored entry */
	    *entry = 'N';
	  else if (excluded_name (name_buffer))
	    *entry = 'N';
	  else
	    {
	      if (deref_stat (dereference_option, name_buffer, &stat_data))
		{
		  stat_diag (name_buffer);
		  *entry = 'N';
		  continue;
		}

	      if (S_ISDIR (stat_data.st_mode))
		{
		  int pd_flag = (verbose_option ? PD_VERBOSE : 0);
		  if (!recursion_option)
		    pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN;
		  else if (directory->children == ALL_CHILDREN)
		    pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN;
		  *entry = 'D';
		  procdir (name_buffer, &stat_data, device, pd_flag, entry);
		}

	      else if (one_file_system_option && device != stat_data.st_dev)
		*entry = 'N';

	      else if (*entry == 'Y')
		/* New entry, skip further checks */;

	      /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */

	      else if (OLDER_STAT_TIME (stat_data, m)
		       && (!after_date_option
			   || OLDER_STAT_TIME (stat_data, c)))
		*entry = 'N';
	      else
		*entry = 'Y';
	    }
	}
      free (itr);
    }

  free (name_buffer);
  if (dirp)
    free (dirp);

  return directory->dump ? directory->dump->contents : NULL;
}