/* 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <system.h>
-#include <getline.h>
#include <hash.h>
#include <quotearg.h>
#include "common.h"
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 */
};
strcpy (directory->name, name);
if (ISSLASH (directory->name[namelen-1]))
directory->name[namelen-1] = 0;
+ directory->tagfile = NULL;
return 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);
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;
}
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
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 */
/* 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);
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 */
}
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
{
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)
}
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);
}
\f
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
{
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
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)
void
list_dumpdir (char *buffer, size_t size)
{
+ int state = 0;
while (size)
{
switch (*buffer)
case 'R':
case 'T':
case 'X':
- fprintf (stdlis, "%c ", *buffer);
+ fprintf (stdlis, "%c", *buffer);
+ if (state == 0)
+ {
+ fprintf (stdlis, " ");
+ state = 1;
+ }
buffer++;
size--;
break;
fputc ('\n', stdlis);
buffer++;
size--;
+ state = 0;
break;
default: