/* 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
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"
/* FIXME: Just make sure we can add files in directories we create. Maybe
should we later remove permissions we are adding, here? */
- newdir_umask &= ~0300;
+ newdir_umask &= ~ MODE_WXUSR;
}
/*------------------------------------------------------------------.
if (!keep_old_files_option
|| (stat_info->st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
if (chmod (file_name, ~current_umask & stat_info->st_mode) < 0)
- ERROR ((0, errno, _("%s: Cannot change mode to %0.4lo"),
+ ERROR ((0, errno, _("%s: Cannot change mode to %04lo"),
file_name,
(unsigned long) (~current_umask & stat_info->st_mode)));
}
/* 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);
}
}
continue;
*cursor = '\0'; /* truncate the path there */
- status = mkdir (file_name, ~newdir_umask & 0777);
+ status = mkdir (file_name, ~newdir_umask & MODE_RWX);
if (status == 0)
{
(unsigned long) current_stat.st_gid));
print_for_mkdir (file_name, cursor - file_name,
- ~newdir_umask & 0777);
+ ~newdir_umask & MODE_RWX);
did_something = 1;
*cursor = '/';
static void
extract_sparse_file (int fd, off_t *sizeleft, off_t totalsize, char *name)
{
- union block *data_block;
int sparse_ind = 0;
size_t written;
ssize_t count;
- /* FIXME: `data_block' might be used uninitialized in this function.
- Reported by Bruno Haible. */
-
/* assuming sizeleft is initially totalsize */
while (*sizeleft > 0)
{
- data_block = find_next_block ();
+ union block *data_block = find_next_block ();
if (data_block == NULL)
{
ERROR ((0, 0, _("Unexpected EOF on archive file")));
return;
}
- lseek (fd, sparsearray[sparse_ind].offset, 0);
+ if (lseek (fd, sparsearray[sparse_ind].offset, SEEK_SET) < 0)
+ {
+ char buf[UINTMAX_STRSIZE_BOUND];
+ ERROR ((0, errno, _("%s: lseek error at byte %s"),
+ STRINGIFY_BIGINT (sparsearray[sparse_ind].offset, buf),
+ name));
+ return;
+ }
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;
data_block = find_next_block ();
}
- count = write (fd, data_block->buffer, written);
+ count = full_write (fd, data_block->buffer, written);
if (count < 0)
ERROR ((0, errno, _("%s: Could not write to file"), name));
*sizeleft -= count;
set_next_block_after (data_block);
}
+
free (sparsearray);
- set_next_block_after (data_block);
}
/*----------------------------------.
off_t size;
int skipcrud;
int counter;
+ char typeflag;
#if 0
int sparse_ind = 0;
#endif
/* 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
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;
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
/* 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;
}
extract_file:
- if (current_header->header.typeflag == GNUTYPE_SPARSE)
+ if (typeflag == GNUTYPE_SPARSE)
{
char *name;
size_t name_length_bis;
break; /* FIXME: What happens, then? */
}
- /* If the file is sparse, use the sparsearray that we created
- before to lseek into the new file the proper amount, and to
- see how many bytes we want to write at that position. */
-
-#if 0
- if (current_header->header.typeflag == GNUTYPE_SPARSE)
- {
- lseek (fd, sparsearray[sparse_ind].offset, 0);
- written = sparsearray[sparse_ind++].numbytes;
- }
- else
-#endif
- written = available_space_after (data_block);
+ written = available_space_after (data_block);
if (written > size)
written = size;
errno = 0; /* FIXME: errno should be read-only */
- sstatus = write (fd, data_block->buffer, written);
+ sstatus = full_write (fd, data_block->buffer, written);
set_next_block_after ((union block *)
(data_block->buffer + written - 1));
if (to_stdout_option)
break;
-#if 0
- if (current_header->header.isextended)
- {
- union block *exhdr;
- int counter;
-
- for (counter = 0; counter < 21; counter++)
- {
- off_t offset;
-
- if (!exhdr->sparse_header.sp[counter].numbytes)
- break;
- offset = OFF_FROM_OCT (exhdr->sparse_header.sp[counter].offset);
- written
- = SIZE_FROM_OCT (exhdr->sparse_header.sp[counter].numbytes);
- lseek (fd, offset, 0);
- sstatus = write (fd, data_block->buffer, written);
- if (sstatus == written)
- continue;
- }
- }
-#endif
status = close (fd);
if (status < 0)
{
gnu_restore (skipcrud);
}
- else if (current_header->header.typeflag == GNUTYPE_DUMPDIR)
+ else if (typeflag == GNUTYPE_DUMPDIR)
skip_file (current_stat.st_size);
if (to_stdout_option)
again_dir:
status = mkdir (CURRENT_FILE_NAME,
- (we_are_root ? 0 : 0300) | current_stat.st_mode);
+ ((we_are_root ? 0 : MODE_WXUSR)
+ | current_stat.st_mode));
if (status != 0)
{
/* If the directory creation fails, let's consider immediately the
}
check_perms:
- if (!we_are_root && 0300 != (0300 & current_stat.st_mode))
+ if (!we_are_root && MODE_WXUSR != (MODE_WXUSR & current_stat.st_mode))
{
- current_stat.st_mode |= 0300;
+ current_stat.st_mode |= MODE_WXUSR;
WARN ((0, 0, _("Added write and execute permission to directory %s"),
CURRENT_FILE_NAME));
}
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;
}