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