]> Dogcows Code - chaz/tar/blobdiff - src/extract.c
*** empty log message ***
[chaz/tar] / src / extract.c
index b717114e3d638f857f84d10fb7943dc19362ea56..84e6a234371f34016a98b1a355e110f22ad903ca 100644 (file)
@@ -217,7 +217,7 @@ extract_archive ()
          */
     case LF_SPARSE:
       sp_array_size = 10;
-      sparsearray = (struct sp_array *) malloc (sp_array_size * sizeof (struct sp_array));
+      sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
       for (i = 0; i < SPARSE_IN_HDR; i++)
        {
          sparsearray[i].offset =
@@ -252,7 +252,7 @@ extract_archive ()
                                          * since we've run out of room --
                                          */
                      sparsearray = (struct sp_array *)
-                       realloc (sparsearray,
+                       ck_realloc (sparsearray,
                            2 * sp_array_size * (sizeof (struct sp_array)));
                      sp_array_size *= 2;
                    }
@@ -367,8 +367,8 @@ extract_archive ()
                          * that happen to contain the filename will look
                          * REAL interesting unless we do this.
                          */
-         namelen = strlen (skipcrud + current_file_name);
-         name = (char *) malloc ((sizeof (char)) * namelen);
+         namelen = strlen (skipcrud + current_file_name) + 1;
+         name = (char *) ck_malloc ((sizeof (char)) * namelen);
          bcopy (skipcrud + current_file_name, name, namelen);
          size = hstat.st_size;
          extract_sparse_file (fd, &size, hstat.st_size, name);
@@ -436,7 +436,7 @@ extract_archive ()
                          skipcrud + current_file_name);
            else
              msg ("could only write %d of %d bytes to file %s",
-                  written, check, skipcrud + current_file_name);
+                  check, written, skipcrud + current_file_name);
            skip_file ((long) (size - written));
            break;              /* Still do the close, mod time, chmod, etc */
          }
@@ -542,7 +542,7 @@ extract_archive ()
          if (chmod (skipcrud + current_file_name,
                     notumask & (int) hstat.st_mode) < 0)
            {
-             msg_perror ("cannot change mode of file %s to %ld",
+             msg_perror ("cannot change mode of file %s to %lo",
                          skipcrud + current_file_name,
                          notumask & (int) hstat.st_mode);
            }
@@ -634,7 +634,7 @@ extract_archive ()
 
     case LF_DIR:
     case LF_DUMPDIR:
-      namelen = strlen (current_file_name) + skipcrud - 1;
+      namelen = strlen (current_file_name + skipcrud) - 1;
     really_dir:
       /* Check for trailing /, and zap as many as we find. */
       while (namelen
@@ -680,16 +680,53 @@ extract_archive ()
               skipcrud + current_file_name);
        }
 
-      if (f_modified)
-       goto set_filestat;
-      tmp = (struct saved_dir_info *) malloc (sizeof (struct saved_dir_info));
-      tmp->path = malloc (strlen (skipcrud + current_file_name) + 1);
-      strcpy (tmp->path, skipcrud + current_file_name);
-      tmp->mode = hstat.st_mode;
-      tmp->atime = hstat.st_atime;
-      tmp->mtime = hstat.st_mtime;
-      tmp->next = saved_dir_info_head;
-      saved_dir_info_head = tmp;
+      /*
+       * If we are root, set the owner and group of the extracted
+       * file.  This does what is wanted both on real Unix and on
+       * System V.  If we are running as a user, we extract as that
+       * user; if running as root, we extract as the original owner.
+       */
+      if (we_are_root || f_do_chown)
+       {
+         if (chown (skipcrud + current_file_name,
+                    hstat.st_uid, hstat.st_gid) < 0)
+           {
+             msg_perror ("cannot chown file %s to uid %d gid %d",
+                         skipcrud + current_file_name,
+                         hstat.st_uid, hstat.st_gid);
+           }
+       }
+
+      if (!f_modified)
+       {
+         tmp = ((struct saved_dir_info *) 
+                ck_malloc (sizeof (struct saved_dir_info)));
+         tmp->path = (char *) ck_malloc (strlen (skipcrud 
+                                                 + current_file_name) + 1);
+         strcpy (tmp->path, skipcrud + current_file_name);
+         tmp->mode = hstat.st_mode;
+         tmp->atime = hstat.st_atime;
+         tmp->mtime = hstat.st_mtime;
+         tmp->next = saved_dir_info_head;
+         saved_dir_info_head = tmp;
+       }
+      else
+       {
+         /* This functions exactly as the code for set_filestat above. */
+         if ((!f_keep)
+             || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
+           {
+             if (chmod (skipcrud + current_file_name,
+                        notumask & (int) hstat.st_mode) < 0)
+               {
+                 msg_perror ("cannot change mode of file %s to %lo",
+                             skipcrud + current_file_name,
+                             notumask & (int) hstat.st_mode);
+               }
+           }
+       }
+      break;
+
     case LF_VOLHDR:
       if (f_verbose)
        {
@@ -860,7 +897,7 @@ restore_saved_dir_info ()
          if (chmod (saved_dir_info_head->path,
                     notumask & saved_dir_info_head->mode) < 0)
            {
-             msg_perror ("cannot change mode of file %s to %ld",
+             msg_perror ("cannot change mode of file %s to %lo",
                          saved_dir_info_head->path,
                          notumask & saved_dir_info_head->mode);
            }
This page took 0.026038 seconds and 4 git commands to generate.