X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fextract.c;h=15fb9f2525c20b546bcb61e5e241329ca7eba949;hb=2d2e1d411e09126a7ed82ad774e24082914a51ce;hp=c01c88d12b58d10749d4a0a6b848c7d7a6c0765c;hpb=48ce2946d97a7eea01cdde404042ad7b7c3c3151;p=chaz%2Ftar diff --git a/src/extract.c b/src/extract.c index c01c88d..15fb9f2 100644 --- a/src/extract.c +++ b/src/extract.c @@ -1,7 +1,7 @@ /* Extract files from a tar archive. Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000, - 2001, 2003, 2004, 2005 Free Software Foundation, Inc. + 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Written by John Gilmore, on 1985-11-19. @@ -392,13 +392,12 @@ static int make_directories (char *file_name) { char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (file_name); - char *cursor; /* points into the file name */ + char *cursor; /* points into the file name */ int did_something = 0; /* did we do anything yet? */ int mode; int invert_permissions; int status; - for (cursor = cursor0; *cursor; cursor++) { if (! ISSLASH (*cursor)) @@ -428,7 +427,7 @@ make_directories (char *file_name) invert_permissions is zero, because repair_delayed_set_stat may need to update the struct. */ delay_set_stat (file_name, - ¤t_stat_info /* ignored */, + ¤t_stat_info, invert_permissions, INTERDIR_PERMSTATUS); print_for_mkdir (file_name, cursor - file_name, mode); @@ -647,7 +646,7 @@ extract_dir (char *file_name, int typeflag) } if (S_ISDIR (st.st_mode)) { - mode = st.st_mode & ~ current_umask; + mode = st.st_mode; break; } } @@ -668,12 +667,16 @@ extract_dir (char *file_name, int typeflag) if (status == 0 || old_files_option == DEFAULT_OLD_FILES || old_files_option == OVERWRITE_OLD_FILES) - delay_set_stat (file_name, ¤t_stat_info, - MODE_RWX & (mode ^ current_stat_info.stat.st_mode), - (status == 0 - ? ARCHIVED_PERMSTATUS - : UNKNOWN_PERMSTATUS)); - + { + if (status == 0) + delay_set_stat (file_name, ¤t_stat_info, + MODE_RWX & (mode ^ current_stat_info.stat.st_mode), + ARCHIVED_PERMSTATUS); + else /* For an already existing directory, invert_perms must be 0 */ + delay_set_stat (file_name, ¤t_stat_info, + 0, + UNKNOWN_PERMSTATUS); + } return status; } @@ -759,26 +762,26 @@ extract_file (char *file_name, int typeflag) for (size = current_stat_info.stat.st_size; size > 0; ) { mv_size_left (size); - + /* Locate data, determine max length writeable, write it, block that we have used the data, then check if the write worked. */ - + data_block = find_next_block (); if (! data_block) { ERROR ((0, 0, _("Unexpected EOF in archive"))); break; /* FIXME: What happens, then? */ } - + written = available_space_after (data_block); - + if (written > size) written = size; errno = 0; count = full_write (fd, data_block->buffer, written); size -= written; - + set_next_block_after ((union block *) (data_block->buffer + written - 1)); if (count != written) @@ -793,7 +796,7 @@ extract_file (char *file_name, int typeflag) skip_file (size); mv_end (); - + /* If writing to stdout, don't try to do anything to the filename; it doesn't exist, or we don't want to touch it anyway. */ @@ -1027,6 +1030,13 @@ extract_mangle_wrapper (char *file_name, int typeflag) return 0; } +static int +extract_volhdr (char *file_name, int typeflag) +{ + if (verbose_option) + fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name)); + skip_member (); +} static int extract_failure (char *file_name, int typeflag) @@ -1107,9 +1117,7 @@ prepare_to_extract (char const *file_name, int typeflag, tar_extractor_t *fun) break; case GNUTYPE_VOLHDR: - if (verbose_option) - fprintf (stdlis, _("Reading %s\n"), quote (current_stat_info.file_name)); - *fun = NULL; + *fun = extract_volhdr; break; case GNUTYPE_NAMES: @@ -1174,51 +1182,36 @@ void extract_archive (void) { char typeflag; - char *file_name; tar_extractor_t fun; set_next_block_after (current_header); decode_header (current_header, ¤t_stat_info, ¤t_format, 1); - - if (interactive_option && !confirm ("extract", current_stat_info.file_name)) + if (!current_stat_info.file_name[0] + || (interactive_option + && !confirm ("extract", current_stat_info.file_name))) { skip_member (); return; } /* Print the block from current_header and current_stat. */ - if (verbose_option) print_header (¤t_stat_info, -1); - file_name = safer_name_suffix (current_stat_info.file_name, - false, absolute_names_option); - if (strip_name_components) - { - size_t prefix_len = stripped_prefix_len (file_name, - strip_name_components); - if (prefix_len == (size_t) -1) - { - skip_member (); - return; - } - file_name += prefix_len; - } - /* Restore stats for all non-ancestor directories, unless it is an incremental archive. (see NOTICE in the comment to delay_set_stat above) */ if (!delay_directory_restore_option) - apply_nonancestor_delayed_set_stat (file_name, 0); - + apply_nonancestor_delayed_set_stat (current_stat_info.file_name, 0); + /* Take a safety backup of a previously existing file. */ if (backup_option) - if (!maybe_backup_file (file_name, 0)) + if (!maybe_backup_file (current_stat_info.file_name, 0)) { int e = errno; ERROR ((0, e, _("%s: Was unable to backup this file"), - quotearg_colon (file_name))); + quotearg_colon (current_stat_info.file_name))); skip_member (); return; } @@ -1228,9 +1221,10 @@ extract_archive (void) typeflag = sparse_member_p (¤t_stat_info) ? GNUTYPE_SPARSE : current_header->header.typeflag; - if (prepare_to_extract (file_name, typeflag, &fun)) + if (prepare_to_extract (current_stat_info.file_name, typeflag, &fun)) { - if (fun && (*fun) (file_name, typeflag) && backup_option) + if (fun && (*fun) (current_stat_info.file_name, typeflag) + && backup_option) undo_last_backup (); } else @@ -1319,6 +1313,39 @@ extract_finish (void) apply_nonancestor_delayed_set_stat ("", 1); } +bool +rename_directory (char *src, char *dst) +{ + if (rename (src, dst)) + { + int e = errno; + + switch (e) + { + case ENOENT: + if (make_directories (dst)) + { + if (rename (src, dst) == 0) + return true; + e = errno; + } + break; + + case EXDEV: + /* FIXME: Fall back to recursive copying */ + + default: + break; + } + + ERROR ((0, e, _("Cannot rename %s to %s"), + quote_n (0, src), + quote_n (1, dst))); + return false; + } + return true; +} + void fatal_exit (void) {