]> Dogcows Code - chaz/tar/blobdiff - src/extract.c
Fix copyright notice.
[chaz/tar] / src / extract.c
index 74da1a1bba269df42302300d521371431651c397..96d487c490053d03e89d13952bbccb2a535a9435 100644 (file)
@@ -1,5 +1,5 @@
 /* Extract files from a tar archive.
-   Copyright (C) 1988, 92, 93, 94, 96, 97 Free Software Foundation, Inc.
+   Copyright (C) 1988, 92,93,94,96,97,98, 1999 Free Software Foundation, Inc.
    Written by John Gilmore, on 1985-11-19.
 
    This program is free software; you can redistribute it and/or modify it
@@ -14,7 +14,7 @@
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "system.h"
 
@@ -35,8 +35,8 @@ struct utimbuf
 
 static time_t now;             /* current time */
 static int we_are_root;                /* true if our effective uid == 0 */
-static int newdir_umask;       /* umask when creating new directories */
-static int current_umask;      /* current umask (which is set to 0 if -p) */
+static mode_t newdir_umask;    /* umask when creating new directories */
+static mode_t current_umask;   /* current umask (which is set to 0 if -p) */
 
 #if 0
 /* "Scratch" space to store the information about a sparse file before
@@ -103,9 +103,10 @@ set_mode (char *file_name, struct stat *stat_info)
 
   if (!keep_old_files_option
       || (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
-    if (chmod (file_name, ~current_umask & (int) stat_info->st_mode) < 0)
-      ERROR ((0, errno, _("%s: Cannot change mode to %0.4o"),
-             file_name, ~current_umask & (int) stat_info->st_mode));
+    if (chmod (file_name, ~current_umask & stat_info->st_mode) < 0)
+      ERROR ((0, errno, _("%s: Cannot change mode to %0.4lo"),
+             file_name,
+             (unsigned long) (~current_umask & stat_info->st_mode)));
 }
 
 /*----------------------------------------------------------------------.
@@ -173,14 +174,18 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag)
       if (symlink_flag)
        {
          if (lchown (file_name, stat_info->st_uid, stat_info->st_gid) < 0)
-           ERROR ((0, errno, _("%s: Cannot lchown to uid %d gid %d"),
-                   file_name, stat_info->st_uid, stat_info->st_gid));
+           ERROR ((0, errno, _("%s: Cannot lchown to uid %lu gid %lu"),
+                   file_name,
+                   (unsigned long) stat_info->st_uid,
+                   (unsigned long) stat_info->st_gid));
        }
       else
        {
          if (chown (file_name, stat_info->st_uid, stat_info->st_gid) < 0)
-           ERROR ((0, errno, _("%s: Cannot chown to uid %d gid %d"),
-                   file_name, stat_info->st_uid, stat_info->st_gid));
+           ERROR ((0, errno, _("%s: Cannot chown to uid %lu gid %lu"),
+                   file_name,
+                   (unsigned long) stat_info->st_uid,
+                   (unsigned long) stat_info->st_gid));
        }
 
 #else /* not HAVE_LCHOWN */
@@ -188,8 +193,10 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag)
       if (!symlink_flag)
 
        if (chown (file_name, stat_info->st_uid, stat_info->st_gid) < 0)
-         ERROR ((0, errno, _("%s: Cannot chown to uid %d gid %d"),
-                 file_name, stat_info->st_uid, stat_info->st_gid));
+         ERROR ((0, errno, _("%s: Cannot chown to uid %lu gid %lu"),
+                 file_name,
+                 (unsigned long) stat_info->st_uid,
+                 (unsigned long) stat_info->st_gid));
 
 #endif/* not HAVE_LCHOWN */
 
@@ -197,9 +204,9 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag)
 
        /* On a few systems, and in particular, those allowing to give files
           away, changing the owner or group destroys the suid or sgid bits.
-          So, when root, let's attempt setting these bits once more.  */
+          So let's attempt setting these bits once more.  */
 
-       if (we_are_root && (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
+       if (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX))
          set_mode (file_name, stat_info);
     }
 }
@@ -242,8 +249,10 @@ make_directories (char *file_name)
          if (we_are_root)
            if (chown (file_name, current_stat.st_uid, current_stat.st_gid) < 0)
              ERROR ((0, errno,
-                     _("%s: Cannot change owner to uid %d, gid %d"),
-                     file_name, current_stat.st_uid, current_stat.st_gid));
+                     _("%s: Cannot change owner to uid %lu, gid %lu"),
+                     file_name,
+                     (unsigned long) current_stat.st_uid,
+                     (unsigned long) current_stat.st_gid));
 
          print_for_mkdir (file_name, cursor - file_name,
                           ~newdir_umask & 0777);
