summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/tar/extract.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/tar/extract.c')
-rw-r--r--gnu/usr.bin/tar/extract.c946
1 files changed, 0 insertions, 946 deletions
diff --git a/gnu/usr.bin/tar/extract.c b/gnu/usr.bin/tar/extract.c
deleted file mode 100644
index faf25ad..0000000
--- a/gnu/usr.bin/tar/extract.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/* Extract files from a tar archive.
- Copyright (C) 1988, 1992, 1993 Free Software Foundation
-
-This file is part of GNU Tar.
-
-GNU Tar is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Tar is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Tar; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/*
- * Extract files from a tar archive.
- *
- * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
- */
-
-#include <stdio.h>
-#include <errno.h>
-#ifndef STDC_HEADERS
-extern int errno;
-#endif
-#include <sys/types.h>
-#include <time.h>
-time_t time ();
-
-#ifdef BSD42
-#include <sys/file.h>
-#else
-#ifndef V7
-#include <fcntl.h>
-#endif
-#endif
-
-#ifdef NO_OPEN3
-/* We need the #define's even though we don't use them. */
-#include "open3.h"
-#endif
-
-#ifdef EMUL_OPEN3
-/* Simulated 3-argument open for systems that don't have it */
-#include "open3.h"
-#endif
-
-#include "tar.h"
-#include "port.h"
-
-#if defined(_POSIX_VERSION)
-#include <utime.h>
-#else
-struct utimbuf
-{
- long actime;
- long modtime;
-};
-
-#endif
-
-extern FILE *msg_file;
-
-extern union record *head; /* Points to current tape header */
-extern struct stat hstat; /* Stat struct corresponding */
-extern int head_standard; /* Tape header is in ANSI format */
-
-extern char *save_name;
-extern long save_totsize;
-extern long save_sizeleft;
-
-int confirm ();
-void decode_header ();
-void extract_mangle ();
-void extract_sparse_file ();
-long from_oct ();
-void gnu_restore ();
-extern void print_header ();
-extern void skip_file ();
-extern void skip_extended_headers ();
-extern void pr_mkdir ();
-void saverec ();
-
-int make_dirs (); /* Makes required directories */
-
-static time_t now = 0; /* Current time */
-static we_are_root = 0; /* True if our effective uid == 0 */
-static int notumask = ~0; /* Masks out bits user doesn't want */
-
-/*
- * "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;*/
-
-struct saved_dir_info
-{
- char *path;
- int mode;
- int atime;
- int mtime;
- struct saved_dir_info *next;
-};
-
-struct saved_dir_info *saved_dir_info_head;
-
-/*
- * Set up to extract files.
- */
-void
-extr_init ()
-{
- int ourmask;
-
- now = time ((time_t *) 0);
- if (geteuid () == 0)
- we_are_root = 1;
-
- /*
- * We need to know our umask. But if f_use_protection is set,
- * leave our kernel umask at 0, and our "notumask" at ~0.
- */
- ourmask = umask (0); /* Read it */
- if (!f_use_protection)
- {
- (void) umask (ourmask); /* Set it back how it was */
- notumask = ~ourmask; /* Make umask override permissions */
- }
-}
-
-
-/*
- * Extract a file from the archive.
- */
-void
-extract_archive ()
-{
- register char *data;
- int fd, check, namelen, written, openflag;
- long size;
- struct utimbuf acc_upd_times;
- register int skipcrud;
- register int i;
- /* int sparse_ind = 0;*/
- union record *exhdr;
- struct saved_dir_info *tmp;
- /* int end_nulls; */
-
- saverec (&head); /* Make sure it sticks around */
- userec (head); /* And go past it in the archive */
- decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
-
- if ((f_confirm && !confirm ("extract", current_file_name)) ||
- (f_exstdout && head->header.linkflag != LF_OLDNORMAL &&
- head->header.linkflag != LF_NORMAL &&
- head->header.linkflag != LF_CONTIG))
- {
- if (head->header.isextended)
- skip_extended_headers ();
- skip_file ((long) hstat.st_size);
- saverec ((union record **) 0);
- return;
- }
-
- /* Print the record from 'head' and 'hstat' */
- if (f_verbose)
- print_header ();
-
- /*
- * Check for fully specified pathnames and other atrocities.
- *
- * Note, we can't just make a pointer to the new file name,
- * since saverec() might move the header and adjust "head".
- * We have to start from "head" every time we want to touch
- * the header record.
- */
- skipcrud = 0;
- while (!f_absolute_paths
- && '/' == current_file_name[skipcrud])
- {
- static int warned_once = 0;
-
- skipcrud++; /* Force relative path */
- if (!warned_once++)
- {
- msg ("Removing leading / from absolute path names in the archive.");
- }
- }
-
- switch (head->header.linkflag)
- {
-
- default:
- msg ("Unknown file type '%c' for %s, extracted as normal file",
- head->header.linkflag, skipcrud + current_file_name);
- /* FALL THRU */
-
- /*
- * 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 translate the character strings representing 1) the offset
- * at which to write and 2) how many bytes to write into numbers,
- * which we store into the scratch array, "sparsearray". This
- * array makes our life easier the same way it did in creating
- * the tar file that had to deal with a sparse file.
- *
- * After we read in the first five (at most) sparse structures,
- * we check to see if the file has an extended header, i.e.,
- * if more sparse structures are needed to describe the contents
- * of the new file. If so, we read in the extended headers
- * and continue to store their contents into the sparsearray.
- */
- case LF_SPARSE:
- sp_array_size = 10;
- sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
- for (i = 0; i < SPARSE_IN_HDR; i++)
- {
- sparsearray[i].offset =
- from_oct (1 + 12, head->header.sp[i].offset);
- sparsearray[i].numbytes =
- from_oct (1 + 12, head->header.sp[i].numbytes);
- if (!sparsearray[i].numbytes)
- break;
- }
-
- /* end_nulls = from_oct(1+12, head->header.ending_blanks);*/
-
- if (head->header.isextended)
- {
- /* read in the list of extended headers
- and translate them into the sparsearray
- as before */
-
- /* static */ int ind = SPARSE_IN_HDR;
-
- for (;;)
- {
-
- exhdr = findrec ();
- for (i = 0; i < SPARSE_EXT_HDR; i++)
- {
-
- if (i + ind > sp_array_size - 1)
- {
- /*
- * realloc the scratch area
- * since we've run out of room --
- */
- sparsearray = (struct sp_array *)
- ck_realloc (sparsearray,
- 2 * sp_array_size * (sizeof (struct sp_array)));
- sp_array_size *= 2;
- }
- if (!exhdr->ext_hdr.sp[i].numbytes)
- break;
- sparsearray[i + ind].offset =
- from_oct (1 + 12, exhdr->ext_hdr.sp[i].offset);
- sparsearray[i + ind].numbytes =
- from_oct (1 + 12, exhdr->ext_hdr.sp[i].numbytes);
- }
- if (!exhdr->ext_hdr.isextended)
- break;
- else
- {
- ind += SPARSE_EXT_HDR;
- userec (exhdr);
- }
- }
- userec (exhdr);
- }
-
- /* FALL THRU */
- case LF_OLDNORMAL:
- case LF_NORMAL:
- case LF_CONTIG:
- /*
- * Appears to be a file.
- * See if it's really a directory.
- */
- namelen = strlen (skipcrud + current_file_name) - 1;
- if (current_file_name[skipcrud + namelen] == '/')
- goto really_dir;
-
- /* FIXME, deal with protection issues */
- again_file:
- openflag = (f_keep ?
- O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_EXCL :
- O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_TRUNC)
- | ((head->header.linkflag == LF_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 is opened
- * with O_APPEND, it writes to the last place
- * that something was written, thereby ignoring
- * any lseeks that we have done. We add this
- * extra condition to make it able to lseek when
- * a file is sparse, i.e., we don't open the new
- * file with this flag. (Grump -- this bug caused
- * me to waste a good deal of time, I might add)
- */
-
- if (f_exstdout)
- {
- fd = 1;
- goto extract_file;
- }
-
- if (f_unlink && !f_keep) {
- if (unlink(skipcrud + current_file_name) == -1)
- if (errno != ENOENT)
- msg_perror ("Could not unlink %s",
- skipcrud + current_file_name);
- }
-
-#ifdef O_CTG
- /*
- * Contiguous files (on the Masscomp) have to specify
- * the size in the open call that creates them.
- */
- if (head->header.linkflag == LF_CONTIG)
- fd = open ((longname ? longname : head->header.name)
- + skipcrud,
- openflag | O_CTG,
- hstat.st_mode, hstat.st_size);
- else
-#endif
- {
-#ifdef NO_OPEN3
- /*
- * On raw V7 we won't let them specify -k (f_keep), but
- * we just bull ahead and create the files.
- */
- fd = creat ((longname
- ? longname
- : head->header.name) + skipcrud,
- hstat.st_mode);
-#else
- /*
- * With 3-arg open(), we can do this up right.
- */
- fd = open (skipcrud + current_file_name,
- openflag, hstat.st_mode);
-#endif
- }
-
- if (fd < 0)
- {
- if (make_dirs (skipcrud + current_file_name))
- goto again_file;
- msg_perror ("Could not create file %s",
- skipcrud + current_file_name);
- if (head->header.isextended)
- skip_extended_headers ();
- skip_file ((long) hstat.st_size);
- goto quit;
- }
-
- extract_file:
- if (head->header.linkflag == LF_SPARSE)
- {
- char *name;
- int namelen;
-
- /*
- * Kludge alert. NAME is assigned to header.name
- * because during the extraction, the space that
- * contains the header will get scribbled on, and
- * the name will get munged, so any error messages
- * that happen to contain the filename will look
- * REAL interesting unless we do this.
- */
- 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);
- }
- else
- for (size = hstat.st_size;
- size > 0;
- size -= written)
- {
-
- /* long offset,
- numbytes;*/
-
- if (f_multivol)
- {
- save_name = current_file_name;
- save_totsize = hstat.st_size;
- save_sizeleft = size;
- }
-
- /*
- * Locate data, determine max length
- * writeable, write it, record that
- * we have used the data, then check
- * if the write worked.
- */
- data = findrec ()->charptr;
- if (data == NULL)
- { /* Check it... */
- msg ("Unexpected EOF on archive file");
- break;
- }
- /*
- * JK - 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 (head->header.linkflag == LF_SPARSE) {
- off_t pos;
-
- pos = lseek(fd, (off_t) sparsearray[sparse_ind].offset, 0);
- printf("%d at %d\n", (int) pos, sparse_ind);
- written = sparsearray[sparse_ind++].numbytes;
- } else*/
- written = endofrecs ()->charptr - data;
- if (written > size)
- written = size;
- errno = 0;
- check = write (fd, data, written);
- /*
- * The following is in violation of strict
- * typing, since the arg to userec
- * should be a struct rec *. FIXME.
- */
- userec ((union record *) (data + written - 1));
- if (check == written)
- continue;
- /*
- * Error in writing to file.
- * Print it, skip to next file in archive.
- */
- if (check < 0)
- msg_perror ("couldn't write to file %s",
- skipcrud + current_file_name);
- else
- msg ("could only write %d of %d bytes to file %s",
- check, written, skipcrud + current_file_name);
- skip_file ((long) (size - written));
- break; /* Still do the close, mod time, chmod, etc */
- }
-
- if (f_multivol)
- 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 */
- if (f_exstdout)
- break;
-
- /* if (head->header.isextended) {
- register union record *exhdr;
- register int i;
-
- for (i = 0; i < 21; i++) {
- long offset;
-
- if (!exhdr->ext_hdr.sp[i].numbytes)
- break;
- offset = from_oct(1+12,
- exhdr->ext_hdr.sp[i].offset);
- written = from_oct(1+12,
- exhdr->ext_hdr.sp[i].numbytes);
- lseek(fd, offset, 0);
- check = write(fd, data, written);
- if (check == written) continue;
-
- }
-
-
- }*/
- check = close (fd);
- if (check < 0)
- {
- msg_perror ("Error while closing %s",
- skipcrud + current_file_name);
- }
-
-
- set_filestat:
-
- /*
- * 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);
- }
- }
-
- /*
- * Set the modified time of the file.
- *
- * Note that we set the accessed time to "now", which
- * is really "the time we started extracting files".
- * unless f_gnudump is used, in which case .st_atime is used
- */
- if (!f_modified)
- {
- /* fixme if f_gnudump should set ctime too, but how? */
- if (f_gnudump)
- acc_upd_times.actime = hstat.st_atime;
- else
- acc_upd_times.actime = now; /* Accessed now */
- acc_upd_times.modtime = hstat.st_mtime; /* Mod'd */
- if (utime (skipcrud + current_file_name,
- &acc_upd_times) < 0)
- {
- msg_perror ("couldn't change access and modification times of %s", skipcrud + current_file_name);
- }
- }
- /* We do the utime before the chmod because some versions of
- utime are broken and trash the modes of the file. Since
- we then change the mode anyway, we don't care. . . */
-
- /*
- * If '-k' is not set, open() or creat() could have saved
- * the permission bits from a previously created file,
- * ignoring the ones we specified.
- * Even if -k is set, if the file has abnormal
- * mode bits, we must chmod since writing or chown() has
- * probably reset them.
- *
- * If -k is set, we know *we* created this file, so the mode
- * bits were set by our open(). If the file is "normal", we
- * skip the chmod. This works because we did umask(0) if -p
- * is set, so umask will have left the specified mode alone.
- */
- 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 0%o",
- skipcrud + current_file_name,
- notumask & (int) hstat.st_mode);
- }
- }
-
- quit:
- break;
-
- case LF_LINK:
- again_link:
- {
- struct stat st1, st2;
-
- if (f_unlink && !f_keep) {
- if (unlink(skipcrud + current_file_name) == -1)
- if (errno != ENOENT)
- msg_perror ("Could not unlink %s",
- skipcrud + current_file_name);
- }
-
- check = link (current_link_name, skipcrud + current_file_name);
-
- if (check == 0)
- break;
- if (make_dirs (skipcrud + current_file_name))
- goto again_link;
- if (f_gnudump && errno == EEXIST)
- break;
- if (stat (current_link_name, &st1) == 0
- && stat (current_file_name + skipcrud, &st2) == 0
- && st1.st_dev == st2.st_dev
- && st1.st_ino == st2.st_ino)
- break;
- msg_perror ("Could not link %s to %s",
- skipcrud + current_file_name,
- current_link_name);
- }
- break;
-
-#ifdef S_ISLNK
- case LF_SYMLINK:
- again_symlink:
- if (f_unlink && !f_keep) {
- if (unlink(skipcrud + current_file_name) == -1)
- if (errno != ENOENT)
- msg_perror ("Could not unlink %s",
- skipcrud + current_file_name);
- }
-
- check = symlink (current_link_name,
- skipcrud + current_file_name);
- /* FIXME, don't worry uid, gid, etc... */
- if (check == 0)
- break;
- if (make_dirs (current_file_name + skipcrud))
- goto again_symlink;
- msg_perror ("Could not create symlink to %s",
- current_link_name);
- break;
-#endif
-
-#ifdef S_IFCHR
- case LF_CHR:
- hstat.st_mode |= S_IFCHR;
- goto make_node;
-#endif
-
-#ifdef S_IFBLK
- case LF_BLK:
- hstat.st_mode |= S_IFBLK;
-#endif
-#if defined(S_IFCHR) || defined(S_IFBLK)
- make_node:
- if (f_unlink && !f_keep) {
- if (unlink(skipcrud + current_file_name) == -1)
- if (errno != ENOENT)
- msg_perror ("Could not unlink %s",
- skipcrud + current_file_name);
- }
-
- check = mknod (current_file_name + skipcrud,
- (int) hstat.st_mode, (int) hstat.st_rdev);
- if (check != 0)
- {
- if (make_dirs (skipcrud + current_file_name))
- goto make_node;
- msg_perror ("Could not make %s",
- current_file_name + skipcrud);
- break;
- };
- goto set_filestat;
-#endif
-
-#ifdef S_ISFIFO
- /* If local system doesn't support FIFOs, use default case */
- case LF_FIFO:
- make_fifo:
- if (f_unlink && !f_keep) {
- if (unlink(skipcrud + current_file_name) == -1)
- if (errno != ENOENT)
- msg_perror ("Could not unlink %s",
- skipcrud + current_file_name);
- }
-
- check = mkfifo (current_file_name + skipcrud,
- (int) hstat.st_mode);
- if (check != 0)
- {
- if (make_dirs (current_file_name + skipcrud))
- goto make_fifo;
- msg_perror ("Could not make %s",
- skipcrud + current_file_name);
- break;
- };
- goto set_filestat;
-#endif
-
- case LF_DIR:
- case LF_DUMPDIR:
- namelen = strlen (current_file_name + skipcrud) - 1;
- really_dir:
- /* Check for trailing /, and zap as many as we find. */
- while (namelen
- && current_file_name[skipcrud + namelen] == '/')
- current_file_name[skipcrud + namelen--] = '\0';
- if (f_gnudump)
- { /* Read the entry and delete files
- that aren't listed in the archive */
- gnu_restore (skipcrud);
-
- }
- else if (head->header.linkflag == LF_DUMPDIR)
- skip_file ((long) (hstat.st_size));
-
-
- again_dir:
- check = mkdir (skipcrud + current_file_name,
- (we_are_root ? 0 : 0300) | (int) hstat.st_mode);
- if (check != 0)
- {
- struct stat st1;
-
- if (make_dirs (skipcrud + current_file_name))
- goto again_dir;
- /* If we're trying to create '.', let it be. */
- if (current_file_name[skipcrud + namelen] == '.' &&
- (namelen == 0 ||
- current_file_name[skipcrud + namelen - 1] == '/'))
- goto check_perms;
- if (errno == EEXIST
- && stat (skipcrud + current_file_name, &st1) == 0
- && (S_ISDIR (st1.st_mode)))
- break;
- msg_perror ("Could not create directory %s", skipcrud + current_file_name);
- break;
- }
-
- check_perms:
- if (!we_are_root && 0300 != (0300 & (int) hstat.st_mode))
- {
- hstat.st_mode |= 0300;
- msg ("Added write and execute permission to directory %s",
- skipcrud + current_file_name);
- }
-
- /*
- * 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 0%o",
- skipcrud + current_file_name,
- notumask & (int) hstat.st_mode);
- }
- }
- }
- break;
-
- case LF_VOLHDR:
- if (f_verbose)
- {
- printf ("Reading %s\n", current_file_name);
- }
- break;
-
- case LF_NAMES:
- extract_mangle (head);
- break;
-
- case LF_MULTIVOL:
- msg ("Can't extract '%s'--file is continued from another volume\n", current_file_name);
- skip_file ((long) hstat.st_size);
- break;
-
- case LF_LONGNAME:
- case LF_LONGLINK:
- msg ("Visible long name error\n");
- skip_file ((long) hstat.st_size);
- break;
- }
-
- /* We don't need to save it any longer. */
- saverec ((union record **) 0);/* Unsave it */
-}
-
-/*
- * After a file/link/symlink/dir creation has failed, see if
- * it's because some required directory was not present, and if
- * so, create all required dirs.
- */
-int
-make_dirs (pathname)
- char *pathname;
-{
- char *p; /* Points into path */
- int madeone = 0; /* Did we do anything yet? */
- int save_errno = errno; /* Remember caller's errno */
- int check;
-
- if (errno != ENOENT)
- return 0; /* Not our problem */
-
- for (p = index (pathname, '/'); p != NULL; p = index (p + 1, '/'))
- {
- /* Avoid mkdir of empty string, if leading or double '/' */
- if (p == pathname || p[-1] == '/')
- continue;
- /* Avoid mkdir where last part of path is '.' */
- if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
- continue;
- *p = 0; /* Truncate the path there */
- check = mkdir (pathname, 0777); /* Try to create it as a dir */
- if (check == 0)
- {
- /* Fix ownership */
- if (we_are_root)
- {
- if (chown (pathname, hstat.st_uid,
- hstat.st_gid) < 0)
- {
- msg_perror ("cannot change owner of %s to uid %d gid %d", pathname, hstat.st_uid, hstat.st_gid);
- }
- }
- pr_mkdir (pathname, p - pathname, notumask & 0777);
- madeone++; /* Remember if we made one */
- *p = '/';
- continue;
- }
- *p = '/';
- if (errno == EEXIST) /* Directory already exists */
- continue;
- /*
- * Some other error in the mkdir. We return to the caller.
- */
- break;
- }
-
- errno = save_errno; /* Restore caller's errno */
- return madeone; /* Tell them to retry if we made one */
-}
-
-void
-extract_sparse_file (fd, sizeleft, totalsize, name)
- int fd;
- long *sizeleft, totalsize;
- char *name;
-{
- /* register char *data;*/
- union record *datarec;
- int sparse_ind = 0;
- int written, count;
-
- /* assuming sizeleft is initially totalsize */
-
-
- while (*sizeleft > 0)
- {
- datarec = findrec ();
- if (datarec == NULL)
- {
- msg ("Unexpected EOF on archive file");
- return;
- }
- lseek (fd, sparsearray[sparse_ind].offset, 0);
- written = sparsearray[sparse_ind++].numbytes;
- while (written > RECORDSIZE)
- {
- count = write (fd, datarec->charptr, RECORDSIZE);
- if (count < 0)
- msg_perror ("couldn't write to file %s", name);
- written -= count;
- *sizeleft -= count;
- userec (datarec);
- datarec = findrec ();
- }
-
- count = write (fd, datarec->charptr, written);
-
- if (count < 0)
- {
- msg_perror ("couldn't write to file %s", name);
- }
- else if (count != written)
- {
- msg ("could only write %d of %d bytes to file %s", count,
- totalsize, name);
- skip_file ((long) (*sizeleft));
- }
-
- written -= count;
- *sizeleft -= count;
- userec (datarec);
- }
- free (sparsearray);
- /* if (end_nulls) {
- register int i;
-
- printf("%d\n", (int) end_nulls);
- for (i = 0; i < end_nulls; i++)
- write(fd, "\000", 1);
- }*/
- userec (datarec);
-}
-
-/* Set back the utime and mode for all the extracted directories. */
-void
-restore_saved_dir_info ()
-{
- struct utimbuf acc_upd_times;
-
- while (saved_dir_info_head != NULL)
- {
- /* fixme if f_gnudump should set ctime too, but how? */
- if (f_gnudump)
- acc_upd_times.actime = saved_dir_info_head->atime;
- else
- acc_upd_times.actime = now; /* Accessed now */
- acc_upd_times.modtime = saved_dir_info_head->mtime; /* Mod'd */
- if (utime (saved_dir_info_head->path, &acc_upd_times) < 0)
- {
- msg_perror ("couldn't change access and modification times of %s",
- saved_dir_info_head->path);
- }
- if ((!f_keep) || (saved_dir_info_head->mode & (S_ISUID | S_ISGID | S_ISVTX)))
- {
- if (chmod (saved_dir_info_head->path,
- notumask & saved_dir_info_head->mode) < 0)
- {
- msg_perror ("cannot change mode of file %s to 0%o",
- saved_dir_info_head->path,
- notumask & saved_dir_info_head->mode);
- }
- }
- saved_dir_info_head = saved_dir_info_head->next;
- }
-}
OpenPOWER on IntegriCloud