Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37854294
en ru br
ALT Linux repos
S:1.35.0.20.1cdad4cc-alt1
5.0: 1.20-alt1
4.1: 1.20-alt1.M41.1
4.0: 1.15.1-alt8
3.0: 1.15.1-alt2
+updates:1.15.1-alt4.M30.2

Group :: Archiving/Backup
RPM: tar

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: tar-1.20-alt1.M41.1.patch
Download


 doc/tar.texi    |    2 +-
 lib/rtapelib.c  |    6 +++-
 src/create.c    |   21 +++++++++--------
 src/extract.c   |   65 +++++++++++++++++++++++++++++++++++++++---------------
 src/list.c      |    9 +++++++
 src/system.c    |   20 ++++++++++++++++-
 src/tar.c       |    8 +++---
 tests/genfile.c |   12 ++++++---
 8 files changed, 103 insertions(+), 40 deletions(-)
diff --git a/doc/tar.texi b/doc/tar.texi
index 5898792..f0edf99 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -53,7 +53,7 @@ supports it in developing GNU and promoting software freedom.''
 
 @dircategory Archiving
 @direntry
-* Tar: (tar).                   Making tape (or disk) archives.
+* Tar: (tar).                                   Making tape (or disk) archives.
 @end direntry
 
 @dircategory Individual utilities