@@ -310,11 +319,12 @@ maybe_recoverable (char *file_name)
 `---*/
 
 static void
-extract_sparse_file (int fd, long *sizeleft, long totalsize, char *name)
+extract_sparse_file (int fd, off_t *sizeleft, off_t totalsize, char *name)
 {
   union block *data_block;
   int sparse_ind = 0;
-  int written, count;
+  size_t written;
+  ssize_t count;
 
   /* FIXME: `data_block' might be used uninitialized in this function.
      Reported by Bruno Haible.  */
@@ -333,7 +343,7 @@ extract_sparse_file (int fd, long *sizeleft, long totalsize, char *name)
       written = sparsearray[sparse_ind++].numbytes;
       while (written > BLOCKSIZE)
        {
-         count = write (fd, data_block->buffer, BLOCKSIZE);
+         count = full_write (fd, data_block->buffer, BLOCKSIZE);
          if (count < 0)
            ERROR ((0, errno, _("%s: Could not write to file"), name));
          written -= count;
@@ -342,15 +352,19 @@ extract_sparse_file (int fd, long *sizeleft, long totalsize, char *name)
          data_block = find_next_block ();
        }
 
-      count = write (fd, data_block->buffer, (size_t) written);
+      count = full_write (fd, data_block->buffer, written);
 
       if (count < 0)
        ERROR ((0, errno, _("%s: Could not write to file"), name));
       else if (count != written)
        {
-         ERROR ((0, 0, _("%s: Could only write %d of %d bytes"),
-                    name, count, totalsize));
-         skip_file ((long) (*sizeleft));
+         char buf1[UINTMAX_STRSIZE_BOUND];
+         char buf2[UINTMAX_STRSIZE_BOUND];
+         ERROR ((0, 0, _("%s: Could only write %s of %s bytes"),
+                 name,
+                 STRINGIFY_BIGINT (totalsize - *sizeleft, buf1),
+                 STRINGIFY_BIGINT (totalsize, buf2)));
+         skip_file (*sizeleft);
        }
 
       written -= count;
@@ -371,12 +385,14 @@ extract_archive (void)
   union block *data_block;
   int fd;
   int status;
-  int name_length;
-  int written;
+  ssize_t sstatus;
+  size_t name_length;
+  size_t written;
   int openflag;
-  long size;
+  off_t size;
   int skipcrud;
   int counter;
+  char typeflag;
 #if 0
   int sparse_ind = 0;
 #endif
@@ -392,7 +408,7 @@ extract_archive (void)
     {
       if (current_header->oldgnu_header.isextended)
        skip_extended_headers ();
-      skip_file ((long) current_stat.st_size);
+      skip_file (current_stat.st_size);
       return;
     }
 
