]> Dogcows Code - chaz/tar/blob - src/extract.c
*** empty log message ***
[chaz/tar] / src / extract.c
1 /* Extract files from a tar archive.
2 Copyright (C) 1988, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
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)
9 any later version.
10
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.
15
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. */
19
20 /*
21 * Extract files from a tar archive.
22 *
23 * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
24 */
25
26 #include <stdio.h>
27 #include <errno.h>
28 #ifndef STDC_HEADERS
29 extern int errno;
30 #endif
31 #include <sys/types.h>
32 #include <time.h>
33 time_t time ();
34
35 #ifdef BSD42
36 #include <sys/file.h>
37 #else
38 #ifndef V7
39 #include <fcntl.h>
40 #endif
41 #endif
42
43 #ifdef NO_OPEN3
44 /* We need the #define's even though we don't use them. */
45 #include "open3.h"
46 #endif
47
48 #ifdef EMUL_OPEN3
49 /* Simulated 3-argument open for systems that don't have it */
50 #include "open3.h"
51 #endif
52
53 #include "tar.h"
54 #include "port.h"
55
56 #if defined(_POSIX_VERSION)
57 #include <utime.h>
58 #else
59 struct utimbuf
60 {
61 long actime;
62 long modtime;
63 };
64
65 #endif
66
67 extern FILE *msg_file;
68
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 */
72
73 extern char *save_name;
74 extern long save_totsize;
75 extern long save_sizeleft;
76
77 int confirm ();
78 void decode_header ();
79 void extract_mangle ();
80 void extract_sparse_file ();
81 long from_oct ();
82 void gnu_restore ();
83 extern void print_header ();
84 extern void skip_file ();
85 extern void skip_extended_headers ();
86 extern void pr_mkdir ();
87 void saverec ();
88
89 int make_dirs (); /* Makes required directories */
90
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 */
94
95 /*
96 * "Scratch" space to store the information about a sparse file before
97 * writing the info into the header or extended header
98 */
99 /*struct sp_array *sparsearray;*/
100
101 /* number of elts storable in the sparsearray */
102 /*int sp_array_size = 10;*/
103
104 struct saved_dir_info
105 {
106 char *path;
107 int mode;
108 int atime;
109 int mtime;
110 struct saved_dir_info *next;
111 };
112
113 struct saved_dir_info *saved_dir_info_head;
114
115 /*
116 * Set up to extract files.
117 */
118 void
119 extr_init ()
120 {
121 int ourmask;
122
123 now = time ((time_t *) 0);
124 if (geteuid () == 0)
125 we_are_root = 1;
126
127 /*
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.
130 */
131 ourmask = umask (0); /* Read it */
132 if (!f_use_protection)
133 {
134 (void) umask (ourmask); /* Set it back how it was */
135 notumask = ~ourmask; /* Make umask override permissions */
136 }
137 }
138
139
140 /*
141 * Extract a file from the archive.
142 */
143 void
144 extract_archive ()
145 {
146 register char *data;
147 int fd, check, namelen, written, openflag;
148 long size;
149 struct utimbuf acc_upd_times;
150 register int skipcrud;
151 register int i;
152 /* int sparse_ind = 0;*/
153 union record *exhdr;
154 struct saved_dir_info *tmp;
155 /* int end_nulls; */
156 char **longp;
157 char *bp;
158
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 */
162
163 if (f_confirm && !confirm ("extract", current_file_name))
164 {
165 if (head->header.isextended)
166 skip_extended_headers ();
167 skip_file ((long) hstat.st_size);
168 saverec ((union record **) 0);
169 return;
170 }
171
172 /* Print the record from 'head' and 'hstat' */
173 if (f_verbose)
174 print_header ();
175
176 /*
177 * Check for fully specified pathnames and other atrocities.
178 *
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
182 * the header record.
183 */
184 skipcrud = 0;
185 while (!f_absolute_paths
186 && '/' == current_file_name[skipcrud])
187 {
188 static int warned_once = 0;
189
190 skipcrud++; /* Force relative path */
191 if (!warned_once++)
192 {
193 msg ("Removing leading / from absolute path names in the archive.");
194 }
195 }
196
197 switch (head->header.linkflag)
198 {
199
200 default:
201 msg ("Unknown file type '%c' for %s, extracted as normal file",
202 head->header.linkflag, skipcrud + current_file_name);
203 /* FALL THRU */
204
205 /*
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.
213 *
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.
219 */
220 case LF_SPARSE:
221 sp_array_size = 10;
222 sparsearray = (struct sp_array *) malloc (sp_array_size * sizeof (struct sp_array));
223 for (i = 0; i < SPARSE_IN_HDR; i++)
224 {
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)
230 break;
231 }
232
233 /* end_nulls = from_oct(1+12, head->header.ending_blanks);*/
234
235 if (head->header.isextended)
236 {
237 /* read in the list of extended headers
238 and translate them into the sparsearray
239 as before */
240
241 /* static */ int ind = SPARSE_IN_HDR;
242
243 for (;;)
244 {
245
246 exhdr = findrec ();
247 for (i = 0; i < SPARSE_EXT_HDR; i++)
248 {
249
250 if (i + ind > sp_array_size - 1)
251 {
252 /*
253 * realloc the scratch area
254 * since we've run out of room --
255 */
256 sparsearray = (struct sp_array *)
257 realloc (sparsearray,
258 2 * sp_array_size * (sizeof (struct sp_array)));
259 sp_array_size *= 2;
260 }
261 if (!exhdr->ext_hdr.sp[i].numbytes)
262 break;
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);
267 }
268 if (!exhdr->ext_hdr.isextended)
269 break;
270 else
271 {
272 ind += SPARSE_EXT_HDR;
273 userec (exhdr);
274 }
275 }
276 userec (exhdr);
277 }
278
279 /* FALL THRU */
280 case LF_OLDNORMAL:
281 case LF_NORMAL:
282 case LF_CONTIG:
283 /*
284 * Appears to be a file.
285 * See if it's really a directory.
286 */
287 namelen = strlen (skipcrud + current_file_name) - 1;
288 if (current_file_name[skipcrud + namelen] == '/')
289 goto really_dir;
290
291 /* FIXME, deal with protection issues */
292 again_file:
293 openflag = (f_keep ?
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);
297 /*
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)
308 */
309
310 if (f_exstdout)
311 {
312 fd = 1;
313 goto extract_file;
314 }
315 #ifdef O_CTG
316 /*
317 * Contiguous files (on the Masscomp) have to specify
318 * the size in the open call that creates them.
319 */
320 if (head->header.linkflag == LF_CONTIG)
321 fd = open ((longname ? longname : head->header.name)
322 + skipcrud,
323 openflag | O_CTG,
324 hstat.st_mode, hstat.st_size);
325 else
326 #endif
327 {
328 #ifdef NO_OPEN3
329 /*
330 * On raw V7 we won't let them specify -k (f_keep), but
331 * we just bull ahead and create the files.
332 */
333 fd = creat ((longname
334 ? longname
335 : head->header.name) + skipcrud,
336 hstat.st_mode);
337 #else
338 /*
339 * With 3-arg open(), we can do this up right.
340 */
341 fd = open (skipcrud + current_file_name,
342 openflag, hstat.st_mode);
343 #endif
344 }
345
346 if (fd < 0)
347 {
348 if (make_dirs (skipcrud + current_file_name))
349 goto again_file;
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);
355 goto quit;
356 }
357
358 extract_file:
359 if (head->header.linkflag == LF_SPARSE)
360 {
361 char *name;
362 int namelen;
363
364 /*
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.
371 */
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);
377 }
378 else
379 for (size = hstat.st_size;
380 size > 0;
381 size -= written)
382 {
383
384 /* long offset,
385 numbytes;*/
386
387 if (f_multivol)
388 {
389 save_name = current_file_name;
390 save_totsize = hstat.st_size;
391 save_sizeleft = size;
392 }
393
394 /*
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.
399 */
400 data = findrec ()->charptr;
401 if (data == NULL)
402 { /* Check it... */
403 msg ("Unexpected EOF on archive file");
404 break;
405 }
406 /*
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.
411 */
412 /* if (head->header.linkflag == LF_SPARSE) {
413 off_t pos;
414
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;
418 } else*/
419 written = endofrecs ()->charptr - data;
420 if (written > size)
421 written = size;
422 errno = 0;
423 check = write (fd, data, written);
424 /*
425 * The following is in violation of strict
426 * typing, since the arg to userec
427 * should be a struct rec *. FIXME.
428 */
429 userec ((union record *) (data + written - 1));
430 if (check == written)
431 continue;
432 /*
433 * Error in writing to file.
434 * Print it, skip to next file in archive.
435 */
436 if (check < 0)
437 msg_perror ("couldn't write to file %s",
438 skipcrud + current_file_name);
439 else
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 */
444 }
445
446 if (f_multivol)
447 save_name = 0;
448
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 */
452 if (f_exstdout)
453 break;
454
455 /* if (head->header.isextended) {
456 register union record *exhdr;
457 register int i;
458
459 for (i = 0; i < 21; i++) {
460 long offset;
461
462 if (!exhdr->ext_hdr.sp[i].numbytes)
463 break;
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;
471
472 }
473
474
475 }*/
476 check = close (fd);
477 if (check < 0)
478 {
479 msg_perror ("Error while closing %s",
480 skipcrud + current_file_name);
481 }
482
483
484 set_filestat:
485
486 /*
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.
491 */
492 if (we_are_root || f_do_chown)
493 {
494 if (chown (skipcrud + current_file_name,
495 hstat.st_uid, hstat.st_gid) < 0)
496 {
497 msg_perror ("cannot chown file %s to uid %d gid %d",
498 skipcrud + current_file_name,
499 hstat.st_uid, hstat.st_gid);
500 }
501 }
502
503 /*
504 * Set the modified time of the file.
505 *
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
509 */
510 if (!f_modified)
511 {
512 /* fixme if f_gnudump should set ctime too, but how? */
513 if (f_gnudump)
514 acc_upd_times.actime = hstat.st_atime;
515 else
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,
519 &acc_upd_times) < 0)
520 {
521 msg_perror ("couldn't change access and modification times of %s", skipcrud + current_file_name);
522 }
523 }
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. . . */
527
528 /*
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.
535 *
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.
540 */
541 if ((!f_keep)
542 || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
543 {
544 if (chmod (skipcrud + current_file_name,
545 notumask & (int) hstat.st_mode) < 0)
546 {
547 msg_perror ("cannot change mode of file %s to %ld",
548 skipcrud + current_file_name,
549 notumask & (int) hstat.st_mode);
550 }
551 }
552
553 quit:
554 break;
555
556 case LF_LINK:
557 again_link:
558 {
559 struct stat st1, st2;
560
561 check = link (current_link_name, skipcrud + current_file_name);
562
563 if (check == 0)
564 break;
565 if (make_dirs (skipcrud + current_file_name))
566 goto again_link;
567 if (f_gnudump && errno == EEXIST)
568 break;
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)
573 break;
574 msg_perror ("Could not link %s to %s",
575 skipcrud + current_file_name,
576 current_link_name);
577 }
578 break;
579
580 #ifdef S_ISLNK
581 case LF_SYMLINK:
582 again_symlink:
583 check = symlink (current_link_name,
584 skipcrud + current_file_name);
585 /* FIXME, don't worry uid, gid, etc... */
586 if (check == 0)
587 break;
588 if (make_dirs (current_file_name + skipcrud))
589 goto again_symlink;
590 msg_perror ("Could not create symlink to %s",
591 current_link_name);
592 break;
593 #endif
594
595 #ifdef S_IFCHR
596 case LF_CHR:
597 hstat.st_mode |= S_IFCHR;
598 goto make_node;
599 #endif
600
601 #ifdef S_IFBLK
602 case LF_BLK:
603 hstat.st_mode |= S_IFBLK;
604 #endif
605 #if defined(S_IFCHR) || defined(S_IFBLK)
606 make_node:
607 check = mknod (current_file_name + skipcrud,
608 (int) hstat.st_mode, (int) hstat.st_rdev);
609 if (check != 0)
610 {
611 if (make_dirs (skipcrud + current_file_name))
612 goto make_node;
613 msg_perror ("Could not make %s",
614 current_file_name + skipcrud);
615 break;
616 };
617 goto set_filestat;
618 #endif
619
620 #ifdef S_ISFIFO
621 /* If local system doesn't support FIFOs, use default case */
622 case LF_FIFO:
623 make_fifo:
624 check = mkfifo (current_file_name + skipcrud,
625 (int) hstat.st_mode);
626 if (check != 0)
627 {
628 if (make_dirs (current_file_name + skipcrud))
629 goto make_fifo;
630 msg_perror ("Could not make %s",
631 skipcrud + current_file_name);
632 break;
633 };
634 goto set_filestat;
635 #endif
636
637 case LF_DIR:
638 case LF_DUMPDIR:
639 namelen = strlen (current_file_name) + skipcrud - 1;
640 really_dir:
641 /* Check for trailing /, and zap as many as we find. */
642 while (namelen
643 && current_file_name[skipcrud + namelen] == '/')
644 current_file_name[skipcrud + namelen--] = '\0';
645 if (f_gnudump)
646 { /* Read the entry and delete files
647 that aren't listed in the archive */
648 gnu_restore (skipcrud);
649
650 }
651 else if (head->header.linkflag == LF_DUMPDIR)
652 skip_file ((long) (hstat.st_size));
653
654
655 again_dir:
656 check = mkdir (skipcrud + current_file_name,
657 (we_are_root ? 0 : 0300) | (int) hstat.st_mode);
658 if (check != 0)
659 {
660 struct stat st1;
661
662 if (make_dirs (skipcrud + current_file_name))
663 goto again_dir;
664 /* If we're trying to create '.', let it be. */
665 if (current_file_name[skipcrud + namelen] == '.' &&
666 (namelen == 0 ||
667 current_file_name[skipcrud + namelen - 1] == '/'))
668 goto check_perms;
669 if (errno == EEXIST
670 && stat (skipcrud + current_file_name, &st1) == 0
671 && (S_ISDIR (st1.st_mode)))
672 break;
673 msg_perror ("Could not create directory %s", skipcrud + current_file_name);
674 break;
675 }
676
677 check_perms:
678 if (!we_are_root && 0300 != (0300 & (int) hstat.st_mode))
679 {
680 hstat.st_mode |= 0300;
681 msg ("Added write and execute permission to directory %s",
682 skipcrud + current_file_name);
683 }
684
685 if (f_modified)
686 goto set_filestat;
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;
695 case LF_VOLHDR:
696 if (f_verbose)
697 {
698 printf ("Reading %s\n", current_file_name);
699 }
700 break;
701
702 case LF_NAMES:
703 extract_mangle (head);
704 break;
705
706 case LF_MULTIVOL:
707 msg ("Can't extract '%s'--file is continued from another volume\n", current_file_name);
708 skip_file ((long) hstat.st_size);
709 break;
710
711 case LF_LONGNAME:
712 case LF_LONGLINK:
713 msg ("Visible long name error\n");
714 skip_file ((long) hstat.st_size);
715 break;
716 }
717
718 /* We don't need to save it any longer. */
719 saverec ((union record **) 0);/* Unsave it */
720 }
721
722 /*
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.
726 */
727 int
728 make_dirs (pathname)
729 char *pathname;
730 {
731 char *p; /* Points into path */
732 int madeone = 0; /* Did we do anything yet? */
733 int save_errno = errno; /* Remember caller's errno */
734 int check;
735
736 if (errno != ENOENT)
737 return 0; /* Not our problem */
738
739 for (p = index (pathname, '/'); p != NULL; p = index (p + 1, '/'))
740 {
741 /* Avoid mkdir of empty string, if leading or double '/' */
742 if (p == pathname || p[-1] == '/')
743 continue;
744 /* Avoid mkdir where last part of path is '.' */
745 if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
746 continue;
747 *p = 0; /* Truncate the path there */
748 check = mkdir (pathname, 0777); /* Try to create it as a dir */
749 if (check == 0)
750 {
751 /* Fix ownership */
752 if (we_are_root)
753 {
754 if (chown (pathname, hstat.st_uid,
755 hstat.st_gid) < 0)
756 {
757 msg_perror ("cannot change owner of %s to uid %d gid %d", pathname, hstat.st_uid, hstat.st_gid);
758 }
759 }
760 pr_mkdir (pathname, p - pathname, notumask & 0777);
761 madeone++; /* Remember if we made one */
762 *p = '/';
763 continue;
764 }
765 *p = '/';
766 if (errno == EEXIST) /* Directory already exists */
767 continue;
768 /*
769 * Some other error in the mkdir. We return to the caller.
770 */
771 break;
772 }
773
774 errno = save_errno; /* Restore caller's errno */
775 return madeone; /* Tell them to retry if we made one */
776 }
777
778 void
779 extract_sparse_file (fd, sizeleft, totalsize, name)
780 int fd;
781 long *sizeleft, totalsize;
782 char *name;
783 {
784 /* register char *data;*/
785 union record *datarec;
786 int sparse_ind = 0;
787 int written, count;
788
789 /* assuming sizeleft is initially totalsize */
790
791
792 while (*sizeleft > 0)
793 {
794 datarec = findrec ();
795 if (datarec == NULL)
796 {
797 msg ("Unexpected EOF on archive file");
798 return;
799 }
800 lseek (fd, sparsearray[sparse_ind].offset, 0);
801 written = sparsearray[sparse_ind++].numbytes;
802 while (written > RECORDSIZE)
803 {
804 count = write (fd, datarec->charptr, RECORDSIZE);
805 if (count < 0)
806 msg_perror ("couldn't write to file %s", name);
807 written -= count;
808 *sizeleft -= count;
809 userec (datarec);
810 datarec = findrec ();
811 }
812
813 count = write (fd, datarec->charptr, written);
814
815 if (count < 0)
816 {
817 msg_perror ("couldn't write to file %s", name);
818 }
819 else if (count != written)
820 {
821 msg ("could only write %d of %d bytes to file %s", totalsize - *sizeleft, totalsize, name);
822 skip_file ((long) (*sizeleft));
823 }
824
825 written -= count;
826 *sizeleft -= count;
827 userec (datarec);
828 }
829 free (sparsearray);
830 /* if (end_nulls) {
831 register int i;
832
833 printf("%d\n", (int) end_nulls);
834 for (i = 0; i < end_nulls; i++)
835 write(fd, "\000", 1);
836 }*/
837 userec (datarec);
838 }
839
840 /* Set back the utime and mode for all the extracted directories. */
841 void
842 restore_saved_dir_info ()
843 {
844 struct utimbuf acc_upd_times;
845 struct saved_dir_info *tmp;
846
847 while (saved_dir_info_head != NULL)
848 {
849 /* fixme if f_gnudump should set ctime too, but how? */
850 if (f_gnudump)
851 acc_upd_times.actime = saved_dir_info_head->atime;
852 else
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)
856 {
857 msg_perror ("couldn't change access and modification times of %s",
858 saved_dir_info_head->path);
859 }
860 if ((!f_keep) || (saved_dir_info_head->mode & (S_ISUID | S_ISGID | S_ISVTX)))
861 {
862 if (chmod (saved_dir_info_head->path,
863 notumask & saved_dir_info_head->mode) < 0)
864 {
865 msg_perror ("cannot change mode of file %s to %ld",
866 saved_dir_info_head->path,
867 notumask & saved_dir_info_head->mode);
868 }
869 }
870 saved_dir_info_head = saved_dir_info_head->next;
871 }
872 }
This page took 0.079303 seconds and 5 git commands to generate.