Beispiel #1
0
/* Print the names of things in the namelist that were not matched.  */
void
names_notfound (void)
{
  struct name const *cursor;

  for (cursor = namelist; cursor; cursor = cursor->next)
    if (!WASFOUND (cursor) && cursor->name[0])
      {
	regex_usage_warning (cursor->name);
	if (cursor->found_count == 0)
	  ERROR ((0, 0, _("%s: Not found in archive"),
		  quotearg_colon (cursor->name)));
	else
	  ERROR ((0, 0, _("%s: Required occurrence not found in archive"),
		  quotearg_colon (cursor->name)));  
      }

  /* Don't bother freeing the name list; we're about to exit.  */
  namelist = NULL;
  nametail = NULL;

  if (same_order_option)
    {
      const char *name;

      while ((name = name_next (1)) != NULL)
	{
	  regex_usage_warning (name);
	  ERROR ((0, 0, _("%s: Not found in archive"),
		  quotearg_colon (name)));
	}
    }
}
Beispiel #2
0
/* Read incremental snapshot format 2 */
static void
read_incr_db_2 (void)
{
  struct obstack stk;
  char offbuf[INT_BUFSIZE_BOUND (off_t)];

  obstack_init (&stk);

  read_timespec (listed_incremental_stream, &newer_mtime_option);

  for (;;)
    {
      intmax_t i;
      struct timespec mtime;
      dev_t dev;
      ino_t ino;
      bool nfs;
      char *name;
      char *content;
      size_t s;

      if (! read_num (listed_incremental_stream, "nfs", 0, 1, &i))
	return; /* Normal return */

      nfs = i;

      read_timespec (listed_incremental_stream, &mtime);

      if (! read_num (listed_incremental_stream, "dev",
		      TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i))
	break;
      dev = i;

      if (! read_num (listed_incremental_stream, "ino",
		      TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i))
	break;
      ino = i;

      if (read_obstack (listed_incremental_stream, &stk, &s))
	break;

      name = obstack_finish (&stk);

      while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
	;
      if (getc (listed_incremental_stream) != 0)
	FATAL_ERROR ((0, 0, _("%s: byte %s: %s"),
		      quotearg_colon (listed_incremental_option),
		      offtostr (ftello (listed_incremental_stream), offbuf),
		      _("Missing record terminator")));

      content = obstack_finish (&stk);
      note_directory (name, mtime, dev, ino, nfs, false, content);
      obstack_free (&stk, content);
    }
  FATAL_ERROR ((0, 0, "%s: %s",
		quotearg_colon (listed_incremental_option),
		_("Unexpected EOF in snapshot file")));
}
Beispiel #3
0
/* Read incremental snapshot format 2 */
static void
read_incr_db_2 ()
{
  uintmax_t u;
  struct obstack stk;

  obstack_init (&stk);

  read_timespec (listed_incremental_stream, &newer_mtime_option);

  for (;;)
    {
      struct timespec mtime;
      dev_t dev;
      ino_t ino;
      bool nfs;
      char *name;
      char *content;
      size_t s;

      if (read_num (listed_incremental_stream, 1, &u))
	return; /* Normal return */

      nfs = u;

      read_timespec (listed_incremental_stream, &mtime);

      if (read_num (listed_incremental_stream, TYPE_MAXIMUM (dev_t), &u))
	break;
      dev = u;

      if (read_num (listed_incremental_stream, TYPE_MAXIMUM (ino_t), &u))
	break;
      ino = u;

      if (read_obstack (listed_incremental_stream, &stk, &s))
	break;

      name = obstack_finish (&stk);

      while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
	;
      if (getc (listed_incremental_stream) != 0)
	FATAL_ERROR ((0, 0, "%s: %s",
		      quotearg_colon (listed_incremental_option),
		      _("Missing record terminator")));

      content = obstack_finish (&stk);
      note_directory (name, mtime, dev, ino, nfs, false, content);
      obstack_free (&stk, content);
    }
  FATAL_ERROR ((0, 0, "%s: %s",
		quotearg_colon (listed_incremental_option),
		_("Unexpected EOF in snapshot file")));
}
Beispiel #4
0
static void
read_timespec (FILE *fp, struct timespec *pval)
{
  int c = getc (fp);
  intmax_t i;
  uintmax_t u;

  if (c == '-')
    {
      read_negative_num (fp, TYPE_MINIMUM (time_t), &i);
      c = 0;
      pval->tv_sec = i;
    }
  else
    {
      c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);
      pval->tv_sec = u;
    }

  if (c || read_num (fp, BILLION - 1, &u))
    FATAL_ERROR ((0, 0, "%s: %s",
		  quotearg_colon (listed_incremental_option),
		  _("Unexpected EOF in snapshot file")));
  pval->tv_nsec = u;
}
Beispiel #5
0
void
symlink_error (char const *contents, char const *name)
{
  int e = errno;
  ERROR ((0, e, _("%s: Cannot create symlink to %s"),
	  quotearg_colon (name), quote_n (1, contents)));
}
Beispiel #6
0
void
link_error (char const *target, char const *source)
{
  int e = errno;
  ERROR ((0, e, _("%s: Cannot hard link to %s"),
	  quotearg_colon (source), quote_n (1, target)));
}
Beispiel #7
0
void
chown_error_details (char const *name, uid_t uid, gid_t gid)
{
  int e = errno;
  ERROR ((0, e, _("%s: Cannot change ownership to uid %lu, gid %lu"),
	  quotearg_colon (name), (unsigned long) uid, (unsigned long) gid));
}
Beispiel #8
0
void
close_stdout (void)
{
  bool prev_fail = ferror (stdout);
  bool none_pending = (0 == __fpending (stdout));
  bool fclose_fail = fclose (stdout);

  if (prev_fail || fclose_fail)
    {
      int e = fclose_fail ? errno : 0;
      char const *write_error;

      /* If ferror returned zero, no data remains to be flushed, and we'd
	 otherwise fail with EBADF due to a failed fclose, then assume that
	 it's ok to ignore the fclose failure.  That can happen when a
	 program like cp is invoked like this `cp a b >&-' (i.e., with
	 stdout closed) and doesn't generate any output (hence no previous
	 error and nothing to be flushed).  */
      if (e == EBADF && !prev_fail && none_pending)
	return;

      write_error = _("write error");
      if (file_name)
	error (exit_failure, e, "%s: %s", quotearg_colon (file_name),
	       write_error);
      else
	error (exit_failure, e, "%s", write_error);
    }
}
Beispiel #9
0
void
close_stdin (void)
{
  bool fail = false;

  /* There is no need to flush stdin if we can determine quickly that stdin's
     input buffer is empty; in this case we know that if stdin is seekable,
     fseeko (stdin, 0, SEEK_CUR) == lseek (0, 0, SEEK_CUR).  */
  //if (freadahead (stdin) > 0)
    {
      /* Only attempt flush if stdin is seekable, as fflush is entitled to
         fail on non-seekable streams.  */
      if (fseek (stdin, 0, SEEK_CUR) == 0 && fflush (stdin) != 0)
        fail = true;
    }
  if (close_stream (stdin) != 0)
    fail = true;
  if (fail)
    {
      /* Report failure, but defer exit until after closing stdout,
         since the failure report should still be flushed.  */
      char const *close_error = _("error closing file");
      if (file_name)
        error (0, errno, "%s: %s", quotearg_colon (file_name),
               close_error);
      else
        error (0, errno, "%s", close_error);
    }

  close_stdout ();

  if (fail)
    _exit (exit_failure);
}
Beispiel #10
0
/* Check if FILE_NAME already exists and make a backup of it right now.
   Return success (nonzero) only if the backup is either unneeded, or
   successful.  For now, directories are considered to never need
   backup.  If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
   so, we do not have to backup block or character devices, nor remote
   entities.  */