@@ -426,13 +442,14 @@ Removing leading `/' from absolute path names in the archive")));
                CURRENT_FILE_NAME));
        if (current_header->oldgnu_header.isextended)
          skip_extended_headers ();
-       skip_file ((long) current_stat.st_size);
+       skip_file (current_stat.st_size);
        return;
       }
 
   /* Extract the archive entry according to its type.  */
 
-  switch (current_header->header.typeflag)
+  typeflag = current_header->header.typeflag;
+  switch (typeflag)
     {
       /* JK - What we want to do if the file is sparse is loop through
         the array of sparse structures in the header and read in and
@@ -456,19 +473,18 @@ Removing leading `/' from absolute path names in the archive")));
       for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
        {
          sparsearray[counter].offset =
-           from_oct (1 + 12,
-                     current_header->oldgnu_header.sp[counter].offset);
+           OFF_FROM_OCT (current_header->oldgnu_header.sp[counter].offset);
          sparsearray[counter].numbytes =
-           from_oct (1 + 12,
-                     current_header->oldgnu_header.sp[counter].numbytes);
+           SIZE_FROM_OCT (current_header->oldgnu_header.sp[counter].numbytes);
          if (!sparsearray[counter].numbytes)
            break;
        }
 
       if (current_header->oldgnu_header.isextended)
        {
-         /* Read in the list of extended headers and translate them into
-            the sparsearray as before.  */
+         /* Read in the list of extended headers and translate them
+            into the sparsearray as before.  Note that this
+            invalidates current_header.  */
 
          /* static */ int ind = SPARSES_IN_OLDGNU_HEADER;
 
@@ -492,11 +508,9 @@ Removing leading `/' from absolute path names in the archive")));
                  if (exhdr->sparse_header.sp[counter].numbytes == 0)
                    break;
                  sparsearray[counter + ind].offset =
-                   from_oct (1 + 12,
-                             exhdr->sparse_header.sp[counter].offset);
+                   OFF_FROM_OCT (exhdr->sparse_header.sp[counter].offset);
                  sparsearray[counter + ind].numbytes =
-                   from_oct (1 + 12,
-                             exhdr->sparse_header.sp[counter].numbytes);
+                   SIZE_FROM_OCT (exhdr->sparse_header.sp[counter].numbytes);
                }
              if (!exhdr->sparse_header.isextended)
                break;
@@ -527,7 +541,7 @@ Removing leading `/' from absolute path names in the archive")));
       openflag = (keep_old_files_option ?
                  O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_EXCL :
                  O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_TRUNC)
-       | ((current_header->header.typeflag == GNUTYPE_SPARSE) ? 0 : O_APPEND);
+       | ((typeflag == GNUTYPE_SPARSE) ? 0 : O_APPEND);
 
       /* JK - The last | is a kludge to solve the problem the O_APPEND
         flag causes with files we are trying to make sparse: when a file
@@ -551,14 +565,14 @@ Removing leading `/' from absolute path names in the archive")));
       /* Contiguous files (on the Masscomp) have to specify the size in
         the open call that creates them.  */
 
-      if (current_header->header.typeflag == CONTTYPE)
+      if (typeflag == CONTTYPE)
        fd = open (CURRENT_FILE_NAME, openflag | O_CTG,
                   current_stat.st_mode, current_stat.st_size);
       else
        fd = open (CURRENT_FILE_NAME, openflag, current_stat.st_mode);
 
 #else /* not O_CTG */
-      if (current_header->header.typeflag == CONTTYPE)
+      if (typeflag == CONTTYPE)
        {
          static int conttype_diagnosed = 0;
 
@@ -581,17 +595,17 @@ Removing leading `/' from absolute path names in the archive")));
                  CURRENT_FILE_NAME));
          if (current_header->oldgnu_header.isextended)
            skip_extended_headers ();
-         skip_file ((long) current_stat.st_size);
+         skip_file (current_stat.st_size);
          if (backup_option)
            undo_last_backup ();
          break;
        }
 
     extract_file:
-      if (current_header->header.typeflag == GNUTYPE_SPARSE)
+      if (typeflag == GNUTYPE_SPARSE)
        {
          char *name;
-         int name_length_bis;
+         size_t name_length_bis;
 
          /* Kludge alert.  NAME is assigned to header.name because
             during the extraction, the space that contains the header
@@ -600,8 +614,8 @@ Removing leading `/' from absolute path names in the archive")));
             REAL interesting unless we do this.  */
 
          name_length_bis = strlen (CURRENT_FILE_NAME) + 1;
-         name = (char *) xmalloc ((sizeof (char)) * name_length_bis);
-         memcpy (name, CURRENT_FILE_NAME, (size_t) name_length_bis);
+         name = (char *) xmalloc (name_length_bis);
+         memcpy (name, CURRENT_FILE_NAME, name_length_bis);
          size = current_stat.st_size;
          extract_sparse_file (fd, &size, current_stat.st_size, name);
        }
@@ -610,9 +624,6 @@ Removing leading `/' from absolute path names in the archive")));
             size > 0;
             size -= written)
          {
-#if 0
-           long offset, numbytes;
-#endif
            if (multi_volume_option)
              {
                assign_string (&save_name, current_file_name);
@@ -636,12 +647,9 @@ Removing leading `/' from absolute path names in the archive")));
               see how many bytes we want to write at that position.  */
 
 #if 0
-           if (current_header->header.typeflag == GNUTYPE_SPARSE)
+           if (typeflag == GNUTYPE_SPARSE)
              {
-               off_t pos;
-
-               pos = lseek (fd, (off_t) sparsearray[sparse_ind].offset, 0);
-               fprintf (msg_file, _("%d at %d\n"), (int) pos, sparse_ind);
+               lseek (fd, sparsearray[sparse_ind].offset, 0);
                written = sparsearray[sparse_ind++].numbytes;
              }
            else
@@ -651,23 +659,25 @@ Removing leading `/' from absolute path names in the archive")));
            if (written > size)
              written = size;
            errno = 0;          /* FIXME: errno should be read-only */
-           status = write (fd, data_block->buffer, (size_t) written);
+           sstatus = full_write (fd, data_block->buffer, written);
 
            set_next_block_after ((union block *)
                                  (data_block->buffer + written - 1));
-           if (status == written)
+           if (sstatus == written)
              continue;
 
            /* Error in writing to file.  Print it, skip to next file in
               archive.  */
 
-           if (status < 0)
+           if (sstatus < 0)
              ERROR ((0, errno, _("%s: Could not write to file"),
                      CURRENT_FILE_NAME));
            else
-             ERROR ((0, 0, _("%s: Could only write %d of %d bytes"),
-                     CURRENT_FILE_NAME, status, written));
-           skip_file ((long) (size - written));
+             ERROR ((0, 0, _("%s: Could only write %lu of %lu bytes"),
+                     CURRENT_FILE_NAME,
+                     (unsigned long) sstatus,
+                     (unsigned long) written));
+           skip_file (size - written);
            break;              /* still do the close, mod time, chmod, etc */
          }
 
@@ -692,11 +702,12 @@ Removing leading `/' from absolute path names in the archive")));
 
              if (!exhdr->sparse_header.sp[counter].numbytes)
                break;
-             offset = from_oct (1 + 12, exhdr->sparse_header.sp[counter].offset);
-             written = from_oct (1 + 12, exhdr->sparse_header.sp[counter].numbytes);
+             offset = OFF_FROM_OCT (exhdr->sparse_header.sp[counter].offset);
+             written
+               = SIZE_FROM_OCT (exhdr->sparse_header.sp[counter].numbytes);
              lseek (fd, offset, 0);
-             status = write (fd, data_block->buffer, written);
-             if (status == written)
+             sstatus = full_write (fd, data_block->buffer, written);
+             if (sstatus == written)
                continue;
            }
        }
