/* Miscellaneous functions, not really specific to GNU tar.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
- 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2009 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
#include <xgetcwd.h>
#include <unlinkdir.h>
#include <utimens.h>
+#include <canonicalize.h>
#if HAVE_STROPTS_H
# include <stropts.h>
*destination = '\0';
return result;
}
+
+/* Zap trailing slashes. */
+char *
+zap_slashes (char *name)
+{
+ char *q;
+
+ if (!name || *name == 0)
+ return name;
+ q = name + strlen (name) - 1;
+ while (q > name && ISSLASH (*q))
+ *q-- = '\0';
+ return name;
+}
+
+char *
+normalize_filename (const char *name)
+{
+ return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
+}
+
+\f
+void
+replace_prefix (char **pname, const char *samp, size_t slen,
+ const char *repl, size_t rlen)
+{
+ char *name = *pname;
+ size_t nlen = strlen (name);
+ if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
+ {
+ if (rlen > slen)
+ {
+ name = xrealloc (name, nlen - slen + rlen + 1);
+ *pname = name;
+ }
+ memmove (name + rlen, name + slen, nlen - slen + 1);
+ memcpy (name, repl, rlen);
+ }
+}
+
\f
/* Handling numbers. */
{
struct stat file_stat;
+ assign_string (&before_backup_name, file_name);
+
+ /* A run situation may exist between Emacs or other GNU programs trying to
+ make a backup for the same file simultaneously. If theoretically
+ possible, real problems are unlikely. Doing any better would require a
+ convention, GNU-wide, for all programs doing backups. */
+
+ assign_string (&after_backup_name, 0);
+
/* Check if we really need to backup the file. */
if (this_is_the_archive && _remdev (file_name))
&& (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
return true;
- assign_string (&before_backup_name, file_name);
-
- /* A run situation may exist between Emacs or other GNU programs trying to
- make a backup for the same file simultaneously. If theoretically
- possible, real problems are unlikely. Doing any better would require a
- convention, GNU-wide, for all programs doing backups. */
-
- assign_string (&after_backup_name, 0);
after_backup_name = find_backup_file_name (file_name, backup_type);
if (! after_backup_name)
xalloc_die ();
static struct wd *wd;
/* The number of working directories in the vector. */
-static size_t wds;
+static size_t wd_count;
/* The allocated size of the vector. */
static size_t wd_alloc;
+int
+chdir_count ()
+{
+ if (wd_count == 0)
+ return wd_count;
+ return wd_count - 1;
+}
+
/* DIR is the operand of a -C option; add it to vector of chdir targets,
and return the index of its location. */
int
chdir_arg (char const *dir)
{
- if (wds == wd_alloc)
+ if (wd_count == wd_alloc)
{
if (wd_alloc == 0)
{
else
wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
- if (! wds)
+ if (! wd_count)
{
- wd[wds].name = ".";
- wd[wds].saved = 0;
- wds++;
+ wd[wd_count].name = ".";
+ wd[wd_count].saved = 0;
+ wd_count++;
}
}
for (dir += 2; ISSLASH (*dir); dir++)
continue;
if (! dir[dir[0] == '.'])
- return wds - 1;
+ return wd_count - 1;
}
- wd[wds].name = dir;
- wd[wds].saved = 0;
- return wds++;
+ wd[wd_count].name = dir;
+ wd[wd_count].saved = 0;
+ return wd_count++;
}
/* Change to directory I. If I is 0, change to the initial working
stat_error (name);
}
+void
+file_removed_diag (const char *name, bool top_level,
+ void (*diagfn) (char const *name))
+{
+ if (!top_level && errno == ENOENT)
+ WARNOPT (WARN_FILE_REMOVED,
+ (0, 0, _("%s: File removed before we read it"),
+ quotearg_colon (name)));
+ else
+ diagfn (name);
+}
+
+void
+dir_removed_diag (const char *name, bool top_level,
+ void (*diagfn) (char const *name))
+{
+ if (!top_level && errno == ENOENT)
+ {
+ WARNOPT (WARN_FILE_REMOVED,
+ (0, 0, _("%s: Directory removed before we read it"),
+ quotearg_colon (name)));
+ if (exit_status == TAREXIT_SUCCESS)
+ exit_status = TAREXIT_DIFFERS;
+ }
+ else
+ diagfn (name);
+}
+
void
write_fatal_details (char const *name, ssize_t status, size_t size)
{
*ptr = xmalloc (size1);
return ptr_align (*ptr, alignment);
}
+