Example #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;
}
Example #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;
}
Example #3
0
/* Implement the 'r' (add files to end of archive), and 'u' (add files
   to end of archive if they aren't there, or are more up to date than
   the version in the archive) commands.  */
void
update_archive (void)
{
  enum read_header previous_status = HEADER_STILL_UNREAD;
  bool found_end = false;

  name_gather ();
  open_archive (ACCESS_UPDATE);
  xheader_write_global ();

  while (!found_end)
    {
      enum read_header status = read_header (false);

      switch (status)
	{
	case HEADER_STILL_UNREAD:
	case HEADER_SUCCESS_EXTENDED:
	  abort ();

	case HEADER_SUCCESS:
	  {
	    struct name *name;

	    decode_header (current_header, &current_stat_info,
			   &current_format, 0);
	    archive_format = current_format;
	    
	    if (subcommand_option == UPDATE_SUBCOMMAND
		&& (name = name_scan (current_stat_info.file_name)) != NULL)
	      {
		struct stat s;

		chdir_do (name->change_dir);
		if (deref_stat (dereference_option,
				current_stat_info.file_name, &s) == 0
		    && s.st_mtime <= current_stat_info.stat.st_mtime)
		  add_avoided_name (current_stat_info.file_name);
	      }

	    skip_member ();
	    break;
	  }

	case HEADER_ZERO_BLOCK:
	  current_block = current_header;
	  found_end = true;
	  break;

	case HEADER_END_OF_FILE:
	  found_end = true;
	  break;

	case HEADER_FAILURE:
	  set_next_block_after (current_header);
	  switch (previous_status)
	    {
	    case HEADER_STILL_UNREAD:
	      WARN ((0, 0, _("This does not look like a tar archive")));
	      /* Fall through.  */

	    case HEADER_SUCCESS:
	    case HEADER_ZERO_BLOCK:
	      ERROR ((0, 0, _("Skipping to next header")));
	      /* Fall through.  */

	    case HEADER_FAILURE:
	      break;

	    case HEADER_END_OF_FILE:
	    case HEADER_SUCCESS_EXTENDED:
	      abort ();
	    }
	  break;
	}

      tar_stat_destroy (&current_stat_info);
      xheader_destroy (&extended_header);
      previous_status = status;
    }

  reset_eof ();
  time_to_start_writing = true;
  output_start = current_block->buffer;

  {
    char *file_name;

    while ((file_name = name_from_list ()) != NULL)
      {
	if (excluded_name (file_name))
	  continue;
	if (interactive_option && !confirm ("add", file_name))
	  continue;
	if (subcommand_option == CAT_SUBCOMMAND)
	  append_file (file_name);
	else
	  dump_file (file_name, 1, (dev_t) 0);
      }
  }

  write_eot ();
  close_archive ();
  names_notfound ();
}
Example #4
0
File: incremen.c Project: 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;
}