@@ -812,8 +823,8 @@ Attempting extraction of symbolic links as hard links")));
       if (unlink_first_option)
        remove_any_file (CURRENT_FILE_NAME, recursive_unlink_option);
 
-      status = mknod (CURRENT_FILE_NAME, (int) current_stat.st_mode,
-                    (int) current_stat.st_rdev);
+      status = mknod (CURRENT_FILE_NAME, current_stat.st_mode,
+                     current_stat.st_rdev);
       if (status != 0)
        {
          if (maybe_recoverable (CURRENT_FILE_NAME))
@@ -836,7 +847,7 @@ Attempting extraction of symbolic links as hard links")));
       if (unlink_first_option)
        remove_any_file (CURRENT_FILE_NAME, recursive_unlink_option);
 
-      while (status = mkfifo (CURRENT_FILE_NAME, (int) current_stat.st_mode),
+      while (status = mkfifo (CURRENT_FILE_NAME, current_stat.st_mode),
             status != 0)
        if (!maybe_recoverable (CURRENT_FILE_NAME))
          break;
@@ -868,15 +879,15 @@ Attempting extraction of symbolic links as hard links")));
 
          gnu_restore (skipcrud);
        }
-      else if (current_header->header.typeflag == GNUTYPE_DUMPDIR)
-       skip_file ((long) (current_stat.st_size));
+      else if (typeflag == GNUTYPE_DUMPDIR)
+       skip_file (current_stat.st_size);
 
       if (to_stdout_option)
        break;
 
     again_dir:
       status = mkdir (CURRENT_FILE_NAME,
-                    (we_are_root ? 0 : 0300) | (int) current_stat.st_mode);
+                    (we_are_root ? 0 : 0300) | current_stat.st_mode);
       if (status != 0)
        {
          /* If the directory creation fails, let's consider immediately the
@@ -929,7 +940,7 @@ Attempting extraction of symbolic links as hard links")));
        }
 
     check_perms:
-      if (!we_are_root && 0300 != (0300 & (int) current_stat.st_mode))
+      if (!we_are_root && 0300 != (0300 & current_stat.st_mode))
        {
          current_stat.st_mode |= 0300;
          WARN ((0, 0, _("Added write and execute permission to directory %s"),
@@ -973,7 +984,7 @@ Attempting extraction of symbolic links as hard links")));
       ERROR ((0, 0, _("\
 Cannot extract `%s' -- file is continued from another volume"),
              current_file_name));
-      skip_file ((long) current_stat.st_size);
+      skip_file (current_stat.st_size);
       if (backup_option)
        undo_last_backup ();
       break;
@@ -981,7 +992,7 @@ Cannot extract `%s' -- file is continued from another volume"),
     case GNUTYPE_LONGNAME:
     case GNUTYPE_LONGLINK:
       ERROR ((0, 0, _("Visible long name error")));
-      skip_file ((long) current_stat.st_size);
+      skip_file (current_stat.st_size);
       if (backup_option)
        undo_last_backup ();
       break;
@@ -989,7 +1000,7 @@ Cannot extract `%s' -- file is continued from another volume"),
     default:
       WARN ((0, 0,
             _("Unknown file type '%c' for %s, extracted as normal file"),
-            current_header->header.typeflag, CURRENT_FILE_NAME));
+            typeflag, CURRENT_FILE_NAME));
       goto again_file;
     }
 
This page took 0.038894 seconds and 4 git commands to generate.