X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=src%2Fextract.c;h=d346f79ac272a04344ed7e78ccafe55aa28a14fa;hb=a0b4431f26a72addb201c306ae02c2e12c2d5092;hp=a630bb799dea386b9f4e598a37c6b6f35baad50e;hpb=e86e864544a87003ac900d60135a3ca9424cfb95;p=chaz%2Ftar diff --git a/src/extract.c b/src/extract.c index a630bb7..d346f79 100644 --- a/src/extract.c +++ b/src/extract.c @@ -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; } @@ -1319,6 +1322,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) {