X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fextract.c;h=84e6a234371f34016a98b1a355e110f22ad903ca;hb=363eb1d48afd94adb4488443dd26bbb3724a2fb6;hp=b717114e3d638f857f84d10fb7943dc19362ea56;hpb=d61947f130d93463249b177fbb8fac5d9ce56c5f;p=chaz%2Ftar diff --git a/src/extract.c b/src/extract.c index b717114..84e6a23 100644 --- a/src/extract.c +++ b/src/extract.c @@ -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); }