]> 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
157 saverec (&head); /* Make sure it sticks around */
158 userec (head); /* And go past it in the archive */
159 decode_header (head, &hstat, &head_standard, 1); /* Snarf fields */
160
161 if (f_confirm && !confirm ("extract", current_file_name))
162 {
163 if (head->header.isextended)
164 skip_extended_headers ();
165 skip_file ((long) hstat.st_size);
166 saverec ((union record **) 0);
167 return;
168 }
169
170 /* Print the record from 'head' and 'hstat' */
171 if (f_verbose)
172 print_header ();
173
174 /*
175 * Check for fully specified pathnames and other atrocities.
176 *
177 * Note, we can't just make a pointer to the new file name,
178 * since saverec() might move the header and adjust "head".
179 * We have to start from "head" every time we want to touch
180 * the header record.
181 */
182 skipcrud = 0;
183 while (!f_absolute_paths
184 && '/' == current_file_name[skipcrud])
185 {
186 static int warned_once = 0;
187
188 skipcrud++; /* Force relative path */
189 if (!warned_once++)
190 {
191 msg ("Removing leading / from absolute path names in the archive.");
192 }
193 }
194
195 switch (head->header.linkflag)
196 {
197
198 default:
199 msg ("Unknown file type '%c' for %s, extracted as normal file",
200 head->header.linkflag, skipcrud + current_file_name);
201 /* FALL THRU */
202
203 /*
204 * JK - What we want to do if the file is sparse is loop through
205 * the array of sparse structures in the header and read in
206 * and translate the character strings representing 1) the offset
207 * at which to write and 2) how many bytes to write into numbers,
208 * which we store into the scratch array, "sparsearray". This
209 * array makes our life easier the same way it did in creating
210 * the tar file that had to deal with a sparse file.
211 *
212 * After we read in the first five (at most) sparse structures,
213 * we check to see if the file has an extended header, i.e.,
214 * if more sparse structures are needed to describe the contents
215 * of the new file. If so, we read in the extended headers
216 * and continue to store their contents into the sparsearray.
217 */
218 case LF_SPARSE:
219 sp_array_size = 10;
220 sparsearray = (struct sp_array *) malloc (sp_array_size * sizeof (struct sp_array));
221 for (i = 0; i < SPARSE_IN_HDR; i++)
222 {
223 sparsearray[i].offset =
224 from_oct (1 + 12, head->header.sp[i].offset);
225 sparsearray[i].numbytes =
226 from_oct (1 + 12, head->header.sp[i].numbytes);
227 if (!sparsearray[i].numbytes)
228 break;
229 }
230
231 /* end_nulls = from_oct(1+12, head->header.ending_blanks);*/
232
233 if (head->header.isextended)
234 {
235 /* read in the list of extended headers
236 and translate them into the sparsearray
237 as before */
238
239 /* static */ int ind = SPARSE_IN_HDR;
240
241 for (;;)
242 {
243
244 exhdr = findrec ();
245 for (i = 0; i < SPARSE_EXT_HDR; i++)
246 {
247
248 if (i + ind > sp_array_size - 1)
249 {
250 /*
251 * realloc the scratch area
252 * since we've run out of room --
253 */
254 sparsearray = (struct sp_array *)
255 realloc (sparsearray,
256 2 * sp_array_size * (sizeof (struct sp_array)));
257 sp_array_size *= 2;
258 }
259 if (!exhdr->ext_hdr.sp[i].numbytes)
260 break;
261 sparsearray[i + ind].offset =
262 from_oct (1 + 12, exhdr->ext_hdr.sp[i].offset);
263 sparsearray[i + ind].numbytes =
264 from_oct (1 + 12, exhdr->ext_hdr.sp[i].numbytes);
265 }
266 if (!exhdr->ext_hdr.isextended)
267 break;
268 else
269 {
270 ind += SPARSE_EXT_HDR;
271 userec (exhdr);
272 }
273 }
274 userec (exhdr);
275 }
276
277 /* FALL THRU */
278 case LF_OLDNORMAL:
279 case LF_NORMAL:
280 case LF_CONTIG:
281 /*
282 * Appears to be a file.
283 * See if it's really a directory.
284 */
285 namelen = strlen (skipcrud + current_file_name) - 1;
286 if (current_file_name[skipcrud + namelen] == '/')
287 goto really_dir;
288
289 /* FIXME, deal with protection issues */
290 again_file:
291 openflag = (f_keep ?
292 O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_EXCL :
293 O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_TRUNC)
294 | ((head->header.linkflag == LF_SPARSE) ? 0 : O_APPEND);
295 /*
296 * JK - The last | is a kludge to solve the problem
297 * the O_APPEND flag causes with files we are
298 * trying to make sparse: when a file is opened
299 * with O_APPEND, it writes to the last place
300 * that something was written, thereby ignoring
301 * any lseeks that we have done. We add this
302 * extra condition to make it able to lseek when
303 * a file is sparse, i.e., we don't open the new
304 * file with this flag. (Grump -- this bug caused
305 * me to waste a good deal of time, I might add)
306 */
307
308 if (f_exstdout)
309 {
310 fd = 1;
311 goto extract_file;
312 }
313 #ifdef O_CTG
314 /*
315 * Contiguous files (on the Masscomp) have to specify
316 * the size in the open call that creates them.
317 */
318 if (head->header.linkflag == LF_CONTIG)
319 fd = open ((longname ? longname : head->header.name)
320 + skipcrud,
321 openflag | O_CTG,
322 hstat.st_mode, hstat.st_size);
323 else
324 #endif
325 {
326 #ifdef NO_OPEN3
327 /*
328 * On raw V7 we won't let them specify -k (f_keep), but
329 * we just bull ahead and create the files.
330 */
331 fd = creat ((longname
332 ? longname
333 : head->header.name) + skipcrud,
334 hstat.st_mode);
335 #else
336 /*
337 * With 3-arg open(), we can do this up right.
338 */
339 fd = open (skipcrud + current_file_name,
340 openflag, hstat.st_mode);
341 #endif
342 }
343
344 if (fd < 0)
345 {
346 if (make_dirs (skipcrud + current_file_name))
347 goto again_file;
348 msg_perror ("Could not create file %s",
349 skipcrud + current_file_name);
350 if (head->header.isextended)
351 skip_extended_headers ();
352 skip_file ((long) hstat.st_size);
353 goto quit;
354 }
355
356 extract_file:
357 if (head->header.linkflag == LF_SPARSE)
358 {
359 char *name;
360 int namelen;
361
362 /*
363 * Kludge alert. NAME is assigned to header.name
364 * because during the extraction, the space that
365 * contains the header will get scribbled on, and
366 * the name will get munged, so any error messages
367 * that happen to contain the filename will look
368 * REAL interesting unless we do this.
369 */
370 namelen = strlen (skipcrud + current_file_name);
371 name = (char *) malloc ((sizeof (char)) * namelen);
372 bcopy (skipcrud + current_file_name, name, namelen);
373 size = hstat.st_size;
374 extract_sparse_file (fd, &size, hstat.st_size, name);
375 }
376 else
377 for (size = hstat.st_size;
378 size > 0;
379 size -= written)
380 {
381
382 /* long offset,
383 numbytes;*/
384
385 if (f_multivol)
386 {
387 save_name = current_file_name;
388 save_totsize = hstat.st_size;
389 save_sizeleft = size;
390 }
391
392 /*
393 * Locate data, determine max length
394 * writeable, write it, record that
395 * we have used the data, then check
396 * if the write worked.
397 */
398 data = findrec ()->charptr;
399 if (data == NULL)
400 { /* Check it... */
401 msg ("Unexpected EOF on archive file");
402 break;
403 }
404 /*
405 * JK - If the file is sparse, use the sparsearray
406 * that we created before to lseek into the new
407 * file the proper amount, and to see how many
408 * bytes we want to write at that position.
409 */
410 /* if (head->header.linkflag == LF_SPARSE) {
411 off_t pos;
412
413 pos = lseek(fd, (off_t) sparsearray[sparse_ind].offset, 0);
414 printf("%d at %d\n", (int) pos, sparse_ind);
415 written = sparsearray[sparse_ind++].numbytes;
416 } else*/
417 written = endofrecs ()->charptr - data;
418 if (written > size)
419 written = size;
420 errno = 0;
421 check = write (fd, data, written);
422 /*
423 * The following is in violation of strict
424 * typing, since the arg to userec
425 * should be a struct rec *. FIXME.
426 */
427 userec ((union record *) (data + written - 1));
428 if (check == written)
429 continue;
430 /*
431 * Error in writing to file.
432 * Print it, skip to next file in archive.
433 */
434 if (check < 0)
435 msg_perror ("couldn't write to file %s",
436 skipcrud + current_file_name);
437 else
438 msg ("could only write %d of %d bytes to file %s",
439 written, check, skipcrud + current_file_name);
440 skip_file ((long) (size - written));
441 break; /* Still do the close, mod time, chmod, etc */
442 }
443
444 if (f_multivol)
445 save_name = 0;
446
447 /* If writing to stdout, don't try to do anything
448 to the filename; it doesn't exist, or we don't
449 want to touch it anyway */
450 if (f_exstdout)
451 break;
452
453 /* if (head->header.isextended) {
454 register union record *exhdr;
455 register int i;
456
457 for (i = 0; i < 21; i++) {
458 long offset;
459
460 if (!exhdr->ext_hdr.sp[i].numbytes)
461 break;
462 offset = from_oct(1+12,
463 exhdr->ext_hdr.sp[i].offset);
464 written = from_oct(1+12,
465 exhdr->ext_hdr.sp[i].numbytes);
466 lseek(fd, offset, 0);
467 check = write(fd, data, written);
468 if (check == written) continue;
469
470 }
471
472
473 }*/
474 check = close (fd);
475 if (check < 0)
476 {
477 msg_perror ("Error while closing %s",
478 skipcrud + current_file_name);
479 }
480
481
482 set_filestat:
483
484 /*
485 * If we are root, set the owner and group of the extracted
486 * file. This does what is wanted both on real Unix and on
487 * System V. If we are running as a user, we extract as that
488 * user; if running as root, we extract as the original owner.
489 */
490 if (we_are_root || f_do_chown)
491 {
492 if (chown (skipcrud + current_file_name,
493 hstat.st_uid, hstat.st_gid) < 0)
494 {
495 msg_perror ("cannot chown file %s to uid %d gid %d",
496 skipcrud + current_file_name,
497 hstat.st_uid, hstat.st_gid);
498 }
499 }
500
501 /*
502 * Set the modified time of the file.
503 *
504 * Note that we set the accessed time to "now", which
505 * is really "the time we started extracting files".
506 * unless f_gnudump is used, in which case .st_atime is used
507 */
508 if (!f_modified)
509 {
510 /* fixme if f_gnudump should set ctime too, but how? */
511 if (f_gnudump)
512 acc_upd_times.actime = hstat.st_atime;
513 else
514 acc_upd_times.actime = now; /* Accessed now */
515 acc_upd_times.modtime = hstat.st_mtime; /* Mod'd */
516 if (utime (skipcrud + current_file_name,
517 &acc_upd_times) < 0)
518 {
519 msg_perror ("couldn't change access and modification times of %s", skipcrud + current_file_name);
520 }
521 }
522 /* We do the utime before the chmod because some versions of
523 utime are broken and trash the modes of the file. Since
524 we then change the mode anyway, we don't care. . . */
525
526 /*
527 * If '-k' is not set, open() or creat() could have saved
528 * the permission bits from a previously created file,
529 * ignoring the ones we specified.
530 * Even if -k is set, if the file has abnormal
531 * mode bits, we must chmod since writing or chown() has
532 * probably reset them.
533 *
534 * If -k is set, we know *we* created this file, so the mode
535 * bits were set by our open(). If the file is "normal", we
536 * skip the chmod. This works because we did umask(0) if -p
537 * is set, so umask will have left the specified mode alone.
538 */
539 if ((!f_keep)
540 || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
541 {
542 if (chmod (skipcrud + current_file_name,
543 notumask & (int) hstat.st_mode) < 0)
544 {
545 msg_perror ("cannot change mode of file %s to %ld",
546 skipcrud + current_file_name,
547 notumask & (int) hstat.st_mode);
548 }
549 }
550
551 quit:
552 break;
553
554 case LF_LINK:
555 again_link:
556 {
557 struct stat st1, st2;
558
559 check = link (current_link_name, skipcrud + current_file_name);
560
561 if (check == 0)
562 break;
563 if (make_dirs (skipcrud + current_file_name))
564 goto again_link;
565 if (f_gnudump && errno == EEXIST)
566 break;
567 if (stat (current_link_name, &st1) == 0
568 && stat (current_file_name + skipcrud, &st2) == 0
569 && st1.st_dev == st2.st_dev
570 && st1.st_ino == st2.st_ino)
571 break;
572 msg_perror ("Could not link %s to %s",
573 skipcrud + current_file_name,
574 current_link_name);
575 }
576 break;
577
578 #ifdef S_ISLNK
579 case LF_SYMLINK:
580 again_symlink:
581 check = symlink (current_link_name,
582 skipcrud + current_file_name);
583 /* FIXME, don't worry uid, gid, etc... */
584 if (check == 0)
585 break;
586 if (make_dirs (current_file_name + skipcrud))
587 goto again_symlink;
588 msg_perror ("Could not create symlink to %s",
589 current_link_name);
590 break;
591 #endif
592
593 #ifdef S_IFCHR
594 case LF_CHR:
595 hstat.st_mode |= S_IFCHR;
596 goto make_node;
597 #endif
598
599 #ifdef S_IFBLK
600 case LF_BLK:
601 hstat.st_mode |= S_IFBLK;
602 #endif
603 #if defined(S_IFCHR) || defined(S_IFBLK)
604 make_node:
605 check = mknod (current_file_name + skipcrud,
606 (int) hstat.st_mode, (int) hstat.st_rdev);
607 if (check != 0)
608 {
609 if (make_dirs (skipcrud + current_file_name))
610 goto make_node;
611 msg_perror ("Could not make %s",
612 current_file_name + skipcrud);
613 break;
614 };
615 goto set_filestat;
616 #endif
617
618 #ifdef S_ISFIFO
619 /* If local system doesn't support FIFOs, use default case */
620 case LF_FIFO:
621 make_fifo:
622 check = mkfifo (current_file_name + skipcrud,
623 (int) hstat.st_mode);
624 if (check != 0)
625 {
626 if (make_dirs (current_file_name + skipcrud))
627 goto make_fifo;
628 msg_perror ("Could not make %s",
629 skipcrud + current_file_name);
630 break;
631 };
632 goto set_filestat;
633 #endif
634
635 case LF_DIR:
636 case LF_DUMPDIR:
637 namelen = strlen (current_file_name) + skipcrud - 1;
638 really_dir:
639 /* Check for trailing /, and zap as many as we find. */
640 while (namelen
641 && current_file_name[skipcrud + namelen] == '/')
642 current_file_name[skipcrud + namelen--] = '\0';
643 if (f_gnudump)
644 { /* Read the entry and delete files
645 that aren't listed in the archive */
646 gnu_restore (skipcrud);
647
648 }
649 else if (head->header.linkflag == LF_DUMPDIR)
650 skip_file ((long) (hstat.st_size));
651
652
653 again_dir:
654 check = mkdir (skipcrud + current_file_name,
655 (we_are_root ? 0 : 0300) | (int) hstat.st_mode);
656 if (check != 0)
657 {
658 struct stat st1;
659
660 if (make_dirs (skipcrud + current_file_name))
661 goto again_dir;
662 /* If we're trying to create '.', let it be. */
663 if (current_file_name[skipcrud + namelen] == '.' &&
664 (namelen == 0 ||
665 current_file_name[skipcrud + namelen - 1] == '/'))
666 goto check_perms;
667 if (errno == EEXIST
668 && stat (skipcrud + current_file_name, &st1) == 0
669 && (S_ISDIR (st1.st_mode)))
670 break;
671 msg_perror ("Could not create directory %s", skipcrud + current_file_name);
672 break;
673 }
674
675 check_perms:
676 if (!we_are_root && 0300 != (0300 & (int) hstat.st_mode))
677 {
678 hstat.st_mode |= 0300;
679 msg ("Added write and execute permission to directory %s",
680 skipcrud + current_file_name);
681 }
682
683 if (f_modified)
684 goto set_filestat;
685 tmp = (struct saved_dir_info *) malloc (sizeof (struct saved_dir_info));
686 tmp->path = malloc (strlen (skipcrud + current_file_name) + 1);
687 strcpy (tmp->path, skipcrud + current_file_name);
688 tmp->mode = hstat.st_mode;
689 tmp->atime = hstat.st_atime;
690 tmp->mtime = hstat.st_mtime;
691 tmp->next = saved_dir_info_head;
692 saved_dir_info_head = tmp;
693 case LF_VOLHDR:
694 if (f_verbose)
695 {
696 printf ("Reading %s\n", current_file_name);
697 }
698 break;
699
700 case LF_NAMES:
701 extract_mangle (head);
702 break;
703
704 case LF_MULTIVOL:
705 msg ("Can't extract '%s'--file is continued from another volume\n", current_file_name);
706 skip_file ((long) hstat.st_size);
707 break;
708
709 case LF_LONGNAME:
710 case LF_LONGLINK:
711 msg ("Visible long name error\n");
712 skip_file ((long) hstat.st_size);
713 break;
714 }
715
716 /* We don't need to save it any longer. */
717 saverec ((union record **) 0);/* Unsave it */
718 }
719
720 /*
721 * After a file/link/symlink/dir creation has failed, see if
722 * it's because some required directory was not present, and if
723 * so, create all required dirs.
724 */
725 int
726 make_dirs (pathname)
727 char *pathname;
728 {
729 char *p; /* Points into path */
730 int madeone = 0; /* Did we do anything yet? */
731 int save_errno = errno; /* Remember caller's errno */
732 int check;
733
734 if (errno != ENOENT)
735 return 0; /* Not our problem */
736
737 for (p = index (pathname, '/'); p != NULL; p = index (p + 1, '/'))
738 {
739 /* Avoid mkdir of empty string, if leading or double '/' */
740 if (p == pathname || p[-1] == '/')
741 continue;
742 /* Avoid mkdir where last part of path is '.' */
743 if (p[-1] == '.' && (p == pathname + 1 || p[-2] == '/'))
744 continue;
745 *p = 0; /* Truncate the path there */
746 check = mkdir (pathname, 0777); /* Try to create it as a dir */
747 if (check == 0)
748 {
749 /* Fix ownership */
750 if (we_are_root)
751 {
752 if (chown (pathname, hstat.st_uid,
753 hstat.st_gid) < 0)
754 {
755 msg_perror ("cannot change owner of %s to uid %d gid %d", pathname, hstat.st_uid, hstat.st_gid);
756 }
757 }
758 pr_mkdir (pathname, p - pathname, notumask & 0777);
759 madeone++; /* Remember if we made one */
760 *p = '/';
761 continue;
762 }
763 *p = '/';
764 if (errno == EEXIST) /* Directory already exists */
765 continue;
766 /*
767 * Some other error in the mkdir. We return to the caller.
768 */
769 break;
770 }
771
772 errno = save_errno; /* Restore caller's errno */
773 return madeone; /* Tell them to retry if we made one */
774 }
775
776 void
777 extract_sparse_file (fd, sizeleft, totalsize, name)
778 int fd;
779 long *sizeleft, totalsize;
780 char *name;
781 {
782 /* register char *data;*/
783 union record *datarec;
784 int sparse_ind = 0;
785 int written, count;
786
787 /* assuming sizeleft is initially totalsize */
788
789
790 while (*sizeleft > 0)
791 {
792 datarec = findrec ();
793 if (datarec == NULL)
794 {
795 msg ("Unexpected EOF on archive file");
796 return;
797 }
798 lseek (fd, sparsearray[sparse_ind].offset, 0);
799 written = sparsearray[sparse_ind++].numbytes;
800 while (written > RECORDSIZE)
801 {
802 count = write (fd, datarec->charptr, RECORDSIZE);
803 if (count < 0)
804 msg_perror ("couldn't write to file %s", name);
805 written -= count;
806 *sizeleft -= count;
807 userec (datarec);
808 datarec = findrec ();
809 }
810
811 count = write (fd, datarec->charptr, written);
812
813 if (count < 0)
814 {
815 msg_perror ("couldn't write to file %s", name);
816 }
817 else if (count != written)
818 {
819 msg ("could only write %d of %d bytes to file %s", totalsize - *sizeleft, totalsize, name);
820 skip_file ((long) (*sizeleft));
821 }
822
823 written -= count;
824 *sizeleft -= count;
825 userec (datarec);
826 }
827 free (sparsearray);
828 /* if (end_nulls) {
829 register int i;
830
831 printf("%d\n", (int) end_nulls);
832 for (i = 0; i < end_nulls; i++)
833 write(fd, "\000", 1);
834 }*/
835 userec (datarec);
836 }
837
838 /* Set back the utime and mode for all the extracted directories. */
839 void
840 restore_saved_dir_info ()
841 {
842 struct utimbuf acc_upd_times;
843
844 while (saved_dir_info_head != NULL)
845 {
846 /* fixme if f_gnudump should set ctime too, but how? */
847 if (f_gnudump)
848 acc_upd_times.actime = saved_dir_info_head->atime;
849 else
850 acc_upd_times.actime = now; /* Accessed now */
851 acc_upd_times.modtime = saved_dir_info_head->mtime; /* Mod'd */
852 if (utime (saved_dir_info_head->path, &acc_upd_times) < 0)
853 {
854 msg_perror ("couldn't change access and modification times of %s",
855 saved_dir_info_head->path);
856 }
857 if ((!f_keep) || (saved_dir_info_head->mode & (S_ISUID | S_ISGID | S_ISVTX)))
858 {
859 if (chmod (saved_dir_info_head->path,
860 notumask & saved_dir_info_head->mode) < 0)
861 {
862 msg_perror ("cannot change mode of file %s to %ld",
863 saved_dir_info_head->path,
864 notumask & saved_dir_info_head->mode);
865 }
866 }
867 saved_dir_info_head = saved_dir_info_head->next;
868 }
869 }
This page took 0.067788 seconds and 5 git commands to generate.