diff --git a/lib/rtapelib.c b/lib/rtapelib.c
index 51faf3c..b6682b2 100644
--- a/lib/rtapelib.c
+++ b/lib/rtapelib.c
@@ -488,12 +488,14 @@ rmt_open__ (const char *file_name, int open_mode, int bias,
 	/* Child.  */
 
 	close (STDIN_FILENO);
-	dup (to_remote[remote_pipe_number][PREAD]);
+	if (dup (to_remote[remote_pipe_number][PREAD]) != STDIN_FILENO)
+	  error (EXIT_ON_EXEC_ERROR, errno, _("Cannot dup"));
 	close (to_remote[remote_pipe_number][PREAD]);
 	close (to_remote[remote_pipe_number][PWRITE]);
 
 	close (STDOUT_FILENO);
-	dup (from_remote[remote_pipe_number][PWRITE]);
+	if (dup (from_remote[remote_pipe_number][PWRITE]) != STDOUT_FILENO)
+	  error (EXIT_ON_EXEC_ERROR, errno, _("Cannot dup"));
 	close (from_remote[remote_pipe_number][PREAD]);
 	close (from_remote[remote_pipe_number][PWRITE]);
 
diff --git a/src/create.c b/src/create.c
index 413115c..afdb053 100644
--- a/src/create.c
+++ b/src/create.c
@@ -1548,6 +1548,17 @@ dump_file0 (struct tar_stat_info *st, const char *p,
   if (is_avoided_name (p))
     return;
 
+  if (S_ISSOCK (st->stat.st_mode))
+    {
+      WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
+      return;
+    }
+  else if (S_ISDOOR (st->stat.st_mode))
+    {
+      WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
+      return;
+    }
+
   is_dir = S_ISDIR (st->stat.st_mode) != 0;
 
   if (!is_dir && dump_hard_link (st))
@@ -1734,16 +1745,6 @@ dump_file0 (struct tar_stat_info *st, const char *p,
     type = BLKTYPE;
   else if (S_ISFIFO (st->stat.st_mode))
     type = FIFOTYPE;
-  else if (S_ISSOCK (st->stat.st_mode))
-    {
-      WARN ((0, 0, _("%s: socket ignored"), quotearg_colon (p)));
-      return;
-    }
-  else if (S_ISDOOR (st->stat.st_mode))
-    {
-      WARN ((0, 0, _("%s: door ignored"), quotearg_colon (p)));
-      return;
-    }
   else
     {
       unknown_file_error (p);
diff --git a/src/extract.c b/src/extract.c
index 0d938e6..9e0daa6 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -130,6 +130,33 @@ extr_init (void)
     }
 }
 
+static int
+fstat_or_stat (int fd, const char *name, struct stat *st)
+{
+  if (fd != -1)
+    return fstat (fd, st);
+  else
+    return stat (name, st);
+}
+
+static int
+fchown_or_chown (int fd, const char *name, uid_t uid, uid_t gid)
+{
+  if (fd != -1)
+    return fchown (fd, uid, gid);
+  else
+    return chown (name, uid, gid);
+}
+
+static int
+fchmod_or_chmod (int fd, const char *name, mode_t mode)
+{
+  if (fd != -1)
+    return fchmod (fd, mode);
+  else
+    return chmod(name, mode);
+}
+
 /* If restoring permissions, restore the mode for FILE_NAME from
    information given in *STAT_INFO (where *CUR_INFO gives
    the current status if CUR_INFO is nonzero); otherwise invert the
@@ -137,7 +164,7 @@ extr_init (void)
    PERMSTATUS specifies the status of the file's permissions.
    TYPEFLAG specifies the type of the file.  */
 static void
-set_mode (char const *file_name,
+set_mode (int fd, char const *file_name,
 	  struct stat const *stat_info,
 	  struct stat const *cur_info,
 	  mode_t invert_permissions, enum permstatus permstatus,
@@ -176,7 +203,7 @@ set_mode (char const *file_name,
       struct stat st;
       if (! cur_info)
 	{
-	  if (stat (file_name, &st) != 0)
+	  if (fstat_or_stat (fd, file_name, &st) != 0)
 	    {
 	      stat_error (file_name);
 	      return;
@@ -186,7 +213,7 @@ set_mode (char const *file_name,
       mode = cur_info->st_mode ^ invert_permissions;
     }
 
-  if (chmod (file_name, mode) != 0)
+  if (fchmod_or_chmod (fd, file_name, mode) != 0)
     chmod_error_details (file_name, mode);
 }
 
@@ -233,7 +260,7 @@ check_time (char const *file_name, struct timespec t)
    punt for the rest.  Sigh!  */
 
 static void
-set_stat (char const *file_name,
+set_stat (int fd, char const *file_name,
 	  struct tar_stat_info const *st,
 	  struct stat const *cur_info,
 	  mode_t invert_permissions, enum permstatus permstatus,
@@ -259,7 +286,7 @@ set_stat (char const *file_name,
 	    ts[0] = start_time;
 	  ts[1] = st->mtime;
 
-	  if (utimens (file_name, ts) != 0)
+	  if (gl_futimens (fd, file_name, ts) != 0)
 	    utime_error (file_name);
 	  else
 	    {
@@ -292,7 +319,8 @@ set_stat (char const *file_name,
 	}
       else
 	{
-	  chown_result = chown (file_name, st->stat.st_uid, st->stat.st_gid);
+	  chown_result = fchown_or_chown (fd, file_name, st->stat.st_uid,
+					  st->stat.st_gid);
 	}
 
       if (chown_result == 0)
@@ -310,7 +338,7 @@ set_stat (char const *file_name,
     }
 
   if (typeflag != SYMTYPE)
-    set_mode (file_name, &st->stat, cur_info,
+    set_mode (fd, file_name, &st->stat, cur_info,
 	      invert_permissions, permstatus, typeflag);
 }
 
@@ -599,7 +627,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
 	  sb.stat.st_gid = data->gid;
 	  sb.atime = data->atime;
 	  sb.mtime = data->mtime;
-	  set_stat (data->file_name, &sb, cur_info,
+	  set_stat (-1, data->file_name, &sb, cur_info,
 		    data->invert_permissions, data->permstatus, DIRTYPE);
 	}
 
@@ -650,7 +678,7 @@ extract_dir (char *file_name, int typeflag)
 	      || old_files_option == OVERWRITE_OLD_FILES))
 	{
 	  struct stat st;
-	  if (stat (file_name, &st) == 0)
+	  if (lstat (file_name, &st) == 0)
 	    {
 	      if (interdir_made)
 		{
@@ -814,6 +842,12 @@ extract_file (char *file_name, int typeflag)
 
   mv_end ();
 
+  if (!to_stdout_option && !to_command_option)
+    set_stat (fd, file_name, &current_stat_info, NULL, invert_permissions,
+	      (old_files_option == OVERWRITE_OLD_FILES ?
+	       UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),
+	      typeflag);
+
   /* If writing to stdout, don't try to do anything to the filename;
      it doesn't exist, or we don't want to touch it anyway.  */
 
@@ -826,11 +860,6 @@ extract_file (char *file_name, int typeflag)
 
   if (to_command_option)
     sys_wait_command ();
-  else
-    set_stat (file_name, &current_stat_info, NULL, invert_permissions,
-	      (old_files_option == OVERWRITE_OLD_FILES ?
-	       UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),
-	      typeflag);
 
   return status;
 }
@@ -986,7 +1015,7 @@ extract_symlink (char *file_name, int typeflag)
       break;
 
   if (status == 0)
-    set_stat (file_name, &current_stat_info, NULL, 0, 0, SYMTYPE);
+    set_stat (-1, file_name, &current_stat_info, NULL, 0, 0, SYMTYPE);
   else
     symlink_error (current_stat_info.link_name, file_name);
   return status;
@@ -1021,7 +1050,7 @@ extract_node (char *file_name, int typeflag)
   if (status != 0)
     mknod_error (file_name);
   else
-    set_stat (file_name, &current_stat_info, NULL, invert_permissions,
+    set_stat (-1, file_name, &current_stat_info, NULL, invert_permissions,
 	      ARCHIVED_PERMSTATUS, typeflag);
   return status;
 }
@@ -1042,7 +1071,7 @@ extract_fifo (char *file_name, int typeflag)
       break;
 
   if (status == 0)
-    set_stat (file_name, &current_stat_info, NULL, invert_permissions,
+    set_stat (-1, file_name, &current_stat_info, NULL, invert_permissions,
 	      ARCHIVED_PERMSTATUS, typeflag);
   else
     mkfifo_error (file_name);
@@ -1291,7 +1320,7 @@ apply_delayed_links (void)
 		  struct tar_stat_info st1;
 		  st1.stat.st_uid = ds->uid;
 		  st1.stat.st_gid = ds->gid;
-		  set_stat (source, &st1, NULL, 0, 0, SYMTYPE);
+		  set_stat (-1, source, &st1, NULL, 0, 0, SYMTYPE);
 		  valid_source = source;
 		}
 	    }
diff --git a/src/list.c b/src/list.c
index b17f604..c56d9b7 100644
--- a/src/list.c
+++ b/src/list.c
@@ -136,6 +136,14 @@ read_and (void (*do_something) (void))
 
 	  if (!ignore_zeros_option)
 	    {
+
+	      /*
+	       * According to POSIX tar specs, this is wrong, but on the web
+	       * there are some tar specs that can trigger this, and some tar
+	       * implementations create tars according to that spec.  For now,
+	       * let's not be pedantic about issuing the warning.
+	       */
+#if 0
 	      char buf[UINTMAX_STRSIZE_BOUND];
 
 	      status = read_header (false);
@@ -143,6 +151,7 @@ read_and (void (*do_something) (void))
 		break;
 	      WARN ((0, 0, _("A lone zero block at %s"),
 		     STRINGIFY_BIGINT (current_block_ordinal (), buf)));
+#endif
 	      break;
 	    }
 	  status = prev_status;
diff --git a/src/system.c b/src/system.c
index e57e6da..f8ee9f2 100644
--- a/src/system.c
+++ b/src/system.c
@@ -249,7 +249,25 @@ int
 sys_truncate (int fd)
 {
   off_t pos = lseek (fd, (off_t) 0, SEEK_CUR);
-  return pos < 0 ? -1 : ftruncate (fd, pos);
+
+  if (pos < 0)
+    return -1;
+
+  if (ftruncate (fd, pos) && errno == EPERM) {
+    /*
+     * ftruncate may fail to grow the size of a file with some OS and
+     * filesystem combinations.  Linux and vfat/fat is one example.
+     * If this is the case do a write to grow the file to the desired length.
+     */
+    struct stat st;
+
+    if (fstat (fd, &st) ||
+        st.st_size >= pos ||
+        lseek (fd, pos - 1, SEEK_SET) == (off_t)-1 ||
+        write (fd, "\0", 1) != 1)
+      return -1;
+  }
+  return 0;
 }
 
 /* Return nonzero if NAME is the name of a regular file, or if the file
diff --git a/src/tar.c b/src/tar.c
index 4a58a74..b611a8c 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -1336,10 +1336,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case 'I':
-      USAGE_ERROR ((0, 0,
-		    _("Warning: the -I option is not supported;"
-		      " perhaps you meant -j or -T?")));
-      break;
+    case 'y':
+      WARN ((0, 0, _("Warning: option '%c' is deprecated!"
+		     " Next time use -j instead."), key));
+      /* Fall through to using bzip2. */
 
     case 'j':
       set_use_compress_program_option ("bzip2");
diff --git a/tests/genfile.c b/tests/genfile.c
index 91cf5b4..991a395 100644
--- a/tests/genfile.c
+++ b/tests/genfile.c
@@ -480,7 +480,8 @@ mkhole (int fd, off_t displ)
 {
   if (lseek (fd, displ, SEEK_CUR) == -1)
     error (EXIT_FAILURE, errno, "lseek");
-  ftruncate (fd, lseek (fd, 0, SEEK_CUR));
+  if (ftruncate (fd, lseek (fd, 0, SEEK_CUR)))
+    error (EXIT_FAILURE, errno, "ftruncate");
 }
 
 static void
@@ -678,13 +679,15 @@ exec_checkpoint (struct action *p)
 	    error (0, errno, _("cannot open `%s'"), p->name);
 	    break;
 	  }
-	ftruncate (fd, p->size);
+	if (ftruncate (fd, p->size))
+	  error (0, errno, _("cannot truncate `%s'"), p->name);
 	close (fd);
       }
       break;
 
     case OPT_EXEC:
-      system (p->name);
+      if (system (p->name) == -1)
+	error (0, errno, _("cannot execute `%s'"), p->name);
       break;
 
     default:
@@ -743,7 +746,8 @@ exec_command (void)
   signal (SIGCHLD, SIG_DFL);
 #endif
 
-  pipe (fd);
+  if (pipe (fd))
+    error (EXIT_FAILURE, errno, "pipe");
 
   pid = fork ();
   if (pid == -1)
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin