/* Various processing of names.
- Copyright 1988, 92, 94, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+
+ Copyright 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001 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
{
if (counter == name_buffer_length)
{
- name_buffer_length += NAME_FIELD_SIZE;
+ if (name_buffer_length * 2 < name_buffer_length)
+ xalloc_die ();
+ name_buffer_length *= 2;
name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
}
name_buffer[counter++] = character;
if (counter == name_buffer_length)
{
- name_buffer_length += NAME_FIELD_SIZE;
+ if (name_buffer_length * 2 < name_buffer_length)
+ xalloc_die ();
+ name_buffer_length *= 2;
name_buffer = xrealloc (name_buffer, name_buffer_length + 2);
}
name_buffer[counter] = '\0';
}
else
{
+ size_t source_len;
source = name_array[name_index++];
- if (strlen (source) > name_buffer_length)
+ source_len = strlen (source);
+ if (name_buffer_length < source_len)
{
+ do
+ {
+ name_buffer_length *= 2;
+ if (! name_buffer_length)
+ xalloc_die ();
+ }
+ while (name_buffer_length < source_len);
+
free (name_buffer);
- name_buffer_length = strlen (source);
name_buffer = xmalloc (name_buffer_length + 2);
}
strcpy (name_buffer, source);
/* Zap trailing slashes. */
cursor = name_buffer + strlen (name_buffer) - 1;
- while (cursor > name_buffer && *cursor == '/')
+ while (cursor > name_buffer && ISSLASH (*cursor))
*cursor-- = '\0';
if (chdir_flag)
{
/* Buffer able to hold a single name. */
static struct name *buffer;
- static size_t allocated_length;
+ static size_t allocated_size;
char const *name;
{
static int change_dir;
- if (allocated_length == 0)
+ if (allocated_size == 0)
{
- allocated_length = sizeof (struct name) + NAME_FIELD_SIZE;
- buffer = xmalloc (allocated_length);
+ allocated_size = offsetof (struct name, name) + NAME_FIELD_SIZE + 1;
+ buffer = xmalloc (allocated_size);
/* FIXME: This memset is overkill, and ugly... */
- memset (buffer, 0, allocated_length);
+ memset (buffer, 0, allocated_size);
}
while ((name = name_next (0)) && strcmp (name, "-C") == 0)
if (name)
{
+ size_t needed_size;
buffer->length = strlen (name);
- if (sizeof (struct name) + buffer->length >= allocated_length)
+ needed_size = offsetof (struct name, name) + buffer->length + 1;
+ if (allocated_size < needed_size)
{
- allocated_length = sizeof (struct name) + buffer->length;
- buffer = xrealloc (buffer, allocated_length);
+ do
+ {
+ allocated_size *= 2;
+ if (! allocated_size)
+ xalloc_die ();
+ }
+ while (allocated_size < needed_size);
+
+ buffer = xrealloc (buffer, allocated_size);
}
buffer->change_dir = change_dir;
- memcpy (buffer->name, name, buffer->length + 1);
+ strcpy (buffer->name, name);
buffer->next = 0;
buffer->found = 0;
struct name *
addname (char const *string, int change_dir)
{
- struct name *name;
- size_t length;
-
- length = string ? strlen (string) : 0;
- name = xmalloc (sizeof (struct name) + length);
- memset (name, 0, sizeof (struct name) + length);
- name->next = 0;
+ size_t length = string ? strlen (string) : 0;
+ struct name *name = xmalloc (offsetof (struct name, name) + length + 1);
if (string)
{
name->fake = 0;
- name->length = length;
- memcpy (name->name, string, length + 1);
+ strcpy (name->name, string);
}
else
- name->fake = 1;
+ {
+ name->fake = 1;
+ /* FIXME: This initialization (and the byte of memory that it
+ initializes) is probably not needed, but we are currently in
+ bug-fix mode so we'll leave it in for now. */
+ name->name[0] = 0;
+ }
+
+ name->next = 0;
+ name->length = length;
name->found = 0;
name->regexp = 0; /* assume not a regular expression */
name->firstch = 1; /* assume first char is literal */
return name;
}
+/* Find a match for PATH (whose string length is LENGTH) in the name
+ list. */
+static struct name *
+namelist_match (char const *path, size_t length)
+{
+ struct name *p;
+
+ for (p = namelist; p; p = p->next)
+ {
+ /* If first chars don't match, quick skip. */
+
+ if (p->firstch && p->name[0] != path[0])
+ continue;
+
+ if (p->regexp
+ ? fnmatch (p->name, path, recursion_option) == 0
+ : (p->length <= length
+ && (path[p->length] == '\0' || ISSLASH (path[p->length]))
+ && memcmp (path, p->name, p->length) == 0))
+ return p;
+ }
+
+ return 0;
+}
+
/* Return true if and only if name PATH (from an archive) matches any
name from the namelist. */
int
return ! files_from_option;
}
- for (; cursor; cursor = cursor->next)
+ cursor = namelist_match (path, length);
+ if (cursor)
{
- /* If first chars don't match, quick skip. */
-
- if (cursor->firstch && cursor->name[0] != path[0])
- continue;
-
- if (cursor->regexp
- ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
- : (cursor->length <= length
- && (path[cursor->length] == '\0'
- || path[cursor->length] == '/')
- && memcmp (path, cursor->name, cursor->length) == 0))
+ cursor->found = 1; /* remember it matched */
+ if (starting_file_option)
{
- cursor->found = 1; /* remember it matched */
- if (starting_file_option)
- {
- free (namelist);
- namelist = 0;
- nametail = &namelist;
- }
- chdir_do (cursor->change_dir);
-
- /* We got a match. */
- return 1;
+ free (namelist);
+ namelist = 0;
+ nametail = &namelist;
}
+ chdir_do (cursor->change_dir);
+
+ /* We got a match. */
+ return 1;
}
/* Filename from archive not found in namelist. If we have the whole
void
names_notfound (void)
{
- struct name *cursor;
- struct name *next;
+ struct name const *cursor;
- for (cursor = namelist; cursor; cursor = next)
- {
- next = cursor->next;
- if (!cursor->found && !cursor->fake)
- ERROR ((0, 0, _("%s: Not found in archive"),
- quotearg_colon (cursor->name)));
+ for (cursor = namelist; cursor; cursor = cursor->next)
+ if (!cursor->found && !cursor->fake)
+ ERROR ((0, 0, _("%s: Not found in archive"),
+ quotearg_colon (cursor->name)));
- /* We could free the list, but the process is about to die anyway, so
- save some CPU time. Amigas and other similarly broken software
- will need to waste the time, though. */
-
-#ifdef amiga
- if (!same_order_option)
- free (cursor);
-#endif
- }
+ /* Don't bother freeing the name list; we're about to exit. */
namelist = 0;
nametail = &namelist;
}
\f
/* Add all the dirs under NAME, which names a directory, to the namelist.
- DIRSIZE is the size of the directory, or -1 if not known.
If any of the files is a directory, recurse on the subdirectory.
DEVICE is the device not to leave, if the -l option is specified. */
static void
-add_hierarchy_to_namelist (struct name *name, off_t dirsize, dev_t device)
+add_hierarchy_to_namelist (struct name *name, dev_t device)
{
char *path = name->name;
- char *buffer = get_directory_contents (path, dirsize, device);
+ char *buffer = get_directory_contents (path, device);
if (! buffer)
name->dir_contents = "\0\0\0\0";
name->dir_contents = buffer;
strcpy (name_buffer, path);
- if (name_buffer[name_length - 1] != '/')
+ if (! ISSLASH (name_buffer[name_length - 1]))
{
name_buffer[name_length++] = '/';
name_buffer[name_length] = '\0';
string_length = strlen (string);
if (*string == 'D')
{
- if (name_length + string_length >= allocated_length)
+ if (allocated_length <= name_length + string_length)
{
- while (name_length + string_length >= allocated_length)
- allocated_length += NAME_FIELD_SIZE;
+ do
+ {
+ allocated_length *= 2;
+ if (! allocated_length)
+ xalloc_die ();
+ }
+ while (allocated_length <= name_length + string_length);
+
name_buffer = xrealloc (name_buffer, allocated_length + 1);
}
strcpy (name_buffer + name_length, string + 1);
add_hierarchy_to_namelist (addname (name_buffer, change_dir),
- -1, device);
+ device);
}
}
if (deref_stat (dereference_option, name->name, &statbuf) != 0)
{
- stat_error (name->name);
+ if (ignore_failed_read_option)
+ stat_warn (name->name);
+ else
+ stat_error (name->name);
continue;
}
if (S_ISDIR (statbuf.st_mode))
{
name->found = 1;
- add_hierarchy_to_namelist (name, statbuf.st_size, statbuf.st_dev);
+ add_hierarchy_to_namelist (name, statbuf.st_dev);
}
}
while (1)
{
- struct name *cursor = namelist;
-
- if (!cursor)
- return 0;
-
- for (; cursor; cursor = cursor->next)
- {
- /* If first chars don't match, quick skip. */
-
- if (cursor->firstch && cursor->name[0] != path[0])
- continue;
-
- if (cursor->regexp
- ? fnmatch (cursor->name, path, FNM_LEADING_DIR) == 0
- : (cursor->length <= length
- && (path[cursor->length] == '\0'
- || path[cursor->length] == '/')
- && memcmp (path, cursor->name, cursor->length) == 0))
- return cursor; /* we got a match */
- }
+ struct name *cursor = namelist_match (path, length);
+ if (cursor)
+ return 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. */
- if (same_order_option && namelist->found)
+ if (same_order_option && namelist && namelist->found)
{
name_gather (); /* read one more */
if (namelist->found)
{
size_t pathlen = strlen (path);
size_t namesize = strlen (name) + 1;
- int slash = pathlen && path[pathlen - 1] != '/';
+ int slash = pathlen && ! ISSLASH (path[pathlen - 1]);
char *buffer = xmalloc (pathlen + slash + namesize);
memcpy (buffer, path, pathlen);
buffer[pathlen] = '/';
/* Return nonzero if file NAME is excluded. Exclude a name if its
prefix matches a pattern that contains slashes, or if one of its
components matches a pattern that contains no slashes. */
-int
+bool
excluded_name (char const *name)
{
- char const *p;
- name += FILESYSTEM_PREFIX_LEN (name);
-
- if (excluded_filename (excluded_with_slash, name,
- FNM_FILE_NAME | FNM_LEADING_DIR))
- return 1;
-
- for (p = name; *p; p++)
- if (((p == name || ISSLASH (p[-1])) && !ISSLASH (p[0]))
- && excluded_filename (excluded_without_slash, p,
- FNM_FILE_NAME | FNM_LEADING_DIR))
- return 1;
-
- return 0;
+ return excluded_filename (excluded, name + FILESYSTEM_PREFIX_LEN (name));
}
\f
/* Names to avoid dumping. */