bool
maybe_backup_file (const char *file_name, bool this_is_the_archive)
{
  struct stat file_stat;

  assign_string (&before_backup_name, file_name);

  /* A run situation may exist between Emacs or other GNU programs trying to
     make a backup for the same file simultaneously.  If theoretically
     possible, real problems are unlikely.  Doing any better would require a
     convention, GNU-wide, for all programs doing backups.  */

  assign_string (&after_backup_name, 0);

  /* Check if we really need to backup the file.  */

  if (this_is_the_archive && _remdev (file_name))
    return true;

  if (deref_stat (file_name, &file_stat) != 0)
    {
      if (errno == ENOENT)
	return true;

      stat_error (file_name);
      return false;
    }

  if (S_ISDIR (file_stat.st_mode))
    return true;

  if (this_is_the_archive
      && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
    return true;

  after_backup_name = find_backup_file_name (file_name, backup_type);
  if (! after_backup_name)
    xalloc_die ();

  if (renameat (chdir_fd, before_backup_name, chdir_fd, after_backup_name)
      == 0)
    {
      if (verbose_option)
	fprintf (stdlis, _("Renaming %s to %s\n"),
		 quote_n (0, before_backup_name),
		 quote_n (1, after_backup_name));
      return true;
    }
  else
    {
      /* The backup operation failed.  */
      int e = errno;
      ERROR ((0, e, _("%s: Cannot rename to %s"),
	      quotearg_colon (before_backup_name),
	      quote_n (1, after_backup_name)));
      assign_string (&after_backup_name, 0);
      return false;
    }
}
Beispiel #11
0
static char *
use_quotearg_colon (const char *str, size_t *len)
{
  char *p = (*len == SIZE_MAX ? quotearg_colon (str)
             : quotearg_colon_mem (str, *len));
  *len = strlen (p);
  return p;
}
static void ATTRIBUTE_NORETURN
randread_error (void const *file_name)
{
  if (file_name)
    error (exit_failure, errno,
           errno == 0 ? _("%s: end of file") : _("%s: read error"),
           quotearg_colon (file_name));
  abort ();
}
Beispiel #13
0
void
seek_warn_details (char const *name, off_t offset)
{
  char buf[UINTMAX_STRSIZE_BOUND];
  int e = errno;
  WARN ((0, e, _("%s: Warning: Cannot seek to %s"),
	 quotearg_colon (name),
	 STRINGIFY_BIGINT (offset, buf)));
}
Beispiel #14
0
void
chmod_error_details (char const *name, mode_t mode)
{
  int e = errno;
  char buf[10];
  decode_mode (mode, buf);
  ERROR ((0, e, _("%s: Cannot change mode to %s"),
	  quotearg_colon (name), buf));
}
Beispiel #15
0
/* Report a warning associated with the system call CALL and
   the optional file name NAME.  */
void
call_arg_warn (char const *call, char const *name)
{
  int e = errno;
  /* TRANSLATORS: %s after `Cannot' is a function name, e.g. `Cannot open'.
     Directly translating this to another language will not work, first because
     %s itself is not translated.
     Translate it as `%s: Function %s failed'. */
  WARN ((0, e, _("%s: Warning: Cannot %s"), quotearg_colon (name), call));
}
Beispiel #16
0
/* Catenate file FILE_NAME to the archive without creating a header for it.
   It had better be a tar file or the archive is screwed.  */
static void
append_file (char *file_name)
{
  int handle = open (file_name, O_RDONLY | O_BINARY);
  struct stat stat_data;

  if (handle < 0)
    {
      open_error (file_name);
      return;
    }

  if (fstat (handle, &stat_data) != 0)
    stat_error (file_name);
  else
    {
      off_t bytes_left = stat_data.st_size;

      while (bytes_left > 0)
	{
	  union block *start = find_next_block ();
	  size_t buffer_size = available_space_after (start);
	  size_t status;
	  char buf[UINTMAX_STRSIZE_BOUND];

	  if (bytes_left < buffer_size)
	    {
	      buffer_size = bytes_left;
	      status = buffer_size % BLOCKSIZE;
	      if (status)
		memset (start->buffer + bytes_left, 0, BLOCKSIZE - status);
	    }

	  status = safe_read (handle, start->buffer, buffer_size);
	  if (status == SAFE_READ_ERROR)
	    read_fatal_details (file_name, stat_data.st_size - bytes_left,
				buffer_size);
	  if (status == 0)
	    FATAL_ERROR ((0, 0,
			  ngettext ("%s: File shrank by %s byte",
				    "%s: File shrank by %s bytes",
				    bytes_left),
			  quotearg_colon (file_name),
			  STRINGIFY_BIGINT (bytes_left, buf)));

	  bytes_left -= status;

	  set_next_block_after (start + (status - 1) / BLOCKSIZE);
	}
    }

  if (close (handle) != 0)
    close_error (file_name);
}
Beispiel #17
0
void
read_fatal_details (char const *name, off_t offset, size_t size)
{
  char buf[UINTMAX_STRSIZE_BOUND];
  int e = errno;
  FATAL_ERROR ((0, e,
		ngettext ("%s: Read error at byte %s, reading %lu byte",
			  "%s: Read error at byte %s, reading %lu bytes",
			  size),
		quotearg_colon (name), STRINGIFY_BIGINT (offset, buf),
		(unsigned long) size));
}
Beispiel #18
0
FILE *
xfopen (const char *name, const char *mode)
{
  FILE *ptr;

  ptr = fopen (name, mode);
  if (!ptr)
    error (EXIT_FAILURE, get_errno (),
           _("%s: cannot open"), quotearg_colon (name));

  return ptr;
}
Beispiel #19
0
void
file_removed_diag (const char *name, bool top_level,
		   void (*diagfn) (char const *name))
{
  if (!top_level && errno == ENOENT)
    {
      WARNOPT (WARN_FILE_REMOVED,
	       (0, 0, _("%s: File removed before we read it"),
		quotearg_colon (name)));
      set_exit_status (TAREXIT_DIFFERS);
    }
  else
    diagfn (name);
}
Beispiel #20
0
/* Sigh about something that differs by writing a MESSAGE to stdlis,
   given MESSAGE is nonzero.  Also set the exit status if not already.  */
void
report_difference (struct tar_stat_info *st, const char *fmt, ...)
{
  if (fmt)
    {
      va_list ap;

      fprintf (stdlis, "%s: ", quotearg_colon (st->file_name));
      va_start (ap, fmt);
      vfprintf (stdlis, fmt, ap);
      va_end (ap);
      fprintf (stdlis, "\n");
    }

  set_exit_status (TAREXIT_DIFFERS);
}
void
close_stdout (void)
{
  if (close_stream (stdout) != 0)
    {
      char const *write_error = _("write error");
      if (file_name)
	error (0, errno, "%s: %s", quotearg_colon (file_name),
	       write_error);
      else
	error (0, errno, "%s", write_error);

      _exit (exit_failure);
    }

   if (close_stream (stderr) != 0)
     _exit (exit_failure);
}
Beispiel #22
0
static void
read_timespec (FILE *fp, struct timespec *pval)
{
  intmax_t s, ns;

  if (read_num (fp, "sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &s)
      && read_num (fp, "nsec", 0, BILLION - 1, &ns))
    {
      pval->tv_sec = s;
      pval->tv_nsec = ns;
    }
  else
    {
      FATAL_ERROR ((0, 0, "%s: %s",
		    quotearg_colon (listed_incremental_option),
		    _("Unexpected EOF in snapshot file")));
    }
}
Beispiel #23
0
void close_stdout( void )
{
  if ( close_stream( *(int*)(134628384) ) != 0 )
  {
    char *write_error = gettext( "write error" );
    if ( file_name != 0 )
    {
      error( 0, *(int*)(__errno_location( )), "%s: %s", quotearg_colon( file_name ), write_error );
    }
    error( 0, *(int*)(__errno_location( )), "%s", write_error );
    _exit( exit_failure );
  }
  if ( close_stream( *(int*)(134628356) ) != 0 )
  {
    _exit( exit_failure );
  }
  return;
}
Beispiel #24
0
/* Try to restore the recently backed up file to its original name.
   This is usually only needed after a failed extraction.  */
void
undo_last_backup (void)
{
  if (after_backup_name)
    {
      if (rename (after_backup_name, before_backup_name) != 0)
	{
	  int e = errno;
	  ERROR ((0, e, _("%s: Cannot rename to %s"),
		  quotearg_colon (after_backup_name),
		  quote_n (1, before_backup_name)));
	}
      if (verbose_option)
	fprintf (stdlis, _("Renaming %s back to %s\n"),
		 quote_n (0, after_backup_name),
		 quote_n (1, before_backup_name));
      assign_string (&after_backup_name, 0);
    }
}
Beispiel #25
0
void
close_stdout_status (int status)
{
  int e = ferror (stdout) ? 0 : -1;

  if (__fpending (stdout) == 0)
    return;

  if (fclose (stdout) != 0)
    e = errno;

  if (0 <= e)
    {
      char const *write_error = _("write error");
      if (file_name)
	error (status, e, "%s: %s", quotearg_colon (file_name), write_error);
      else
	error (status, e, "%s", write_error);
    }
}
Beispiel #26
0
void
close_stdout (void)
{
  int e = ferror (stdout) ? 0 : -1;

  /* If the stream's error bit is clear and there is nothing to flush,
     then return right away.  */
  if (e && __fpending (stdout) == 0)
    return;

  if (fclose (stdout) != 0)
    e = errno;

  if (0 <= e)
    {
      char const *write_error = _("write error");
      if (file_name)
	error (exit_failure, e, "%s: %s", quotearg_colon (file_name),
	       write_error);
      else
	error (exit_failure, e, "%s", write_error);
    }
}
Beispiel #27
0
/* Read incremental snapshot formats 0 and 1 */
static void
read_incr_db_01 (int version, const char *initbuf)
{
  int n;
  uintmax_t u;
  time_t sec;
  long int nsec;
  char *buf = NULL;
  size_t bufsize = 0;
  char *ebuf;
  long lineno = 1;

  if (version == 1)
    {
      if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)
	{
	  read_error (listed_incremental_option);
	  free (buf);
	  return;
	}
      ++lineno;
    }
  else
    {
      buf = strdup (initbuf);
      bufsize = strlen (buf) + 1;
    }

  sec = TYPE_MINIMUM (time_t);
  nsec = -1;
  errno = 0;
  u = strtoumax (buf, &ebuf, 10);
  if (!errno && TYPE_MAXIMUM (time_t) < u)
    errno = ERANGE;
  if (errno || buf == ebuf)
    ERROR ((0, errno, "%s:%ld: %s",
	    quotearg_colon (listed_incremental_option),
	    lineno,
	    _("Invalid time stamp")));
  else
    {
      sec = u;

      if (version == 1 && *ebuf)
	{
	  char const *buf_ns = ebuf + 1;
	  errno = 0;
	  u = strtoumax (buf_ns, &ebuf, 10);
	  if (!errno && BILLION <= u)
	    errno = ERANGE;
	  if (errno || buf_ns == ebuf)
	    {
	      ERROR ((0, errno, "%s:%ld: %s",
		      quotearg_colon (listed_incremental_option),
		      lineno,
		      _("Invalid time stamp")));
	      sec = TYPE_MINIMUM (time_t);
	    }
	  else
	    nsec = u;
	}
      else
	{
	  /* pre-1 incremental format does not contain nanoseconds */
	  nsec = 0;
	}
    }
  newer_mtime_option.tv_sec = sec;
  newer_mtime_option.tv_nsec = nsec;


  while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))
    {
      dev_t dev;
      ino_t ino;
      bool nfs = buf[0] == '+';
      char *strp = buf + nfs;
      struct timespec mtime;

      lineno++;

      if (buf[n - 1] == '\n')
	buf[n - 1] = '\0';

      if (version == 1)
	{
	  errno = 0;
	  u = strtoumax (strp, &ebuf, 10);
	  if (!errno && TYPE_MAXIMUM (time_t) < u)
	    errno = ERANGE;
	  if (errno || strp == ebuf || *ebuf != ' ')
	    {
	      ERROR ((0, errno, "%s:%ld: %s",
		      quotearg_colon (listed_incremental_option), lineno,
		      _("Invalid modification time (seconds)")));
	      sec = (time_t) -1;
	    }
	  else
	    sec = u;
	  strp = ebuf;

	  errno = 0;
	  u = strtoumax (strp, &ebuf, 10);
	  if (!errno && BILLION <= u)
	    errno = ERANGE;
	  if (errno || strp == ebuf || *ebuf != ' ')
	    {
	      ERROR ((0, errno, "%s:%ld: %s",
		      quotearg_colon (listed_incremental_option), lineno,
		      _("Invalid modification time (nanoseconds)")));
	      nsec = -1;
	    }
	  else
	    nsec = u;
	  mtime.tv_sec = sec;
	  mtime.tv_nsec = nsec;
	  strp = ebuf;
	}
      else
	memset (&mtime, 0, sizeof mtime);

      errno = 0;
      u = strtoumax (strp, &ebuf, 10);
      if (!errno && TYPE_MAXIMUM (dev_t) < u)
	errno = ERANGE;
      if (errno || strp == ebuf || *ebuf != ' ')
	{
	  ERROR ((0, errno, "%s:%ld: %s",
		  quotearg_colon (listed_incremental_option), lineno,
		  _("Invalid device number")));
	  dev = (dev_t) -1;
	}
      else
	dev = u;
      strp = ebuf;

      errno = 0;
      u = strtoumax (strp, &ebuf, 10);
      if (!errno && TYPE_MAXIMUM (ino_t) < u)
	errno = ERANGE;
      if (errno || strp == ebuf || *ebuf != ' ')
	{
	  ERROR ((0, errno, "%s:%ld: %s",
		  quotearg_colon (listed_incremental_option), lineno,
		  _("Invalid inode number")));
	  ino = (ino_t) -1;
	}
      else
	ino = u;
      strp = ebuf;

      strp++;
      unquote_string (strp);
      note_directory (strp, mtime, dev, ino, nfs, false, NULL);
    }
  free (buf);
}
Beispiel #28
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;
}
Beispiel #29
0
/* Examine the directories under directory_name and delete any
   files that were not there at the time of the back-up. */
static bool
try_purge_directory (char const *directory_name)
{
  char *current_dir;
  char *cur, *arc, *p;
  char *temp_stub = NULL;
  struct dumpdir *dump;

  if (!is_dumpdir (&current_stat_info))
    return false;

  current_dir = savedir (directory_name);

  if (!current_dir)
    /* The directory doesn't exist now.  It'll be created.  In any
       case, we don't have to delete any files out of it.  */
    return false;

  /* Verify if dump directory is sane */
  if (!dumpdir_ok (current_stat_info.dumpdir))
    return false;

  /* Process renames */
  for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
    {
      if (*arc == 'X')
	{
#define TEMP_DIR_TEMPLATE "tar.XXXXXX"
	  size_t len = strlen (arc + 1);
	  temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
	  memcpy (temp_stub, arc + 1, len);
	  temp_stub[len] = '/';
	  memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
		  sizeof TEMP_DIR_TEMPLATE);
	  if (!mkdtemp (temp_stub))
	    {
	      ERROR ((0, errno,
		      _("Cannot create temporary directory using template %s"),
		      quote (temp_stub)));
	      free (temp_stub);
	      free (current_dir);
	      return false;
	    }
	}
      else if (*arc == 'R')
	{
	  char *src, *dst;
	  src = arc + 1;
	  arc += strlen (arc) + 1;
	  dst = arc + 1;

	  /* Ensure that neither source nor destination are absolute file
	     names (unless permitted by -P option), and that they do not
	     contain dubious parts (e.g. ../).

	     This is an extra safety precaution. Besides, it might be
	     necessary to extract from archives created with tar versions
	     prior to 1.19. */

	  if (*src)
	    src = safer_name_suffix (src, false, absolute_names_option);
	  if (*dst)
	    dst = safer_name_suffix (dst, false, absolute_names_option);

	  if (*src == 0)
	    src = temp_stub;
	  else if (*dst == 0)
	    dst = temp_stub;

	  if (!rename_directory (src, dst))
	    {
	      free (temp_stub);
	      free (current_dir);
	      /* FIXME: Make sure purge_directory(dst) will return
		 immediately */
	      return false;
	    }
	}
    }

  free (temp_stub);

  /* Process deletes */
  dump = dumpdir_create (current_stat_info.dumpdir);
  p = NULL;
  for (cur = current_dir; *cur; cur += strlen (cur) + 1)
    {
      const char *entry;
      struct stat st;
      if (p)
	free (p);
      p = new_name (directory_name, cur);

      if (deref_stat (false, p, &st))
	{
	  if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed
				  dirs and check it here? */
	    {
	      stat_diag (p);
	      WARN ((0, 0, _("%s: Not purging directory: unable to stat"),
		     quotearg_colon (p)));
	    }
	  continue;
	}

      if (!(entry = dumpdir_locate (dump, cur))
	  || (*entry == 'D' && !S_ISDIR (st.st_mode))
	  || (*entry == 'Y' && S_ISDIR (st.st_mode)))
	{
	  if (one_file_system_option && st.st_dev != root_device)
	    {
	      WARN ((0, 0,
		     _("%s: directory is on a different device: not purging"),
		     quotearg_colon (p)));
	      continue;
	    }

	  if (! interactive_option || confirm ("delete", p))
	    {
	      if (verbose_option)
		fprintf (stdlis, _("%s: Deleting %s\n"),
			 program_name, quote (p));
	      if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION))
		{
		  int e = errno;
		  ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p)));
		}
	    }
	}
    }
  free (p);
  dumpdir_free (dump);
  
  free (current_dir);
  return true;
}
Beispiel #30
0
void
info_attach_exclist (struct tar_stat_info *dir)
{
  struct excfile *file;
  struct exclist *head = NULL, *tail = NULL, *ent;
  struct vcs_ignore_file *vcsfile;

  if (dir->exclude_list)
    return;
  for (file = excfile_head; file; file = file->next)
    {
      if (faccessat (dir ? dir->fd : chdir_fd, file->name, F_OK, 0) == 0)
	{
	  FILE *fp;
	  struct exclude *ex = NULL;
	  int fd = subfile_open (dir, file->name, O_RDONLY);
	  if (fd == -1)
	    {
	      open_error (file->name);
	      continue;
	    }
	  fp = fdopen (fd, "r");
	  if (!fp)
	    {
	      ERROR ((0, errno, _("%s: fdopen failed"), file->name));
	      close (fd);
	      continue;
	    }

	  if (!ex)
	    ex = new_exclude ();

	  vcsfile = get_vcs_ignore_file (file->name);

	  if (vcsfile->initfn)
	    vcsfile->data = vcsfile->initfn (vcsfile->data);

	  if (add_exclude_fp (vcsfile->addfn, ex, fp,
			      EXCLUDE_WILDCARDS|EXCLUDE_ANCHORED, '\n',
			      vcsfile->data))
	    {
	      int e = errno;
	      FATAL_ERROR ((0, e, "%s", quotearg_colon (file->name)));
	    }
	  fclose (fp);

	  ent = xmalloc (sizeof (*ent));
	  ent->excluded = ex;
	  ent->flags = file->flags == EXCL_DEFAULT
	               ? file->flags : vcsfile->flags;
	  ent->prev = tail;
	  ent->next = NULL;

	  if (tail)
	    tail->next = ent;
	  else
	    head = ent;
	  tail = ent;
	}
    }
  dir->exclude_list = head;
}