]>
Dogcows Code - chaz/tar/blob - src/extract.c
1 /* Extract files from a tar archive.
2 Copyright (C) 1988, 1992 Free Software Foundation
4 This file is part of GNU Tar.
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 * Extract files from a tar archive.
23 * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
31 #include <sys/types.h>
44 /* We need the #define's even though we don't use them. */
49 /* Simulated 3-argument open for systems that don't have it */
56 #if defined(_POSIX_VERSION)
67 extern FILE *msg_file
;
69 extern union record
*head
; /* Points to current tape header */
70 extern struct stat hstat
; /* Stat struct corresponding */
71 extern int head_standard
; /* Tape header is in ANSI format */
73 extern char *save_name
;
74 extern long save_totsize
;
75 extern long save_sizeleft
;
78 void decode_header ();
79 void extract_mangle ();
80 void extract_sparse_file ();
83 extern void print_header ();
84 extern void skip_file ();
85 extern void skip_extended_headers ();
86 extern void pr_mkdir ();
89 int make_dirs (); /* Makes required directories */
91 static time_t now
= 0; /* Current time */
92 static we_are_root
= 0; /* True if our effective uid == 0 */
93 static int notumask
= ~0; /* Masks out bits user doesn't want */
96 * "Scratch" space to store the information about a sparse file before
97 * writing the info into the header or extended header
99 /*struct sp_array *sparsearray;*/
101 /* number of elts storable in the sparsearray */
102 /*int sp_array_size = 10;*/
104 struct saved_dir_info
110 struct saved_dir_info
*next
;
113 struct saved_dir_info
*saved_dir_info_head
;
116 * Set up to extract files.
123 now
= time ((time_t *) 0);
128 * We need to know our umask. But if f_use_protection is set,
129 * leave our kernel umask at 0, and our "notumask" at ~0.
131 ourmask
= umask (0); /* Read it */
132 if (!f_use_protection
)
134 (void) umask (ourmask
); /* Set it back how it was */
135 notumask
= ~ourmask
; /* Make umask override permissions */
141 * Extract a file from the archive.
147 int fd
, check
, namelen
, written
, openflag
;
149 struct utimbuf acc_upd_times
;
150 register int skipcrud
;
152 /* int sparse_ind = 0;*/
154 struct saved_dir_info
*tmp
;
159 saverec (&head
); /* Make sure it sticks around */
160 userec (head
); /* And go past it in the archive */
161 decode_header (head
, &hstat
, &head_standard
, 1); /* Snarf fields */
163 if (f_confirm
&& !confirm ("extract", current_file_name
))
165 if (head
->header
.isextended
)
166 skip_extended_headers ();
167 skip_file ((long) hstat
.st_size
);
168 saverec ((union record
**) 0);
172 /* Print the record from 'head' and 'hstat' */
177 * Check for fully specified pathnames and other atrocities.
179 * Note, we can't just make a pointer to the new file name,
180 * since saverec() might move the header and adjust "head".
181 * We have to start from "head" every time we want to touch
185 while (!f_absolute_paths
186 && '/' == current_file_name
[skipcrud
])
188 static int warned_once
= 0;
190 skipcrud
++; /* Force relative path */
193 msg ("Removing leading / from absolute path names in the archive.");
197 switch (head
->header
.linkflag
)
201 msg ("Unknown file type '%c' for %s, extracted as normal file",
202 head
->header
.linkflag
, skipcrud
+ current_file_name
);
206 * JK - What we want to do if the file is sparse is loop through
207 * the array of sparse structures in the header and read in
208 * and translate the character strings representing 1) the offset
209 * at which to write and 2) how many bytes to write into numbers,
210 * which we store into the scratch array, "sparsearray". This
211 * array makes our life easier the same way it did in creating
212 * the tar file that had to deal with a sparse file.
214 * After we read in the first five (at most) sparse structures,
215 * we check to see if the file has an extended header, i.e.,
216 * if more sparse structures are needed to describe the contents
217 * of the new file. If so, we read in the extended headers
218 * and continue to store their contents into the sparsearray.
222 sparsearray
= (struct sp_array
*) malloc (sp_array_size
* sizeof (struct sp_array
));
223 for (i
= 0; i
< SPARSE_IN_HDR
; i
++)
225 sparsearray
[i
].offset
=
226 from_oct (1 + 12, head
->header
.sp
[i
].offset
);
227 sparsearray
[i
].numbytes
=
228 from_oct (1 + 12, head
->header
.sp
[i
].numbytes
);
229 if (!sparsearray
[i
].numbytes
)
233 /* end_nulls = from_oct(1+12, head->header.ending_blanks);*/
235 if (head
->header
.isextended
)
237 /* read in the list of extended headers
238 and translate them into the sparsearray
241 /* static */ int ind
= SPARSE_IN_HDR
;
247 for (i
= 0; i
< SPARSE_EXT_HDR
; i
++)
250 if (i
+ ind
> sp_array_size
- 1)
253 * realloc the scratch area
254 * since we've run out of room --
256 sparsearray
= (struct sp_array
*)
257 realloc (sparsearray
,
258 2 * sp_array_size
* (sizeof (struct sp_array
)));
261 if (!exhdr
->ext_hdr
.sp
[i
].numbytes
)
263 sparsearray
[i
+ ind
].offset
=
264 from_oct (1 + 12, exhdr
->ext_hdr
.sp
[i
].offset
);
265 sparsearray
[i
+ ind
].numbytes
=
266 from_oct (1 + 12, exhdr
->ext_hdr
.sp
[i
].numbytes
);
268 if (!exhdr
->ext_hdr
.isextended
)
272 ind
+= SPARSE_EXT_HDR
;
284 * Appears to be a file.
285 * See if it's really a directory.
287 namelen
= strlen (skipcrud
+ current_file_name
) - 1;
288 if (current_file_name
[skipcrud
+ namelen
] == '/')
291 /* FIXME, deal with protection issues */
294 O_BINARY
| O_NDELAY
| O_WRONLY
| O_CREAT
| O_EXCL
:
295 O_BINARY
| O_NDELAY
| O_WRONLY
| O_CREAT
| O_TRUNC
)
296 | ((head
->header
.linkflag
== LF_SPARSE
) ? 0 : O_APPEND
);
298 * JK - The last | is a kludge to solve the problem
299 * the O_APPEND flag causes with files we are
300 * trying to make sparse: when a file is opened
301 * with O_APPEND, it writes to the last place
302 * that something was written, thereby ignoring
303 * any lseeks that we have done. We add this
304 * extra condition to make it able to lseek when
305 * a file is sparse, i.e., we don't open the new
306 * file with this flag. (Grump -- this bug caused
307 * me to waste a good deal of time, I might add)
317 * Contiguous files (on the Masscomp) have to specify
318 * the size in the open call that creates them.
320 if (head
->header
.linkflag
== LF_CONTIG
)
321 fd
= open ((longname
? longname
: head
->header
.name
)
324 hstat
.st_mode
, hstat
.st_size
);
330 * On raw V7 we won't let them specify -k (f_keep), but
331 * we just bull ahead and create the files.
333 fd
= creat ((longname
335 : head
->header
.name
) + skipcrud
,
339 * With 3-arg open(), we can do this up right.
341 fd
= open (skipcrud
+ current_file_name
,
342 openflag
, hstat
.st_mode
);
348 if (make_dirs (skipcrud
+ current_file_name
))
350 msg_perror ("Could not create file %s",
351 skipcrud
+ current_file_name
);
352 if (head
->header
.isextended
)
353 skip_extended_headers ();
354 skip_file ((long) hstat
.st_size
);
359 if (head
->header
.linkflag
== LF_SPARSE
)
365 * Kludge alert. NAME is assigned to header.name
366 * because during the extraction, the space that
367 * contains the header will get scribbled on, and
368 * the name will get munged, so any error messages
369 * that happen to contain the filename will look
370 * REAL interesting unless we do this.
372 namelen
= strlen (skipcrud
+ current_file_name
);
373 name
= (char *) malloc ((sizeof (char)) * namelen
);
374 bcopy (skipcrud
+ current_file_name
, name
, namelen
);
375 size
= hstat
.st_size
;
376 extract_sparse_file (fd
, &size
, hstat
.st_size
, name
);
379 for (size
= hstat
.st_size
;
389 save_name
= current_file_name
;
390 save_totsize
= hstat
.st_size
;
391 save_sizeleft
= size
;
395 * Locate data, determine max length
396 * writeable, write it, record that
397 * we have used the data, then check
398 * if the write worked.
400 data
= findrec ()->charptr
;
403 msg ("Unexpected EOF on archive file");
407 * JK - If the file is sparse, use the sparsearray
408 * that we created before to lseek into the new
409 * file the proper amount, and to see how many
410 * bytes we want to write at that position.
412 /* if (head->header.linkflag == LF_SPARSE) {
415 pos = lseek(fd, (off_t) sparsearray[sparse_ind].offset, 0);
416 printf("%d at %d\n", (int) pos, sparse_ind);
417 written = sparsearray[sparse_ind++].numbytes;
419 written
= endofrecs ()->charptr
- data
;
423 check
= write (fd
, data
, written
);
425 * The following is in violation of strict
426 * typing, since the arg to userec
427 * should be a struct rec *. FIXME.
429 userec ((union record
*) (data
+ written
- 1));
430 if (check
== written
)
433 * Error in writing to file.
434 * Print it, skip to next file in archive.
437 msg_perror ("couldn't write to file %s",
438 skipcrud
+ current_file_name
);
440 msg ("could only write %d of %d bytes to file %s",
441 written
, check
, skipcrud
+ current_file_name
);
442 skip_file ((long) (size
- written
));
443 break; /* Still do the close, mod time, chmod, etc */
449 /* If writing to stdout, don't try to do anything
450 to the filename; it doesn't exist, or we don't
451 want to touch it anyway */
455 /* if (head->header.isextended) {
456 register union record *exhdr;
459 for (i = 0; i < 21; i++) {
462 if (!exhdr->ext_hdr.sp[i].numbytes)
464 offset = from_oct(1+12,
465 exhdr->ext_hdr.sp[i].offset);
466 written = from_oct(1+12,
467 exhdr->ext_hdr.sp[i].numbytes);
468 lseek(fd, offset, 0);
469 check = write(fd, data, written);
470 if (check == written) continue;
479 msg_perror ("Error while closing %s",
480 skipcrud
+ current_file_name
);
487 * If we are root, set the owner and group of the extracted
488 * file. This does what is wanted both on real Unix and on
489 * System V. If we are running as a user, we extract as that
490 * user; if running as root, we extract as the original owner.
492 if (we_are_root
|| f_do_chown
)
494 if (chown (skipcrud
+ current_file_name
,
495 hstat
.st_uid
, hstat
.st_gid
) < 0)
497 msg_perror ("cannot chown file %s to uid %d gid %d",
498 skipcrud
+ current_file_name
,
499 hstat
.st_uid
, hstat
.st_gid
);
504 * Set the modified time of the file.
506 * Note that we set the accessed time to "now", which
507 * is really "the time we started extracting files".
508 * unless f_gnudump is used, in which case .st_atime is used
512 /* fixme if f_gnudump should set ctime too, but how? */
514 acc_upd_times
.actime
= hstat
.st_atime
;
516 acc_upd_times
.actime
= now
; /* Accessed now */
517 acc_upd_times
.modtime
= hstat
.st_mtime
; /* Mod'd */
518 if (utime (skipcrud
+ current_file_name
,
521 msg_perror ("couldn't change access and modification times of %s", skipcrud
+ current_file_name
);
524 /* We do the utime before the chmod because some versions of
525 utime are broken and trash the modes of the file. Since
526 we then change the mode anyway, we don't care. . . */
529 * If '-k' is not set, open() or creat() could have saved
530 * the permission bits from a previously created file,
531 * ignoring the ones we specified.
532 * Even if -k is set, if the file has abnormal
533 * mode bits, we must chmod since writing or chown() has
534 * probably reset them.
536 * If -k is set, we know *we* created this file, so the mode
537 * bits were set by our open(). If the file is "normal", we
538 * skip the chmod. This works because we did umask(0) if -p
539 * is set, so umask will have left the specified mode alone.
542 || (hstat
.st_mode
& (S_ISUID
| S_ISGID
| S_ISVTX
)))
544 if (chmod (skipcrud
+ current_file_name
,
545 notumask
& (int) hstat
.st_mode
) < 0)
547 msg_perror ("cannot change mode of file %s to %ld",
548 skipcrud
+ current_file_name
,
549 notumask
& (int) hstat
.st_mode
);
559 struct stat st1
, st2
;
561 check
= link (current_link_name
, skipcrud
+ current_file_name
);
565 if (make_dirs (skipcrud
+ current_file_name
))
567 if (f_gnudump
&& errno
== EEXIST
)
569 if (stat (current_link_name
, &st1
) == 0
570 && stat (current_file_name
+ skipcrud
, &st2
) == 0
571 && st1
.st_dev
== st2
.st_dev
572 && st1
.st_ino
== st2
.st_ino
)
574 msg_perror ("Could not link %s to %s",
575 skipcrud
+ current_file_name
,
583 check
= symlink (current_link_name
,
584 skipcrud
+ current_file_name
);
585 /* FIXME, don't worry uid, gid, etc... */
588 if (make_dirs (current_file_name
+ skipcrud
))
590 msg_perror ("Could not create symlink to %s",
597 hstat
.st_mode
|= S_IFCHR
;
603 hstat
.st_mode
|= S_IFBLK
;
605 #if defined(S_IFCHR) || defined(S_IFBLK)
607 check
= mknod (current_file_name
+ skipcrud
,
608 (int) hstat
.st_mode
, (int) hstat
.st_rdev
);
611 if (make_dirs (skipcrud
+ current_file_name
))
613 msg_perror ("Could not make %s",
614 current_file_name
+ skipcrud
);
621 /* If local system doesn't support FIFOs, use default case */
624 check
= mkfifo (current_file_name
+ skipcrud
,
625 (int) hstat
.st_mode
);
628 if (make_dirs (current_file_name
+ skipcrud
))
630 msg_perror ("Could not make %s",
631 skipcrud
+ current_file_name
);
639 namelen
= strlen (current_file_name
) + skipcrud
- 1;
641 /* Check for trailing /, and zap as many as we find. */
643 && current_file_name
[skipcrud
+ namelen
] == '/')
644 current_file_name
[skipcrud
+ namelen
--] = '\0';
646 { /* Read the entry and delete files
647 that aren't listed in the archive */
648 gnu_restore (skipcrud
);
651 else if (head
->header
.linkflag
== LF_DUMPDIR
)
652 skip_file ((long) (hstat
.st_size
));
656 check
= mkdir (skipcrud
+ current_file_name
,
657 (we_are_root
? 0 : 0300) | (int) hstat
.st_mode
);
662 if (make_dirs (skipcrud
+ current_file_name
))
664 /* If we're trying to create '.', let it be. */
665 if (current_file_name
[skipcrud
+ namelen
] == '.' &&
667 current_file_name
[skipcrud
+ namelen
- 1] == '/'))
670 && stat (skipcrud
+ current_file_name
, &st1
) == 0
671 && (S_ISDIR (st1
.st_mode
)))
673 msg_perror ("Could not create directory %s", skipcrud
+ current_file_name
);
678 if (!we_are_root
&& 0300 != (0300 & (int) hstat
.st_mode
))
680 hstat
.st_mode
|= 0300;
681 msg ("Added write and execute permission to directory %s",
682 skipcrud
+ current_file_name
);
687 tmp
= (struct saved_dir_info
*) malloc (sizeof (struct saved_dir_info
));
688 tmp
->path
= malloc (strlen (skipcrud
+ current_file_name
) + 1);
689 strcpy (tmp
->path
, skipcrud
+ current_file_name
);
690 tmp
->mode
= hstat
.st_mode
;
691 tmp
->atime
= hstat
.st_atime
;
692 tmp
->mtime
= hstat
.st_mtime
;
693 tmp
->next
= saved_dir_info_head
;
694 saved_dir_info_head
= tmp
;
698 printf ("Reading %s\n", current_file_name
);
703 extract_mangle (head
);
707 msg ("Can't extract '%s'--file is continued from another volume\n", current_file_name
);
708 skip_file ((long) hstat
.st_size
);
713 msg ("Visible long name error\n");
714 skip_file ((long) hstat
.st_size
);
718 /* We don't need to save it any longer. */
719 saverec ((union record
**) 0);/* Unsave it */
723 * After a file/link/symlink/dir creation has failed, see if
724 * it's because some required directory was not present, and if
725 * so, create all required dirs.
731 char *p
; /* Points into path */
732 int madeone
= 0; /* Did we do anything yet? */
733 int save_errno
= errno
; /* Remember caller's errno */
737 return 0; /* Not our problem */
739 for (p
= index (pathname
, '/'); p
!= NULL
; p
= index (p
+ 1, '/'))
741 /* Avoid mkdir of empty string, if leading or double '/' */
742 if (p
== pathname
|| p
[-1] == '/')
744 /* Avoid mkdir where last part of path is '.' */
745 if (p
[-1] == '.' && (p
== pathname
+ 1 || p
[-2] == '/'))
747 *p
= 0; /* Truncate the path there */
748 check
= mkdir (pathname
, 0777); /* Try to create it as a dir */
754 if (chown (pathname
, hstat
.st_uid
,
757 msg_perror ("cannot change owner of %s to uid %d gid %d", pathname
, hstat
.st_uid
, hstat
.st_gid
);
760 pr_mkdir (pathname
, p
- pathname
, notumask
& 0777);
761 madeone
++; /* Remember if we made one */
766 if (errno
== EEXIST
) /* Directory already exists */
769 * Some other error in the mkdir. We return to the caller.
774 errno
= save_errno
; /* Restore caller's errno */
775 return madeone
; /* Tell them to retry if we made one */
779 extract_sparse_file (fd
, sizeleft
, totalsize
, name
)
781 long *sizeleft
, totalsize
;
784 /* register char *data;*/
785 union record
*datarec
;
789 /* assuming sizeleft is initially totalsize */
792 while (*sizeleft
> 0)
794 datarec
= findrec ();
797 msg ("Unexpected EOF on archive file");
800 lseek (fd
, sparsearray
[sparse_ind
].offset
, 0);
801 written
= sparsearray
[sparse_ind
++].numbytes
;
802 while (written
> RECORDSIZE
)
804 count
= write (fd
, datarec
->charptr
, RECORDSIZE
);
806 msg_perror ("couldn't write to file %s", name
);
810 datarec
= findrec ();
813 count
= write (fd
, datarec
->charptr
, written
);
817 msg_perror ("couldn't write to file %s", name
);
819 else if (count
!= written
)
821 msg ("could only write %d of %d bytes to file %s", totalsize
- *sizeleft
, totalsize
, name
);
822 skip_file ((long) (*sizeleft
));
833 printf("%d\n", (int) end_nulls);
834 for (i = 0; i < end_nulls; i++)
835 write(fd, "\000", 1);
840 /* Set back the utime and mode for all the extracted directories. */
842 restore_saved_dir_info ()
844 struct utimbuf acc_upd_times
;
845 struct saved_dir_info
*tmp
;
847 while (saved_dir_info_head
!= NULL
)
849 /* fixme if f_gnudump should set ctime too, but how? */
851 acc_upd_times
.actime
= saved_dir_info_head
->atime
;
853 acc_upd_times
.actime
= now
; /* Accessed now */
854 acc_upd_times
.modtime
= saved_dir_info_head
->mtime
; /* Mod'd */
855 if (utime (saved_dir_info_head
->path
, &acc_upd_times
) < 0)
857 msg_perror ("couldn't change access and modification times of %s",
858 saved_dir_info_head
->path
);
860 if ((!f_keep
) || (saved_dir_info_head
->mode
& (S_ISUID
| S_ISGID
| S_ISVTX
)))
862 if (chmod (saved_dir_info_head
->path
,
863 notumask
& saved_dir_info_head
->mode
) < 0)
865 msg_perror ("cannot change mode of file %s to %ld",
866 saved_dir_info_head
->path
,
867 notumask
& saved_dir_info_head
->mode
);
870 saved_dir_info_head
= saved_dir_info_head
->next
;
This page took 0.074365 seconds and 4 git commands to generate.