X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fextract.c;h=0aba5e7fa0af2ecf7d812332196a54fc875d0efe;hb=3495d84e27c42c0619daf43c2b546d35e3ecbba6;hp=e761da5c884fbd8bfd90382f226092ad25c775d3;hpb=5e0e027651e89233d4f3c4ca089db72468e31173;p=chaz%2Ftar diff --git a/src/extract.c b/src/extract.c index e761da5..0aba5e7 100644 --- a/src/extract.c +++ b/src/extract.c @@ -18,11 +18,6 @@ #include "system.h" -#include -#ifndef time -time_t time (); -#endif - #if HAVE_UTIME_H # include #else @@ -35,20 +30,10 @@ struct utimbuf #include "common.h" -static time_t now; /* current time */ static int we_are_root; /* true if our effective uid == 0 */ 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 - writing the info into the header or extended header. */ -struct sp_array *sparsearray; - -/* Number of elts storable in the sparsearray. */ -int sp_array_size = 10; -#endif - struct delayed_set_stat { struct delayed_set_stat *next; @@ -65,15 +50,16 @@ static struct delayed_set_stat *delayed_set_stat_head; void extr_init (void) { - now = time (0); we_are_root = geteuid () == 0; + same_permissions_option += we_are_root; + same_owner_option += we_are_root; /* Option -p clears the kernel umask, so it does not affect proper restoration of file permissions. New intermediate directories will comply with umask at start of program. */ newdir_umask = umask (0); - if (same_permissions_option) + if (0 < same_permissions_option) current_umask = 0; else { @@ -105,7 +91,7 @@ set_mode (char *file_name, struct stat *stat_info) normal, we merely skip the chmod. This works because we did umask (0) when -p, so umask will have left the specified mode alone. */ - if ((we_are_root || same_permissions_option) + if (0 < same_permissions_option && ((!keep_old_files_option && !unlink_first_option) || (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX)))) if (chmod (file_name, ~current_umask & stat_info->st_mode) < 0) @@ -146,7 +132,7 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag) if (incremental_option) utimbuf.actime = stat_info->st_atime; else - utimbuf.actime = now; + utimbuf.actime = start_time; utimbuf.modtime = stat_info->st_mtime; @@ -167,10 +153,8 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag) extract as the original owner. Or else, if we are running as a user, leave the owner and group as they are, so we extract as that user. */ - if (we_are_root || same_owner_option) + if (0 < same_owner_option) { -#if HAVE_LCHOWN - /* When lchown exists, it should be used to change the attributes of the symbolic link itself. In this case, a mere chown would change the attributes of the file the symbolic link is pointing to, and @@ -178,11 +162,13 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag) if (symlink_flag) { +#if HAVE_LCHOWN if (lchown (file_name, stat_info->st_uid, stat_info->st_gid) < 0) 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)); +#endif } else { @@ -191,28 +177,13 @@ set_stat (char *file_name, struct stat *stat_info, int symlink_flag) file_name, (unsigned long) stat_info->st_uid, (unsigned long) stat_info->st_gid)); - } -#else /* not HAVE_LCHOWN */ - - if (!symlink_flag) - - if (chown (file_name, stat_info->st_uid, stat_info->st_gid) < 0) - 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 */ - - if (!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 let's attempt setting these bits once more. */ - - if (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX)) - set_mode (file_name, stat_info); + /* 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 let's attempt setting these bits once more. */ + if (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX)) + set_mode (file_name, stat_info); + } } } @@ -231,7 +202,7 @@ make_directories (char *file_name) int status; for (cursor = strchr (file_name, '/'); - cursor != NULL; + cursor; cursor = strchr (cursor + 1, '/')) { /* Avoid mkdir of empty string, if leading or double '/'. */ @@ -344,7 +315,7 @@ extract_sparse_file (int fd, off_t *sizeleft, off_t totalsize, char *name) while (*sizeleft > 0) { union block *data_block = find_next_block (); - if (data_block == NULL) + if (! data_block) { ERROR ((0, 0, _("Unexpected EOF on archive file"))); return; @@ -367,6 +338,11 @@ extract_sparse_file (int fd, off_t *sizeleft, off_t totalsize, char *name) *sizeleft -= count; set_next_block_after (data_block); data_block = find_next_block (); + if (! data_block) + { + ERROR ((0, 0, _("Unexpected EOF on archive file"))); + return; + } } count = full_write (fd, data_block->buffer, written); @@ -483,15 +459,14 @@ extract_archive (void) case GNUTYPE_SPARSE: sp_array_size = 10; - sparsearray = (struct sp_array *) + sparsearray = xmalloc (sp_array_size * sizeof (struct sp_array)); for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++) { - sparsearray[counter].offset = - OFF_FROM_CHARS (current_header->oldgnu_header.sp[counter].offset); - sparsearray[counter].numbytes = - SIZE_FROM_CHARS (current_header->oldgnu_header.sp[counter].numbytes); + struct sparse const *s = ¤t_header->oldgnu_header.sp[counter]; + sparsearray[counter].offset = OFF_FROM_HEADER (s->offset); + sparsearray[counter].numbytes = SIZE_FROM_HEADER (s->numbytes); if (!sparsearray[counter].numbytes) break; } @@ -507,26 +482,30 @@ extract_archive (void) while (1) { exhdr = find_next_block (); + if (! exhdr) + { + ERROR ((0, 0, _("Unexpected EOF on archive file"))); + return; + } for (counter = 0; counter < SPARSES_IN_SPARSE_HEADER; counter++) { + struct sparse const *s = &exhdr->sparse_header.sp[counter]; if (counter + ind > sp_array_size - 1) { /* Realloc the scratch area since we've run out of room. */ sp_array_size *= 2; - sparsearray = (struct sp_array *) + sparsearray = xrealloc (sparsearray, - sp_array_size * (sizeof (struct sp_array))); + sp_array_size * sizeof (struct sp_array)); } - /* Compare to 0, or use !(int)..., for Pyramid's dumb - compiler. */ - if (exhdr->sparse_header.sp[counter].numbytes == 0) + if (s->numbytes[0] == 0) break; sparsearray[counter + ind].offset = - OFF_FROM_CHARS (exhdr->sparse_header.sp[counter].offset); + OFF_FROM_HEADER (s->offset); sparsearray[counter + ind].numbytes = - SIZE_FROM_CHARS (exhdr->sparse_header.sp[counter].numbytes); + SIZE_FROM_HEADER (s->numbytes); } if (!exhdr->sparse_header.isextended) break; @@ -597,7 +576,7 @@ extract_archive (void) #else /* not O_CTG */ if (typeflag == CONTTYPE) { - static int conttype_diagnosed = 0; + static int conttype_diagnosed; if (!conttype_diagnosed) { @@ -637,7 +616,7 @@ extract_archive (void) REAL interesting unless we do this. */ name_length_bis = strlen (CURRENT_FILE_NAME) + 1; - name = (char *) xmalloc (name_length_bis); + name = 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); @@ -659,7 +638,7 @@ extract_archive (void) worked. */ data_block = find_next_block (); - if (data_block == NULL) + if (! data_block) { ERROR ((0, 0, _("Unexpected EOF on archive file"))); break; /* FIXME: What happens, then? */ @@ -693,7 +672,7 @@ extract_archive (void) } if (multi_volume_option) - assign_string (&save_name, NULL); + assign_string (&save_name, 0); /* 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. */ @@ -745,7 +724,7 @@ extract_archive (void) #else { - static int warned_once = 0; + static int warned_once; if (!warned_once) { @@ -938,7 +917,7 @@ extract_archive (void) } #if !MSDOS - /* MSDOS does not associate timestamps with directories. In this + /* MSDOS does not associate time stamps with directories. In this case, no need to try delaying their restoration. */ if (touch_option) @@ -951,8 +930,7 @@ extract_archive (void) else { - data = ((struct delayed_set_stat *) - xmalloc (sizeof (struct delayed_set_stat))); + data = xmalloc (sizeof (struct delayed_set_stat)); data->file_name = xstrdup (CURRENT_FILE_NAME); data->stat_info = current_stat; data->next = delayed_set_stat_head; @@ -1006,7 +984,7 @@ apply_delayed_set_stat (void) { struct delayed_set_stat *data; - while (delayed_set_stat_head != NULL) + while (delayed_set_stat_head) { data = delayed_set_stat_head; delayed_set_stat_head = delayed_set_stat_head->next;