X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fnames.c;h=6fc5ee5105ba68d0ceadde88b1391fa33bbeb516;hb=f30c03c934e5ba865c966cb7add6542ec5f1a68f;hp=46581e0738f5228ed542a8af4ee29e983766f44e;hpb=f364d50661977d5db6df03470e85999a88ec5981;p=chaz%2Ftar diff --git a/src/names.c b/src/names.c index 46581e0..6fc5ee5 100644 --- a/src/names.c +++ b/src/names.c @@ -20,9 +20,7 @@ #include "system.h" #include -#include #include -#include #include #include "common.h" @@ -440,7 +438,7 @@ name_gather (void) buffer->change_dir = change_dir; strcpy (buffer->name, name); buffer->next = 0; - buffer->found = 0; + buffer->found_count = 0; namelist = buffer; nametail = &namelist->next; @@ -497,7 +495,7 @@ addname (char const *string, int change_dir) name->next = 0; name->length = length; - name->found = 0; + name->found_count = 0; name->regexp = 0; /* assume not a regular expression */ name->firstch = 1; /* assume first char is literal */ name->change_dir = change_dir; @@ -566,7 +564,9 @@ name_match (const char *path) cursor = namelist_match (path, length); if (cursor) { - cursor->found = 1; /* remember it matched */ + if (!(ISSLASH (path[cursor->length]) && recursion_option) + || cursor->found_count == 0) + cursor->found_count++; /* remember it matched */ if (starting_file_option) { free (namelist); @@ -576,18 +576,18 @@ name_match (const char *path) chdir_do (cursor->change_dir); /* We got a match. */ - return 1; + return ISFOUND (cursor); } /* Filename from archive not found in namelist. If we have the whole namelist here, just return 0. Otherwise, read the next name in and - compare it. If this was the last name, namelist->found will remain - on. If not, we loop to compare the newly read name. */ + compare it. If this was the last name, namelist->found_count will + remain on. If not, we loop to compare the newly read name. */ - if (same_order_option && namelist->found) + if (same_order_option && namelist->found_count) { name_gather (); /* read one more */ - if (namelist->found) + if (namelist->found_count) return 0; } else @@ -595,14 +595,31 @@ name_match (const char *path) } } -/* Returns true if all names from the namelist were processed */ +/* Returns true if all names from the namelist were processed. + P is the stat_info of the most recently processed entry. + The decision is postponed until the next entry is read if: + + 1) P ended with a slash (i.e. it was a directory) + 2) P matches any entry from the namelist *and* represents a subdirectory + or a file lying under this entry (in the terms of directory structure). + + This is necessary to handle contents of directories. */ bool -names_done () +all_names_found (struct tar_stat_info *p) { struct name const *cursor; + size_t len; + + if (!p->file_name || occurrence_option == 0 || p->had_trailing_slash) + return false; + len = strlen (p->file_name); for (cursor = namelist; cursor; cursor = cursor->next) - if (cursor->regexp || (!cursor->found && !cursor->fake)) - return false; + { + if (cursor->regexp + || (!WASFOUND(cursor) && !cursor->fake) + || (len >= cursor->length && ISSLASH (p->file_name[cursor->length]))) + return false; + } return true; } @@ -613,10 +630,16 @@ names_notfound (void) struct name const *cursor; for (cursor = namelist; cursor; cursor = cursor->next) - if (!cursor->found && !cursor->fake) - ERROR ((0, 0, _("%s: Not found in archive"), - quotearg_colon (cursor->name))); - + if (!WASFOUND(cursor) && !cursor->fake) + { + if (cursor->found_count == 0) + ERROR ((0, 0, _("%s: Not found in archive"), + quotearg_colon (cursor->name))); + else + ERROR ((0, 0, _("%s: Required occurrence not found in archive"), + quotearg_colon (cursor->name))); + } + /* Don't bother freeing the name list; we're about to exit. */ namelist = 0; nametail = &namelist; @@ -625,7 +648,7 @@ names_notfound (void) { char *name; - while (name = name_next (1), name) + while ((name = name_next (1)) != NULL) ERROR ((0, 0, _("%s: Not found in archive"), quotearg_colon (name))); } @@ -714,7 +737,7 @@ merge_sort (struct name *list, int length, static int compare_names (struct name const *n1, struct name const *n2) { - int found_diff = n2->found - n1->found; + int found_diff = WASFOUND(n2) - WASFOUND(n1); return found_diff ? found_diff : strcmp (n1->name, n2->name); } @@ -800,7 +823,7 @@ collect_and_sort_names (void) for (name = namelist; name; name = next_name) { next_name = name->next; - if (name->found || name->dir_contents) + if (name->found_count || name->dir_contents) continue; if (name->regexp) /* FIXME: just skip regexps for now */ continue; @@ -810,15 +833,12 @@ collect_and_sort_names (void) if (deref_stat (dereference_option, name->name, &statbuf) != 0) { - if (ignore_failed_read_option) - stat_warn (name->name); - else - stat_error (name->name); + stat_diag (name->name); continue; } if (S_ISDIR (statbuf.st_mode)) { - name->found = 1; + name->found_count++; add_hierarchy_to_namelist (name, statbuf.st_dev); } } @@ -829,7 +849,7 @@ collect_and_sort_names (void) namelist = merge_sort (namelist, num_names, compare_names); for (name = namelist; name; name = name->next) - name->found = 0; + name->found_count = 0; } /* This is like name_match, except that it returns a pointer to the @@ -849,13 +869,13 @@ name_scan (const char *path) /* Filename from archive not found in namelist. If we have the whole namelist here, just return 0. Otherwise, read the next name in and - compare it. If this was the last name, namelist->found will remain - on. If not, we loop to compare the newly read name. */ + compare it. If this was the last name, namelist->found_count will + remain on. If not, we loop to compare the newly read name. */ - if (same_order_option && namelist && namelist->found) + if (same_order_option && namelist && namelist->found_count) { name_gather (); /* read one more */ - if (namelist->found) + if (namelist->found_count) return 0; } else @@ -873,11 +893,11 @@ name_from_list (void) { if (!gnu_list_name) gnu_list_name = namelist; - while (gnu_list_name && (gnu_list_name->found | gnu_list_name->fake)) + while (gnu_list_name && (gnu_list_name->found_count || gnu_list_name->fake)) gnu_list_name = gnu_list_name->next; if (gnu_list_name) { - gnu_list_name->found = 1; + gnu_list_name->found_count++; chdir_do (gnu_list_name->change_dir); return gnu_list_name->name; } @@ -891,7 +911,7 @@ blank_name_list (void) gnu_list_name = 0; for (name = namelist; name; name = name->next) - name->found = 0; + name->found_count = 0; } /* Yield a newly allocated file name consisting of PATH concatenated to @@ -1001,9 +1021,9 @@ safer_name_suffix (char const *file_name, bool link_target) for (p = file_name + prefix_len; *p; ) { - if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2])) + if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2])) prefix_len = p + 2 - file_name; - + do { char c = *p++; @@ -1047,7 +1067,7 @@ safer_name_suffix (char const *file_name, bool link_target) }; WARN ((0, 0, _(diagnostic[link_target]))); } - + p = "."; }