]>
Dogcows Code - chaz/tar/blob - src/extract.c
1 /* Extract files from a tar archive.
2 Copyright (C) 1988, 92,93,94,96,97,98, 1999 Free Software Foundation, Inc.
3 Written by John Gilmore, on 1985-11-19.
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any later
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 59 Place - Suite 330, Boston, MA 02111-1307, USA. */
36 static time_t now
; /* current time */
37 static int we_are_root
; /* true if our effective uid == 0 */
38 static mode_t newdir_umask
; /* umask when creating new directories */
39 static mode_t current_umask
; /* current umask (which is set to 0 if -p) */
42 /* "Scratch" space to store the information about a sparse file before
43 writing the info into the header or extended header. */
44 struct sp_array
*sparsearray
;
46 /* Number of elts storable in the sparsearray. */
47 int sp_array_size
= 10;
50 struct delayed_set_stat
52 struct delayed_set_stat
*next
;
54 struct stat stat_info
;
57 static struct delayed_set_stat
*delayed_set_stat_head
;
59 /*--------------------------.
60 | Set up to extract files. |
61 `--------------------------*/
66 now
= time ((time_t *) 0);
67 we_are_root
= geteuid () == 0;
69 /* Option -p clears the kernel umask, so it does not affect proper
70 restoration of file permissions. New intermediate directories will
71 comply with umask at start of program. */
73 newdir_umask
= umask (0);
74 if (same_permissions_option
)
78 umask (newdir_umask
); /* restore the kernel umask */
79 current_umask
= newdir_umask
;
82 /* FIXME: Just make sure we can add files in directories we create. Maybe
83 should we later remove permissions we are adding, here? */
84 newdir_umask
&= ~0300;
87 /*------------------------------------------------------------------.
88 | Restore mode for FILE_NAME, from information given in STAT_INFO. |
89 `------------------------------------------------------------------*/
92 set_mode (char *file_name
, struct stat
*stat_info
)
94 /* We ought to force permission when -k is not selected, because if the
95 file already existed, open or creat would save the permission bits from
96 the previously created file, ignoring the ones we specified.
98 But with -k selected, we know *we* created this file, so the mode
99 bits were set by our open. If the file has abnormal mode bits, we must
100 chmod since writing or chown has probably reset them. If the file is
101 normal, we merely skip the chmod. This works because we did umask (0)
102 when -p, so umask will have left the specified mode alone. */
104 if (!keep_old_files_option
105 || (stat_info
->st_mode
& (S_ISUID
| S_ISGID
| S_ISVTX
)))
106 if (chmod (file_name
, ~current_umask
& stat_info
->st_mode
) < 0)
107 ERROR ((0, errno
, _("%s: Cannot change mode to %0.4lo"),
109 (unsigned long) (~current_umask
& stat_info
->st_mode
)));
112 /*----------------------------------------------------------------------.
113 | Restore stat attributes (owner, group, mode and times) for FILE_NAME, |
114 | using information given in STAT_INFO. SYMLINK_FLAG is non-zero for a |
115 | freshly restored symbolic link. |
116 `----------------------------------------------------------------------*/
118 /* FIXME: About proper restoration of symbolic link attributes, we still do
119 not have it right. Pretesters' reports tell us we need further study and
120 probably more configuration. For now, just use lchown if it exists, and
121 punt for the rest. Sigh! */
124 set_stat (char *file_name
, struct stat
*stat_info
, int symlink_flag
)
126 struct utimbuf utimbuf
;
130 /* We do the utime before the chmod because some versions of utime are
131 broken and trash the modes of the file. */
135 /* We set the accessed time to `now', which is really the time we
136 started extracting files, unless incremental_option is used, in
137 which case .st_atime is used. */
139 /* FIXME: incremental_option should set ctime too, but how? */
141 if (incremental_option
)
142 utimbuf
.actime
= stat_info
->st_atime
;
144 utimbuf
.actime
= now
;
146 utimbuf
.modtime
= stat_info
->st_mtime
;
148 if (utime (file_name
, &utimbuf
) < 0)
150 _("%s: Could not change access and modification times"),
154 /* Some systems allow non-root users to give files away. Once this
155 done, it is not possible anymore to change file permissions, so we
156 have to set permissions prior to possibly giving files away. */
158 set_mode (file_name
, stat_info
);
161 /* If we are root, set the owner and group of the extracted file, so we
162 extract as the original owner. Or else, if we are running as a user,
163 leave the owner and group as they are, so we extract as that user. */
165 if (we_are_root
|| same_owner_option
)
169 /* When lchown exists, it should be used to change the attributes of
170 the symbolic link itself. In this case, a mere chown would change
171 the attributes of the file the symbolic link is pointing to, and
172 should be avoided. */
176 if (lchown (file_name
, stat_info
->st_uid
, stat_info
->st_gid
) < 0)
177 ERROR ((0, errno
, _("%s: Cannot lchown to uid %lu gid %lu"),
179 (unsigned long) stat_info
->st_uid
,
180 (unsigned long) stat_info
->st_gid
));
184 if (chown (file_name
, stat_info
->st_uid
, stat_info
->st_gid
) < 0)
185 ERROR ((0, errno
, _("%s: Cannot chown to uid %lu gid %lu"),
187 (unsigned long) stat_info
->st_uid
,
188 (unsigned long) stat_info
->st_gid
));
191 #else /* not HAVE_LCHOWN */
195 if (chown (file_name
, stat_info
->st_uid
, stat_info
->st_gid
) < 0)
196 ERROR ((0, errno
, _("%s: Cannot chown to uid %lu gid %lu"),
198 (unsigned long) stat_info
->st_uid
,
199 (unsigned long) stat_info
->st_gid
));
201 #endif/* not HAVE_LCHOWN */
205 /* On a few systems, and in particular, those allowing to give files
206 away, changing the owner or group destroys the suid or sgid bits.
207 So let's attempt setting these bits once more. */
209 if (stat_info
->st_mode
& (S_ISUID
| S_ISGID
| S_ISVTX
))
210 set_mode (file_name
, stat_info
);
214 /*-----------------------------------------------------------------------.
215 | After a file/link/symlink/directory creation has failed, see if it's |
216 | because some required directory was not present, and if so, create all |
217 | required directories. Return non-zero if a directory was created. |
218 `-----------------------------------------------------------------------*/
221 make_directories (char *file_name
)
223 char *cursor
; /* points into path */
224 int did_something
= 0; /* did we do anything yet? */
225 int saved_errno
= errno
; /* remember caller's errno */
228 for (cursor
= strchr (file_name
, '/');
230 cursor
= strchr (cursor
+ 1, '/'))
232 /* Avoid mkdir of empty string, if leading or double '/'. */
234 if (cursor
== file_name
|| cursor
[-1] == '/')
237 /* Avoid mkdir where last part of path is '.'. */
239 if (cursor
[-1] == '.' && (cursor
== file_name
+ 1 || cursor
[-2] == '/'))
242 *cursor
= '\0'; /* truncate the path there */
243 status
= mkdir (file_name
, ~newdir_umask
& 0777);
250 if (chown (file_name
, current_stat
.st_uid
, current_stat
.st_gid
) < 0)
252 _("%s: Cannot change owner to uid %lu, gid %lu"),
254 (unsigned long) current_stat
.st_uid
,
255 (unsigned long) current_stat
.st_gid
));
257 print_for_mkdir (file_name
, cursor
- file_name
,
258 ~newdir_umask
& 0777);
269 /* Turbo C mkdir gives a funny errno. */
273 /* Directory already exists. */
276 /* Some other error in the mkdir. We return to the caller. */
280 errno
= saved_errno
; /* FIXME: errno should be read-only */
281 return did_something
; /* tell them to retry if we made one */
284 /*--------------------------------------------------------------------.
285 | Attempt repairing what went wrong with the extraction. Delete an |
286 | already existing file or create missing intermediate directories. |
287 | Return nonzero if we somewhat increased our chances at a successful |
288 | extraction. errno is properly restored on zero return. |
289 `--------------------------------------------------------------------*/
292 maybe_recoverable (char *file_name
)
297 /* Attempt deleting an existing file. However, with -k, just stay
300 if (keep_old_files_option
)
303 return remove_any_file (file_name
, 0);
306 /* Attempt creating missing intermediate directories. */
308 return make_directories (file_name
);
311 /* Just say we can't do anything about it... */
322 extract_sparse_file (int fd
, off_t
*sizeleft
, off_t totalsize
, char *name
)
324 union block
*data_block
;
329 /* FIXME: `data_block' might be used uninitialized in this function.
330 Reported by Bruno Haible. */
332 /* assuming sizeleft is initially totalsize */
334 while (*sizeleft
> 0)
336 data_block
= find_next_block ();
337 if (data_block
== NULL
)
339 ERROR ((0, 0, _("Unexpected EOF on archive file")));
342 lseek (fd
, sparsearray
[sparse_ind
].offset
, 0);
343 written
= sparsearray
[sparse_ind
++].numbytes
;
344 while (written
> BLOCKSIZE
)
346 count
= write (fd
, data_block
->buffer
, BLOCKSIZE
);
348 ERROR ((0, errno
, _("%s: Could not write to file"), name
));
351 set_next_block_after (data_block
);
352 data_block
= find_next_block ();
355 count
= write (fd
, data_block
->buffer
, written
);
358 ERROR ((0, errno
, _("%s: Could not write to file"), name
));
359 else if (count
!= written
)
361 char buf1
[UINTMAX_STRSIZE_BOUND
];
362 char buf2
[UINTMAX_STRSIZE_BOUND
];
363 ERROR ((0, 0, _("%s: Could only write %s of %s bytes"),
365 STRINGIFY_BIGINT (totalsize
- *sizeleft
, buf1
),
366 STRINGIFY_BIGINT (totalsize
, buf2
)));
367 skip_file (*sizeleft
);
372 set_next_block_after (data_block
);
375 set_next_block_after (data_block
);
378 /*----------------------------------.
379 | Extract a file from the archive. |
380 `----------------------------------*/
383 extract_archive (void)
385 union block
*data_block
;
400 struct delayed_set_stat
*data
;
402 #define CURRENT_FILE_NAME (skipcrud + current_file_name)
404 set_next_block_after (current_header
);
405 decode_header (current_header
, ¤t_stat
, ¤t_format
, 1);
407 if (interactive_option
&& !confirm ("extract", current_file_name
))
409 if (current_header
->oldgnu_header
.isextended
)
410 skip_extended_headers ();
411 skip_file (current_stat
.st_size
);
415 /* Print the block from `current_header' and `current_stat'. */
420 /* Check for fully specified file names and other atrocities. */
423 while (!absolute_names_option
&& CURRENT_FILE_NAME
[0] == '/')
425 static int warned_once
= 0;
427 skipcrud
++; /* force relative path */
432 Removing leading `/' from absolute path names in the archive")));
436 /* Take a safety backup of a previously existing file. */
438 if (backup_option
&& !to_stdout_option
)
439 if (!maybe_backup_file (CURRENT_FILE_NAME
, 0))
441 ERROR ((0, errno
, _("%s: Was unable to backup this file"),
443 if (current_header
->oldgnu_header
.isextended
)
444 skip_extended_headers ();
445 skip_file (current_stat
.st_size
);
449 /* Extract the archive entry according to its type. */
451 typeflag
= current_header
->header
.typeflag
;
454 /* JK - What we want to do if the file is sparse is loop through
455 the array of sparse structures in the header and read in and
456 translate the character strings representing 1) the offset at
457 which to write and 2) how many bytes to write into numbers,
458 which we store into the scratch array, "sparsearray". This
459 array makes our life easier the same way it did in creating the
460 tar file that had to deal with a sparse file.
462 After we read in the first five (at most) sparse structures, we
463 check to see if the file has an extended header, i.e., if more
464 sparse structures are needed to describe the contents of the new
465 file. If so, we read in the extended headers and continue to
466 store their contents into the sparsearray. */
470 sparsearray
= (struct sp_array
*)
471 xmalloc (sp_array_size
* sizeof (struct sp_array
));
473 for (counter
= 0; counter
< SPARSES_IN_OLDGNU_HEADER
; counter
++)
475 sparsearray
[counter
].offset
=
476 OFF_FROM_OCT (current_header
->oldgnu_header
.sp
[counter
].offset
);
477 sparsearray
[counter
].numbytes
=
478 SIZE_FROM_OCT (current_header
->oldgnu_header
.sp
[counter
].numbytes
);
479 if (!sparsearray
[counter
].numbytes
)
483 if (current_header
->oldgnu_header
.isextended
)
485 /* Read in the list of extended headers and translate them
486 into the sparsearray as before. Note that this
487 invalidates current_header. */
489 /* static */ int ind
= SPARSES_IN_OLDGNU_HEADER
;
493 exhdr
= find_next_block ();
494 for (counter
= 0; counter
< SPARSES_IN_SPARSE_HEADER
; counter
++)
496 if (counter
+ ind
> sp_array_size
- 1)
498 /* Realloc the scratch area since we've run out of
502 sparsearray
= (struct sp_array
*)
503 xrealloc (sparsearray
,
504 sp_array_size
* (sizeof (struct sp_array
)));
506 /* Compare to 0, or use !(int)..., for Pyramid's dumb
508 if (exhdr
->sparse_header
.sp
[counter
].numbytes
== 0)
510 sparsearray
[counter
+ ind
].offset
=
511 OFF_FROM_OCT (exhdr
->sparse_header
.sp
[counter
].offset
);
512 sparsearray
[counter
+ ind
].numbytes
=
513 SIZE_FROM_OCT (exhdr
->sparse_header
.sp
[counter
].numbytes
);
515 if (!exhdr
->sparse_header
.isextended
)
519 ind
+= SPARSES_IN_SPARSE_HEADER
;
520 set_next_block_after (exhdr
);
523 set_next_block_after (exhdr
);
531 /* Appears to be a file. But BSD tar uses the convention that a slash
532 suffix means a directory. */
534 name_length
= strlen (CURRENT_FILE_NAME
) - 1;
535 if (CURRENT_FILE_NAME
[name_length
] == '/')
538 /* FIXME: deal with protection issues. */
541 openflag
= (keep_old_files_option
?
542 O_BINARY
| O_NDELAY
| O_WRONLY
| O_CREAT
| O_EXCL
:
543 O_BINARY
| O_NDELAY
| O_WRONLY
| O_CREAT
| O_TRUNC
)
544 | ((typeflag
== GNUTYPE_SPARSE
) ? 0 : O_APPEND
);
546 /* JK - The last | is a kludge to solve the problem the O_APPEND
547 flag causes with files we are trying to make sparse: when a file
548 is opened with O_APPEND, it writes to the last place that
549 something was written, thereby ignoring any lseeks that we have
550 done. We add this extra condition to make it able to lseek when
551 a file is sparse, i.e., we don't open the new file with this
552 flag. (Grump -- this bug caused me to waste a good deal of
553 time, I might add) */
555 if (to_stdout_option
)
561 if (unlink_first_option
)
562 remove_any_file (CURRENT_FILE_NAME
, recursive_unlink_option
);
565 /* Contiguous files (on the Masscomp) have to specify the size in
566 the open call that creates them. */
568 if (typeflag
== CONTTYPE
)
569 fd
= open (CURRENT_FILE_NAME
, openflag
| O_CTG
,
570 current_stat
.st_mode
, current_stat
.st_size
);
572 fd
= open (CURRENT_FILE_NAME
, openflag
, current_stat
.st_mode
);
574 #else /* not O_CTG */
575 if (typeflag
== CONTTYPE
)
577 static int conttype_diagnosed
= 0;
579 if (!conttype_diagnosed
)
581 conttype_diagnosed
= 1;
582 WARN ((0, 0, _("Extracting contiguous files as regular files")));
585 fd
= open (CURRENT_FILE_NAME
, openflag
, current_stat
.st_mode
);
587 #endif /* not O_CTG */
591 if (maybe_recoverable (CURRENT_FILE_NAME
))
594 ERROR ((0, errno
, _("%s: Could not create file"),
596 if (current_header
->oldgnu_header
.isextended
)
597 skip_extended_headers ();
598 skip_file (current_stat
.st_size
);
605 if (typeflag
== GNUTYPE_SPARSE
)
608 size_t name_length_bis
;
610 /* Kludge alert. NAME is assigned to header.name because
611 during the extraction, the space that contains the header
612 will get scribbled on, and the name will get munged, so any
613 error messages that happen to contain the filename will look
614 REAL interesting unless we do this. */
616 name_length_bis
= strlen (CURRENT_FILE_NAME
) + 1;
617 name
= (char *) xmalloc (name_length_bis
);
618 memcpy (name
, CURRENT_FILE_NAME
, name_length_bis
);
619 size
= current_stat
.st_size
;
620 extract_sparse_file (fd
, &size
, current_stat
.st_size
, name
);
623 for (size
= current_stat
.st_size
;
627 if (multi_volume_option
)
629 assign_string (&save_name
, current_file_name
);
630 save_totsize
= current_stat
.st_size
;
631 save_sizeleft
= size
;
634 /* Locate data, determine max length writeable, write it,
635 block that we have used the data, then check if the write
638 data_block
= find_next_block ();
639 if (data_block
== NULL
)
641 ERROR ((0, 0, _("Unexpected EOF on archive file")));
642 break; /* FIXME: What happens, then? */
645 /* If the file is sparse, use the sparsearray that we created
646 before to lseek into the new file the proper amount, and to
647 see how many bytes we want to write at that position. */
650 if (typeflag
== GNUTYPE_SPARSE
)
652 lseek (fd
, sparsearray
[sparse_ind
].offset
, 0);
653 written
= sparsearray
[sparse_ind
++].numbytes
;
657 written
= available_space_after (data_block
);
661 errno
= 0; /* FIXME: errno should be read-only */
662 sstatus
= write (fd
, data_block
->buffer
, written
);
664 set_next_block_after ((union block
*)
665 (data_block
->buffer
+ written
- 1));
666 if (sstatus
== written
)
669 /* Error in writing to file. Print it, skip to next file in
673 ERROR ((0, errno
, _("%s: Could not write to file"),
676 ERROR ((0, 0, _("%s: Could only write %lu of %lu bytes"),
678 (unsigned long) sstatus
,
679 (unsigned long) written
));
680 skip_file (size
- written
);
681 break; /* still do the close, mod time, chmod, etc */
684 if (multi_volume_option
)
685 assign_string (&save_name
, NULL
);
687 /* If writing to stdout, don't try to do anything to the filename;
688 it doesn't exist, or we don't want to touch it anyway. */
690 if (to_stdout_option
)
694 if (current_header
->header
.isextended
)
699 for (counter
= 0; counter
< 21; counter
++)
703 if (!exhdr
->sparse_header
.sp
[counter
].numbytes
)
705 offset
= OFF_FROM_OCT (exhdr
->sparse_header
.sp
[counter
].offset
);
707 = SIZE_FROM_OCT (exhdr
->sparse_header
.sp
[counter
].numbytes
);
708 lseek (fd
, offset
, 0);
709 sstatus
= write (fd
, data_block
->buffer
, written
);
710 if (sstatus
== written
)
718 ERROR ((0, errno
, _("%s: Error while closing"), CURRENT_FILE_NAME
));
723 set_stat (CURRENT_FILE_NAME
, ¤t_stat
, 0);
727 if (to_stdout_option
)
731 if (unlink_first_option
)
732 remove_any_file (CURRENT_FILE_NAME
, recursive_unlink_option
);
734 while (status
= symlink (current_link_name
, CURRENT_FILE_NAME
),
736 if (!maybe_recoverable (CURRENT_FILE_NAME
))
741 /* Setting the attributes of symbolic links might, on some systems,
742 change the pointed to file, instead of the symbolic link itself.
743 At least some of these systems have a lchown call, and the
744 set_stat routine knows about this. */
746 set_stat (CURRENT_FILE_NAME
, ¤t_stat
, 1);
750 ERROR ((0, errno
, _("%s: Could not create symlink to `%s'"),
751 CURRENT_FILE_NAME
, current_link_name
));
757 #else /* not S_ISLNK */
759 static int warned_once
= 0;
765 Attempting extraction of symbolic links as hard links")));
770 #endif /* not S_ISLNK */
773 if (to_stdout_option
)
776 if (unlink_first_option
)
777 remove_any_file (CURRENT_FILE_NAME
, recursive_unlink_option
);
781 struct stat st1
, st2
;
783 /* MSDOS does not implement links. However, djgpp's link() actually
785 status
= link (current_link_name
, CURRENT_FILE_NAME
);
789 if (maybe_recoverable (CURRENT_FILE_NAME
))
792 if (incremental_option
&& errno
== EEXIST
)
794 if (stat (current_link_name
, &st1
) == 0
795 && stat (CURRENT_FILE_NAME
, &st2
) == 0
796 && st1
.st_dev
== st2
.st_dev
797 && st1
.st_ino
== st2
.st_ino
)
800 ERROR ((0, errno
, _("%s: Could not link to `%s'"),
801 CURRENT_FILE_NAME
, current_link_name
));
809 current_stat
.st_mode
|= S_IFCHR
;
815 current_stat
.st_mode
|= S_IFBLK
;
818 #if defined(S_IFCHR) || defined(S_IFBLK)
820 if (to_stdout_option
)
823 if (unlink_first_option
)
824 remove_any_file (CURRENT_FILE_NAME
, recursive_unlink_option
);
826 status
= mknod (CURRENT_FILE_NAME
, current_stat
.st_mode
,
827 current_stat
.st_rdev
);
830 if (maybe_recoverable (CURRENT_FILE_NAME
))
833 ERROR ((0, errno
, _("%s: Could not make node"), CURRENT_FILE_NAME
));
838 set_stat (CURRENT_FILE_NAME
, ¤t_stat
, 0);
844 if (to_stdout_option
)
847 if (unlink_first_option
)
848 remove_any_file (CURRENT_FILE_NAME
, recursive_unlink_option
);
850 while (status
= mkfifo (CURRENT_FILE_NAME
, current_stat
.st_mode
),
852 if (!maybe_recoverable (CURRENT_FILE_NAME
))
856 set_stat (CURRENT_FILE_NAME
, ¤t_stat
, 0);
859 ERROR ((0, errno
, _("%s: Could not make fifo"), CURRENT_FILE_NAME
));
867 case GNUTYPE_DUMPDIR
:
868 name_length
= strlen (CURRENT_FILE_NAME
) - 1;
871 /* Check for trailing /, and zap as many as we find. */
872 while (name_length
&& CURRENT_FILE_NAME
[name_length
] == '/')
873 CURRENT_FILE_NAME
[name_length
--] = '\0';
875 if (incremental_option
)
877 /* Read the entry and delete files that aren't listed in the
880 gnu_restore (skipcrud
);
882 else if (typeflag
== GNUTYPE_DUMPDIR
)
883 skip_file (current_stat
.st_size
);
885 if (to_stdout_option
)
889 status
= mkdir (CURRENT_FILE_NAME
,
890 (we_are_root
? 0 : 0300) | current_stat
.st_mode
);
893 /* If the directory creation fails, let's consider immediately the
894 case where the directory already exists. We have three good
895 reasons for clearing out this case before attempting recovery.
897 1) It would not be efficient recovering the error by deleting
898 the directory in maybe_recoverable, then recreating it right
899 away. We only hope we will be able to adjust its permissions
902 2) Removing the directory might fail if it is not empty. By
903 exception, this real error is traditionally not reported.
905 3) Let's suppose `DIR' already exists and we are about to
906 extract `DIR/../DIR'. This would fail because the directory
907 already exists, and maybe_recoverable would react by removing
908 `DIR'. This then would fail again because there are missing
909 intermediate directories, and maybe_recoverable would react by
910 creating `DIR'. We would then have an extraction loop. */
915 int saved_errno
= errno
;
917 if (stat (CURRENT_FILE_NAME
, &st1
) == 0 && S_ISDIR (st1
.st_mode
))
920 errno
= saved_errno
; /* FIXME: errno should be read-only */
923 if (maybe_recoverable (CURRENT_FILE_NAME
))
926 /* If we're trying to create '.', let it be. */
928 /* FIXME: Strange style... */
930 if (CURRENT_FILE_NAME
[name_length
] == '.'
932 || CURRENT_FILE_NAME
[name_length
- 1] == '/'))
935 ERROR ((0, errno
, _("%s: Could not create directory"),
943 if (!we_are_root
&& 0300 != (0300 & current_stat
.st_mode
))
945 current_stat
.st_mode
|= 0300;
946 WARN ((0, 0, _("Added write and execute permission to directory %s"),
951 /* MSDOS does not associate timestamps with directories. In this
952 case, no need to try delaying their restoration. */
956 /* FIXME: I do not believe in this. Ignoring time stamps does not
957 alleviate the need of delaying the restoration of directories'
958 mode. Let's ponder this for a little while. */
960 set_mode (CURRENT_FILE_NAME
, ¤t_stat
);
964 data
= ((struct delayed_set_stat
*)
965 xmalloc (sizeof (struct delayed_set_stat
)));
966 data
->file_name
= xstrdup (CURRENT_FILE_NAME
);
967 data
->stat_info
= current_stat
;
968 data
->next
= delayed_set_stat_head
;
969 delayed_set_stat_head
= data
;
976 fprintf (stdlis
, _("Reading %s\n"), current_file_name
);
983 case GNUTYPE_MULTIVOL
:
985 Cannot extract `%s' -- file is continued from another volume"),
987 skip_file (current_stat
.st_size
);
992 case GNUTYPE_LONGNAME
:
993 case GNUTYPE_LONGLINK
:
994 ERROR ((0, 0, _("Visible long name error")));
995 skip_file (current_stat
.st_size
);
1002 _("Unknown file type '%c' for %s, extracted as normal file"),
1003 typeflag
, CURRENT_FILE_NAME
));
1007 #undef CURRENT_FILE_NAME
1010 /*----------------------------------------------------------------.
1011 | Set back the utime and mode for all the extracted directories. |
1012 `----------------------------------------------------------------*/
1015 apply_delayed_set_stat (void)
1017 struct delayed_set_stat
*data
;
1019 while (delayed_set_stat_head
!= NULL
)
1021 data
= delayed_set_stat_head
;
1022 delayed_set_stat_head
= delayed_set_stat_head
->next
;
1023 set_stat (data
->file_name
, &data
->stat_info
, 0);
1024 free (data
->file_name
);
This page took 0.085334 seconds and 4 git commands to generate.