#include <xgetcwd.h>
#include <unlinkdir.h>
#include <utimens.h>
-#include <canonicalize.h>
#if HAVE_STROPTS_H
# include <stropts.h>
# include <sys/filio.h>
#endif
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+#endif
+
\f
/* Handling strings. */
return name;
}
+/* Normalize NAME by resolving any relative references and
+ removing trailing slashes. Destructive version: modifies its argument. */
+int
+normalize_filename_x (char *name)
+{
+ char *p, *q;
+
+ p = name;
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && ISSLASH (*p))
+ p++;
+
+ /* Remove /./, resolve /../ and compress sequences of slashes */
+ for (q = p; *q; )
+ {
+ if (ISSLASH (*q))
+ {
+ *p++ = *q++;
+ while (ISSLASH (*q))
+ q++;
+ continue;
+ }
+ else if (p == name)
+ {
+ if (*q == '.')
+ {
+ if (ISSLASH (q[1]))
+ {
+ q += 2;
+ continue;
+ }
+ if (q[1] == '.' && ISSLASH (q[2]))
+ return 1;
+ }
+ }
+ else
+ {
+ if (*q == '.' && ISSLASH (p[-1]))
+ {
+ if (ISSLASH (q[1]))
+ {
+ q += 2;
+ while (ISSLASH (*q))
+ q++;
+ continue;
+ }
+ else if (q[1] == '.' && ISSLASH (q[2]))
+ {
+ do
+ {
+ --p;
+ }
+ while (p > name && !ISSLASH (p[-1]));
+ q += 3;
+ continue;
+ }
+ }
+ }
+ *p++ = *q++;
+ }
+
+ /* Remove trailing slashes */
+ while (p - 1 > name && ISSLASH (p[-1]))
+ p--;
+
+ *p = 0;
+ return 0;
+}
+
+/* Normalize NAME by resolving any relative references, removing trailing
+ slashes, and converting it to absolute file name. Return the normalized
+ name, or NULL in case of error. */
+
char *
normalize_filename (const char *name)
{
- return zap_slashes (canonicalize_filename_mode (name, CAN_MISSING));
+ char *copy;
+
+ if (name[0] != '/')
+ {
+ copy = xgetcwd ();
+ copy = xrealloc (copy, strlen (copy) + strlen (name) + 2);
+
+ strcat (copy, "/");
+ strcat (copy, name);
+ }
+ else
+ copy = xstrdup (name);
+ if (normalize_filename_x (copy))
+ {
+ free (copy);
+ return NULL;
+ }
+ return xrealloc (copy, strlen (copy) + 1);
}
\f
char *np;
bool negative = s < 0;
+ /* ignore invalid values of ns */
+ if (BILLION <= ns || ns < 0)
+ ns = 0;
+
if (negative && ns != 0)
{
s++;
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)));
+ set_exit_status (TAREXIT_DIFFERS);
+ }
+ 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)));
+ set_exit_status (TAREXIT_DIFFERS);
+ }
+ else
+ diagfn (name);
+}
+
void
write_fatal_details (char const *name, ssize_t status, size_t size)
{
return ptr_align (*ptr, alignment);
}
+\f
+
+struct namebuf
+{
+ char *buffer; /* directory, `/', and directory member */
+ size_t buffer_size; /* allocated size of name_buffer */
+ size_t dir_length; /* length of directory part in buffer */
+};
+
+namebuf_t
+namebuf_create (const char *dir)
+{
+ namebuf_t buf = xmalloc (sizeof (*buf));
+ buf->buffer_size = strlen (dir) + 2;
+ buf->buffer = xmalloc (buf->buffer_size);
+ strcpy (buf->buffer, dir);
+ buf->dir_length = strlen (buf->buffer);
+ if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
+ buf->buffer[buf->dir_length++] = DIRECTORY_SEPARATOR;
+ return buf;
+}
+
+void
+namebuf_free (namebuf_t buf)
+{
+ free (buf->buffer);
+ free (buf);
+}
+
+char *
+namebuf_name (namebuf_t buf, const char *name)
+{
+ size_t len = strlen (name);
+ while (buf->dir_length + len + 1 >= buf->buffer_size)
+ buf->buffer = x2realloc (buf->buffer, &buf->buffer_size);
+ strcpy (buf->buffer + buf->dir_length, name);
+ return buf->buffer;
+}
+