/* Extract files from a tar archive.
- Copyright (C) 1988, 92,93,94,96,97,98, 1999 Free Software Foundation, Inc.
+ Copyright 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
#include "system.h"
-#include <time.h>
-time_t time ();
-
#if HAVE_UTIME_H
# include <utime.h>
#else
#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;
void
extr_init (void)
{
- now = time ((time_t *) 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
{
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)
if (incremental_option)
utimbuf.actime = stat_info->st_atime;
else
- utimbuf.actime = now;
+ utimbuf.actime = start_time;
utimbuf.modtime = stat_info->st_mtime;
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
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
{
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);
+ }
}
}
int status;
for (cursor = strchr (file_name, '/');
- cursor != NULL;
+ cursor;
cursor = strchr (cursor + 1, '/'))
{
/* Avoid mkdir of empty string, if leading or double '/'. */
if (status == 0)
{
- /* Fix ownership. */
-
- 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 %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 & MODE_RWX);
did_something = 1;
break;
}
- errno = saved_errno; /* FIXME: errno should be read-only */
+ errno = saved_errno;
return did_something; /* tell them to retry if we made one */
}
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;
*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);
skipcrud = 0;
while (!absolute_names_option && CURRENT_FILE_NAME[0] == '/')
{
- static int warned_once = 0;
+ static int warned_once;
- skipcrud++; /* force relative path */
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("\
-Removing leading `/' from absolute path names in the archive")));
+ WARN ((0, 0, _("Removing leading `/' from archive names")));
}
+ skipcrud++; /* force relative path */
}
/* Take a safety backup of a previously existing file. */
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;
}
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;
#else /* not O_CTG */
if (typeflag == CONTTYPE)
{
- static int conttype_diagnosed = 0;
+ static int conttype_diagnosed;
if (!conttype_diagnosed)
{
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);
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? */
if (written > size)
written = size;
- errno = 0; /* FIXME: errno should be read-only */
+ errno = 0;
sstatus = full_write (fd, data_block->buffer, written);
set_next_block_after ((union block *)
}
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. */
#else
{
- static int warned_once = 0;
+ static int warned_once;
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("\
-Attempting extraction of symbolic links as hard links")));
+ WARN ((0, 0,
+ _("Attempting extraction of symbolic links as hard links")));
}
}
/* Fall through. */
if (stat (CURRENT_FILE_NAME, &st1) == 0 && S_ISDIR (st1.st_mode))
goto check_perms;
- errno = saved_errno; /* FIXME: errno should be read-only */
+ errno = saved_errno;
}
if (maybe_recoverable (CURRENT_FILE_NAME))
}
#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)
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;
break;
case GNUTYPE_MULTIVOL:
- ERROR ((0, 0, _("\
-Cannot extract `%s' -- file is continued from another volume"),
+ ERROR ((0, 0,
+ _("Cannot extract `%s' -- file is continued from another volume"),
current_file_name));
skip_file (current_stat.st_size);
if (backup_option)
{
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;