X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fincremen.c;h=d570082e2bf8055ad9df6aa844a80d3dfe77ff71;hb=32562b941207be3c41589dee45f32c022785c668;hp=6cd8efb8b2ae662ce2fe058d0b3ae6af34b6293b;hpb=37724f5e203c0aa40bb0d197c55aac87a1a272c1;p=chaz%2Ftar diff --git a/src/incremen.c b/src/incremen.c index 6cd8efb..d570082 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -1,11 +1,11 @@ /* GNU dump extensions to tar. Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, - 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any later + Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but @@ -18,7 +18,6 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include -#include #include #include #include "common.h" @@ -63,6 +62,8 @@ struct directory unsigned flags; /* See DIRF_ macros above */ struct directory *orig; /* If the directory was renamed, points to the original directory structure */ + const char *tagfile; /* Tag file, if the directory falls under + exclusion_tag_under */ char name[1]; /* file name of directory */ }; @@ -125,6 +126,7 @@ make_directory (const char *name) strcpy (directory->name, name); if (ISSLASH (directory->name[namelen-1])) directory->name[namelen-1] = 0; + directory->tagfile = NULL; return directory; } @@ -230,7 +232,8 @@ static struct directory * procdir (char *name_buffer, struct stat *stat_data, dev_t device, enum children children, - bool verbose) + bool verbose, + char *entry) { struct directory *directory; bool nfs = NFS_FILE_STAT (*stat_data); @@ -331,6 +334,39 @@ procdir (char *name_buffer, struct stat *stat_data, DIR_SET_FLAG (directory, DIRF_INIT); + { + const char *tag_file_name; + + switch (check_exclusion_tags (name_buffer, &tag_file_name)) + { + case exclusion_tag_all: + /* This warning can be duplicated by code in dump_file0, but only + in case when the topmost directory being archived contains + an exclusion tag. */ + exclusion_tag_warning (name_buffer, tag_file_name, + _("directory not dumped")); + if (entry) + *entry = 'N'; + directory->children = NO_CHILDREN; + break; + + case exclusion_tag_contents: + exclusion_tag_warning (name_buffer, tag_file_name, + _("contents not dumped")); + directory->children = NO_CHILDREN; + break; + + case exclusion_tag_under: + exclusion_tag_warning (name_buffer, tag_file_name, + _("contents not dumped")); + directory->tagfile = tag_file_name; + break; + + case exclusion_tag_none: + break; + } + } + return directory; } @@ -378,7 +414,9 @@ dumpdir_size (const char *p) static int compare_dirnames (const void *first, const void *second) { - return strcmp (*(const char**)first, *(const char**)second); + char const *const *name1 = first; + char const *const *name2 = second; + return strcmp (*name1, *name2); } /* Compare dumpdir array from DIRECTORY with directory listing DIR and @@ -435,9 +473,17 @@ makedumpdir (struct directory *directory, const char *dir) const char *loc = dumpdir_locate (dump, array[i]); if (loc) { - *new_dump_ptr++ = ' '; + if (directory->tagfile) + *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ? + ' ' : 'I'; + else + *new_dump_ptr = ' '; + new_dump_ptr++; dump = loc + strlen (loc) + 1; } + else if (directory->tagfile) + *new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ? + ' ' : 'I'; else *new_dump_ptr++ = 'Y'; /* New entry */ @@ -453,22 +499,22 @@ makedumpdir (struct directory *directory, const char *dir) /* Recursively scan the given directory. */ static char * -scan_directory (char *dir_name, dev_t device) +scan_directory (char *dir, dev_t device) { - char *dirp = savedir (dir_name); /* for scanning directory */ + char *dirp = savedir (dir); /* for scanning directory */ char *name_buffer; /* directory, `/', and directory member */ size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */ size_t name_length; /* used length in name_buffer */ struct stat stat_data; struct directory *directory; - + if (! dirp) - savedir_error (dir_name); + savedir_error (dir); - name_buffer_size = strlen (dir_name) + NAME_FIELD_SIZE; + name_buffer_size = strlen (dir) + NAME_FIELD_SIZE; name_buffer = xmalloc (name_buffer_size + 2); - strcpy (name_buffer, dir_name); - if (! ISSLASH (dir_name[strlen (dir_name) - 1])) + strcpy (name_buffer, dir); + if (! ISSLASH (dir[strlen (dir) - 1])) strcat (name_buffer, "/"); name_length = strlen (name_buffer); @@ -483,8 +529,9 @@ scan_directory (char *dir_name, dev_t device) return NULL; } - directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false); - + directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false, + NULL); + if (dirp && directory->children != NO_CHILDREN) { char *entry; /* directory entry being scanned */ @@ -505,7 +552,9 @@ scan_directory (char *dir_name, dev_t device) } strcpy (name_buffer + name_length, entry + 1); - if (excluded_name (name_buffer)) + if (*entry == 'I') /* Ignored entry */ + *entry = 'N'; + else if (excluded_name (name_buffer)) *entry = 'N'; else { @@ -518,10 +567,10 @@ scan_directory (char *dir_name, dev_t device) if (S_ISDIR (stat_data.st_mode)) { + *entry = 'D'; procdir (name_buffer, &stat_data, device, directory->children, - verbose_option); - *entry = 'D'; + verbose_option, entry); } else if (one_file_system_option && device != stat_data.st_dev) @@ -550,19 +599,26 @@ scan_directory (char *dir_name, dev_t device) } char * -get_directory_contents (char *dir_name, dev_t device) +get_directory_contents (char *dir, dev_t device) { - return scan_directory (dir_name, device); + return scan_directory (dir, device); } static void obstack_code_rename (struct obstack *stk, char *from, char *to) { + char *s; + + s = from[0] == 0 ? from : + safer_name_suffix (from, false, absolute_names_option); obstack_1grow (stk, 'R'); - obstack_grow (stk, from, strlen (from) + 1); + obstack_grow (stk, s, strlen (s) + 1); + + s = to[0] == 0 ? to: + safer_name_suffix (to, false, absolute_names_option); obstack_1grow (stk, 'T'); - obstack_grow (stk, to, strlen (to) + 1); + obstack_grow (stk, s, strlen (s) + 1); } static bool @@ -575,7 +631,7 @@ rename_handler (void *data, void *proc_data) { struct directory *prev, *p; - /* Detect eventual cycles and clear DIRF_RENAMED flag, so this entries + /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries are ignored when hit by this function next time. If the chain forms a cycle, prev points to the entry DIR is renamed from. In this case it still retains DIRF_RENAMED flag, which will be @@ -1353,6 +1409,19 @@ try_purge_directory (char const *directory_name) arc += strlen (arc) + 1; dst = arc + 1; + /* Ensure that neither source nor destination are absolute file + names (unless permitted by -P option), and that they do not + contain dubious parts (e.g. ../). + + This is an extra safety precaution. Besides, it might be + necessary to extract from archives created with tar versions + prior to 1.19. */ + + if (*src) + src = safer_name_suffix (src, false, absolute_names_option); + if (*dst) + dst = safer_name_suffix (dst, false, absolute_names_option); + if (*src == 0) src = temp_stub; else if (*dst == 0) @@ -1434,6 +1503,7 @@ purge_directory (char const *directory_name) void list_dumpdir (char *buffer, size_t size) { + int state = 0; while (size) { switch (*buffer) @@ -1444,7 +1514,12 @@ list_dumpdir (char *buffer, size_t size) case 'R': case 'T': case 'X': - fprintf (stdlis, "%c ", *buffer); + fprintf (stdlis, "%c", *buffer); + if (state == 0) + { + fprintf (stdlis, " "); + state = 1; + } buffer++; size--; break; @@ -1453,6 +1528,7 @@ list_dumpdir (char *buffer, size_t size) fputc ('\n', stdlis); buffer++; size--; + state = 0; break; default: