You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
- 59 Place - Suite 330, Boston, MA 02111-1307, USA. */
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "system.h"
char name[1];
};
-struct link *linklist = NULL; /* points to first link in list */
+static struct link *linklist; /* points to first link in list */
\f
-
-/*------------------------------------------------------------------------.
-| Convert VALUE (with substitute SUBSTITUTE if VALUE is out of range) |
-| into a size-SIZE field at WHERE, including a |
-| trailing space. For example, 3 for SIZE means two digits and a space. |
-| |
-| We assume the trailing NUL is already there and don't fill it in. This |
-| fact is used by start_header and finish_header, so don't change it! |
-`------------------------------------------------------------------------*/
-
-/* Output VALUE in octal, using SUBSTITUTE if value won't fit.
+/* Base 64 digits; see Internet RFC 2045 Table 1. */
+char const base_64_digits[64] =
+{
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+};
+#define base_8_digits (base_64_digits + 26 * 2)
+
+/* The maximum uintmax_t value that can be represented with DIGITS digits,
+ assuming that each digit is BITS_PER_DIGIT wide. */
+#define MAX_VAL_WITH_DIGITS(digits, bits_per_digit) \
+ ((digits) * (bits_per_digit) < sizeof (uintmax_t) * CHAR_BIT \
+ ? ((uintmax_t) 1 << ((digits) * (bits_per_digit))) - 1 \
+ : (uintmax_t) -1)
+
+/* Convert VALUE to a representation suitable for tar headers,
+ using base 1 << BITS_PER_DIGIT.
+ Use the digits in DIGIT_CHAR[0] ... DIGIT_CHAR[base - 1].
Output to buffer WHERE with size SIZE.
- TYPE is the kind of value being output (useful for diagnostics).
- Prefer SIZE - 1 octal digits (with leading '0's), followed by '\0';
- but if SIZE octal digits would fit, omit the '\0'. */
+ The result is undefined if SIZE is 0 or if VALUE is too large to fit. */
static void
-to_oct (uintmax_t value, uintmax_t substitute, char *where, size_t size, const char *type)
+to_base (uintmax_t value, int bits_per_digit, char const *digit_char,
+ char *where, size_t size)
{
uintmax_t v = value;
size_t i = size;
+ unsigned digit_mask = (1 << bits_per_digit) - 1;
-# define MAX_OCTAL_VAL_WITH_DIGITS(digits) \
- ((digits) * 3 < sizeof (uintmax_t) * CHAR_BIT \
- ? ((uintmax_t) 1 << ((digits) * 3)) - 1 \
- : (uintmax_t) -1)
+ do
+ {
+ where[--i] = digit_char[v & digit_mask];
+ v >>= bits_per_digit;
+ }
+ while (i);
+}
- /* Output a trailing NUL unless the value is too large. */
- if (value <= MAX_OCTAL_VAL_WITH_DIGITS (size - 1))
- where[--i] = '\0';
+/* NEGATIVE is nonzero if VALUE was negative before being cast to
+ uintmax_t; its original bitpattern can be deduced from VALSIZE, its
+ original size before casting. Convert VALUE to external form,
+ using SUBSTITUTE (...) if VALUE won't fit. Output to buffer WHERE
+ with size SIZE. TYPE is the kind of value being output (useful for
+ diagnostics). Prefer the POSIX format of SIZE - 1 octal digits
+ (with leading zero digits), followed by '\0'. If this won't work,
+ and if GNU format is allowed, use '+' or '-' followed by SIZE - 1
+ base-64 digits. If neither format works, use SUBSTITUTE (...)
+ instead. Pass to SUBSTITUTE the address of an 0-or-1 flag
+ recording whether the substitute value is negative. */
- /* Produce the digits -- at least one. */
+static void
+to_chars (int negative, uintmax_t value, size_t valsize,
+ uintmax_t (*substitute) PARAMS ((int *)),
+ char *where, size_t size, const char *type)
+{
+ uintmax_t v = negative ? -value : value;
- do
+ /* Generate the POSIX octal representation if the number fits. */
+ if (! negative && v <= MAX_VAL_WITH_DIGITS (size - 1, LG_8))
{
- where[--i] = '0' + (int) (v & 7); /* one octal digit */
- v >>= 3;
+ where[size - 1] = '\0';
+ to_base (v, LG_8, base_8_digits, where, size - 1);
}
- while (i != 0 && v != 0);
- /* Leading zeros, if necessary. */
- while (i != 0)
- where[--i] = '0';
+ /* Otherwise, generate the GNU base-64 representation if we are
+ generating an old or new GNU format and if the number fits. */
+ else if (v <= MAX_VAL_WITH_DIGITS (size - 1, LG_64)
+ && (archive_format == GNU_FORMAT
+ || archive_format == OLDGNU_FORMAT))
+ {
+ where[0] = negative ? '-' : '+';
+ to_base (v, LG_64, base_64_digits, where + 1, size - 1);
+ }
- if (v != 0)
+ /* Otherwise, if the number is negative, and if it would not cause
+ ambiguity on this host by confusing positive with negative
+ values, then generate the POSIX octal representation of the value
+ modulo 2**(field bits). The resulting tar file is
+ machine-dependent, since it depends on the host word size. Yuck!
+ But this is the traditional behavior. */
+ else if (negative && valsize * CHAR_BIT <= (size - 1) * LG_8)
+ {
+ where[size - 1] = '\0';
+ to_base (value & MAX_VAL_WITH_DIGITS (valsize * CHAR_BIT, 1),
+ LG_8, base_8_digits, where, size - 1);
+ }
+
+ /* Otherwise, output a substitute value if possible (with a
+ warning), and an error message if not. */
+ else
{
- uintmax_t maxval = MAX_OCTAL_VAL_WITH_DIGITS (size);
- char buf1[UINTMAX_STRSIZE_BOUND];
- char buf2[UINTMAX_STRSIZE_BOUND];
- char buf3[UINTMAX_STRSIZE_BOUND];
- char *value_string = STRINGIFY_BIGINT (value, buf1);
- char *maxval_string = STRINGIFY_BIGINT (maxval, buf2);
+ uintmax_t maxval = (archive_format == GNU_FORMAT
+ ? MAX_VAL_WITH_DIGITS (size - 1, LG_64)
+ : MAX_VAL_WITH_DIGITS (size - 1, LG_8));
+ char buf1[UINTMAX_STRSIZE_BOUND + 1];
+ char buf2[UINTMAX_STRSIZE_BOUND + 1];
+ char buf3[UINTMAX_STRSIZE_BOUND + 1];
+ char *value_string = STRINGIFY_BIGINT (v, buf1 + 1);
+ char *maxval_string = STRINGIFY_BIGINT (maxval, buf2 + 1);
+ char const *minval_string =
+ (archive_format == GNU_FORMAT
+ ? "0"
+ : (maxval_string[-1] = '-', maxval_string - 1));
+ if (negative)
+ *--value_string = '-';
if (substitute)
{
- substitute &= maxval;
- WARN ((0, 0, _("%s value %s too large (max=%s); substituting %s"),
- type, value_string, maxval_string,
- STRINGIFY_BIGINT (substitute, buf3)));
- to_oct (substitute, (uintmax_t) 0, where, size, type);
+ int negsub;
+ uintmax_t sub = substitute (&negsub) & maxval;
+ uintmax_t s = (negsub &= archive_format == GNU_FORMAT) ? -sub : sub;
+ char *sub_string = STRINGIFY_BIGINT (s, buf3 + 1);
+ if (negsub)
+ *--sub_string = '-';
+ WARN ((0, 0, _("value %s out of %s range %s..%s; substituting %s"),
+ value_string, type, minval_string, maxval_string,
+ sub_string));
+ to_chars (negsub, s, valsize, 0, where, size, type);
}
else
- ERROR ((0, 0, _("%s value %s too large (max=%s)"),
- type, value_string, maxval_string));
+ ERROR ((0, 0, _("value %s out of %s range %s..%s"),
+ value_string, type, minval_string, maxval_string));
}
}
-#ifndef GID_NOBODY
-#define GID_NOBODY 0
+
+static uintmax_t
+gid_substitute (int *negative)
+{
+ gid_t r;
+#ifdef GID_NOBODY
+ r = GID_NOBODY;
+#else
+ static gid_t gid_nobody;
+ if (!gid_nobody && !gname_to_gid ("nobody", &gid_nobody))
+ gid_nobody = -2;
+ r = gid_nobody;
#endif
+ *negative = r < 0;
+ return r;
+}
+
void
-gid_to_oct (gid_t v, char *p, size_t s)
+gid_to_chars (gid_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) GID_NOBODY, p, s, "gid_t");
+ to_chars (v < 0, (uintmax_t) v, sizeof v, gid_substitute, p, s, "gid_t");
}
+
void
-major_to_oct (major_t v, char *p, size_t s)
+major_to_chars (major_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "major_t");
+ to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "major_t");
}
+
void
-minor_to_oct (minor_t v, char *p, size_t s)
+minor_to_chars (minor_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "minor_t");
+ to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "minor_t");
}
+
void
-mode_to_oct (mode_t v, char *p, size_t s)
+mode_to_chars (mode_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "mode_t");
+ /* In the common case where the internal and external mode bits are the same,
+ propagate all unknown bits to the external mode.
+ This matches historical practice.
+ Otherwise, just copy the bits we know about. */
+ int negative;
+ uintmax_t u;
+ if (S_ISUID == TSUID && S_ISGID == TSGID && S_ISVTX == TSVTX
+ && S_IRUSR == TUREAD && S_IWUSR == TUWRITE && S_IXUSR == TUEXEC
+ && S_IRGRP == TGREAD && S_IWGRP == TGWRITE && S_IXGRP == TGEXEC
+ && S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC)
+ {
+ negative = v < 0;
+ u = v;
+ }
+ else
+ {
+ negative = 0;
+ u = ((v & S_ISUID ? TSUID : 0)
+ | (v & S_ISGID ? TSGID : 0)
+ | (v & S_ISVTX ? TSVTX : 0)
+ | (v & S_IRUSR ? TUREAD : 0)
+ | (v & S_IWUSR ? TUWRITE : 0)
+ | (v & S_IXUSR ? TUEXEC : 0)
+ | (v & S_IRGRP ? TGREAD : 0)
+ | (v & S_IWGRP ? TGWRITE : 0)
+ | (v & S_IXGRP ? TGEXEC : 0)
+ | (v & S_IROTH ? TOREAD : 0)
+ | (v & S_IWOTH ? TOWRITE : 0)
+ | (v & S_IXOTH ? TOEXEC : 0));
+ }
+ to_chars (negative, u, sizeof v, 0, p, s, "mode_t");
}
+
void
-off_to_oct (off_t v, char *p, size_t s)
+off_to_chars (off_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "off_t");
+ to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "off_t");
}
+
void
-size_to_oct (size_t v, char *p, size_t s)
+size_to_chars (size_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "size_t");
+ to_chars (0, (uintmax_t) v, sizeof v, 0, p, s, "size_t");
}
+
void
-time_to_oct (time_t v, char *p, size_t s)
+time_to_chars (time_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) 0, p, s, "time_t");
+ to_chars (v < 0, (uintmax_t) v, sizeof v, 0, p, s, "time_t");
}
-#ifndef UID_NOBODY
-#define UID_NOBODY 0
+
+static uintmax_t
+uid_substitute (int *negative)
+{
+ uid_t r;
+#ifdef UID_NOBODY
+ r = UID_NOBODY;
+#else
+ static uid_t uid_nobody;
+ if (!uid_nobody && !uname_to_uid ("nobody", &uid_nobody))
+ uid_nobody = -2;
+ r = uid_nobody;
#endif
+ *negative = r < 0;
+ return r;
+}
+
void
-uid_to_oct (uid_t v, char *p, size_t s)
+uid_to_chars (uid_t v, char *p, size_t s)
{
- to_oct ((uintmax_t) v, (uintmax_t) UID_NOBODY, p, s, "uid_t");
+ to_chars (v < 0, (uintmax_t) v, sizeof v, uid_substitute, p, s, "uid_t");
}
+
void
-uintmax_to_oct (uintmax_t v, char *p, size_t s)
+uintmax_to_chars (uintmax_t v, char *p, size_t s)
{
- to_oct (v, (uintmax_t) 0, p, s, "uintmax_t");
+ to_chars (0, v, sizeof v, 0, p, s, "uintmax_t");
}
\f
/* Writing routines. */
}
/*-------------------------------------------------------------------------.
-| Write the EOT block(s). We actually zero at least one block, through |
+| Write the EOT block(s). We zero at least two blocks, through |
| the end of the record. Old tar, as previous versions of GNU tar, writes |
| garbage after two zeroed blocks. |
`-------------------------------------------------------------------------*/
write_eot (void)
{
union block *pointer = find_next_block ();
-
- if (pointer)
- {
- size_t space = available_space_after (pointer);
-
- memset (pointer->buffer, 0, space);
- set_next_block_after (pointer);
- }
+ memset (pointer->buffer, 0, BLOCKSIZE);
+ set_next_block_after (pointer);
+ pointer = find_next_block ();
+ memset (pointer->buffer, 0, available_space_after (pointer));
+ set_next_block_after (pointer);
}
/*-----------------------------------------------------.
/*---------------------------------------------------------------------.
| Make a header block for the file name whose stat info is st. Return |
-| header pointer for success, NULL if the name is too long. |
+| header pointer for success, zero if the name is too long. |
`---------------------------------------------------------------------*/
static union block *
if (!absolute_names_option)
{
- static int warned_once = 0;
+ size_t prefix_len = FILESYSTEM_PREFIX_LEN (name);
-#if MSDOS
- if (name[1] == ':')
+ if (prefix_len)
{
- name += 2;
+ static int warned_once;
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("Removing drive spec from names in the archive")));
+ WARN ((0, 0, _("Removing `%.*s' prefix from archive names"),
+ (int) prefix_len, name));
}
+ name += prefix_len;
}
-#endif
while (*name == '/')
{
- name++; /* force relative path */
+ static int warned_once;
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("\
-Removing leading `/' from absolute path names in the archive")));
+ WARN ((0, 0, _("Removing leading `/' from archive names")));
}
+ name++;
}
}
/* Check the file name and put it in the block. */
- if (strlen (name) >= (size_t) NAME_FIELD_SIZE)
+ if (sizeof header->header.name <= strlen (name))
write_long (name, GNUTYPE_LONGNAME);
header = find_next_block ();
memset (header->buffer, 0, sizeof (union block));
if (group_option != (gid_t) -1)
st->st_gid = group_option;
if (mode_option)
- st->st_mode = ((st->st_mode & S_IFMT)
+ st->st_mode = ((st->st_mode & ~MODE_ALL)
| mode_adjust (st->st_mode, mode_option));
/* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
acceptor for Paul's test. */
if (archive_format == V7_FORMAT)
- MODE_TO_OCT (st->st_mode & 07777, header->header.mode);
+ MODE_TO_CHARS (st->st_mode & MODE_ALL, header->header.mode);
else
- MODE_TO_OCT (st->st_mode, header->header.mode);
+ MODE_TO_CHARS (st->st_mode, header->header.mode);
- UID_TO_OCT (st->st_uid, header->header.uid);
- GID_TO_OCT (st->st_gid, header->header.gid);
- OFF_TO_OCT (st->st_size, header->header.size);
- TIME_TO_OCT (st->st_mtime, header->header.mtime);
+ UID_TO_CHARS (st->st_uid, header->header.uid);
+ GID_TO_CHARS (st->st_gid, header->header.gid);
+ OFF_TO_CHARS (st->st_size, header->header.size);
+ TIME_TO_CHARS (st->st_mtime, header->header.mtime);
if (incremental_option)
if (archive_format == OLDGNU_FORMAT)
{
- TIME_TO_OCT (st->st_atime, header->oldgnu_header.atime);
- TIME_TO_OCT (st->st_ctime, header->oldgnu_header.ctime);
+ TIME_TO_CHARS (st->st_atime, header->oldgnu_header.atime);
+ TIME_TO_CHARS (st->st_ctime, header->oldgnu_header.ctime);
}
header->header.typeflag = archive_format == V7_FORMAT ? AREGTYPE : REGTYPE;
switch (archive_format)
{
- case DEFAULT_FORMAT:
case V7_FORMAT:
break;
strncpy (header->header.magic, TMAGIC, TMAGLEN);
strncpy (header->header.version, TVERSION, TVERSLEN);
break;
+
+ default:
+ abort ();
}
if (archive_format == V7_FORMAT || numeric_owner_option)
int sum;
char *p;
- memcpy (header->header.chksum, CHKBLANKS, sizeof (header->header.chksum));
+ memcpy (header->header.chksum, CHKBLANKS, sizeof header->header.chksum);
sum = 0;
p = header->buffer;
- for (i = sizeof (*header); i-- != 0; )
+ for (i = sizeof *header; i-- != 0; )
/* We can't use unsigned char here because of old compilers, e.g. V7. */
sum += 0xFF & *p++;
/* Fill in the checksum field. It's formatted differently from the
other fields: it has [6] digits, a null, then a space -- rather than
- digits, then a null. We use to_oct.
- The final space is already there, from checksumming,
- and to_oct doesn't modify it.
+ digits, then a null. We use to_chars.
+ The final space is already there, from
+ checksumming, and to_chars doesn't modify it.
This is a fast way to do:
sprintf(header->header.chksum, "%6o", sum); */
- uintmax_to_oct ((uintmax_t) sum, header->header.chksum, 7);
+ uintmax_to_chars ((uintmax_t) sum, header->header.chksum, 7);
set_next_block_after (header);
/* Make room for our scratch space -- initially is 10 elts long. */
- sparsearray = (struct sp_array *)
- xmalloc (sp_array_size * sizeof (struct sp_array));
+ sparsearray = xmalloc (sp_array_size * sizeof (struct sp_array));
for (counter = 0; counter < sp_array_size; counter++)
{
sparsearray[counter].offset = 0;
init_sparsearray ();
clear_buffer (buffer);
- while (count = read (file, buffer, sizeof buffer), count != 0)
+ while (count = safe_read (file, buffer, sizeof buffer), count != 0)
{
/* Realloc the scratch area as necessary. FIXME: should reallocate
only at beginning of a new instance of non-zero data. */
if (sparse_index > sp_array_size - 1)
{
-
- sparsearray = (struct sp_array *)
+ sparsearray =
xrealloc (sparsearray,
2 * sp_array_size * sizeof (struct sp_array));
sp_array_size *= 2;
break;
}
- if (lseek (file, sparsearray[sparse_index++].offset, 0) < 0)
+ if (lseek (file, sparsearray[sparse_index++].offset, SEEK_SET) < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
ERROR ((0, errno, _("lseek error at byte %s in file %s"),
#if 0
if (amount_read)
{
- count = read (file, start->buffer + amount_read,
- BLOCKSIZE - amount_read);
+ count = safe_read (file, start->buffer + amount_read,
+ BLOCKSIZE - amount_read);
bufsize -= BLOCKSIZE - amount_read;
amount_read = 0;
set_next_block_after (start);
#endif
/* Store the data. */
- count = read (file, start->buffer, BLOCKSIZE);
+ count = safe_read (file, start->buffer, BLOCKSIZE);
if (count < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
- ERROR ((0, errno, _("\
-Read error at byte %s, reading %lu bytes, in file %s"),
+ ERROR ((0, errno,
+ _("Read error at byte %s, reading %lu bytes, in file %s"),
STRINGIFY_BIGINT (fullsize - *sizeleft, buf),
(unsigned long) bufsize, name));
return 1;
char buffer[BLOCKSIZE];
clear_buffer (buffer);
- count = read (file, buffer, bufsize);
+ count = safe_read (file, buffer, bufsize);
memcpy (start->buffer, buffer, BLOCKSIZE);
}
collect_and_sort_names ();
while (p = name_from_list (), p)
- dump_file (p, (dev_t) -1, 1);
+ if (!excluded_name (p))
+ dump_file (p, (dev_t) -1, 1);
blank_name_list ();
while (p = name_from_list (), p)
- {
- strcpy (buffer, p);
- if (p[strlen (p) - 1] != '/')
- strcat (buffer, "/");
- bufp = buffer + strlen (buffer);
- for (q = gnu_list_name->dir_contents;
- q && *q;
- q += strlen (q) + 1)
- {
- if (*q == 'Y')
- {
- strcpy (bufp, q + 1);
- dump_file (buffer, (dev_t) -1, 1);
- }
- }
- }
+ if (!excluded_name (p))
+ {
+ strcpy (buffer, p);
+ if (p[strlen (p) - 1] != '/')
+ strcat (buffer, "/");
+ bufp = buffer + strlen (buffer);
+ q = gnu_list_name->dir_contents;
+ if (q)
+ for (; *q; q += strlen (q) + 1)
+ if (*q == 'Y')
+ {
+ strcpy (bufp, q + 1);
+ dump_file (buffer, (dev_t) -1, 1);
+ }
+ }
free (buffer);
}
else
{
while (p = name_next (1), p)
- dump_file (p, (dev_t) -1, 1);
+ if (!excluded_name (p))
+ dump_file (p, (dev_t) -1, 1);
}
write_eot ();
#ifdef S_ISHIDDEN
if (S_ISHIDDEN (current_stat.st_mode))
{
- char *new = (char *) alloca (strlen (p) + 2);
+ char *new = alloca (strlen (p) + 2);
if (new)
{
strcpy (new, p);
}
#endif
- /* See if we only want new files, and check if this one is too old to
+ /* See if we want only new files, and check if this one is too old to
put in the archive. */
- if (!incremental_option && !S_ISDIR (current_stat.st_mode)
+ if ((!incremental_option || listed_incremental_option)
+ && !S_ISDIR (current_stat.st_mode)
&& current_stat.st_mtime < newer_mtime_option
&& (!after_date_option || current_stat.st_ctime < newer_ctime_option))
{
- if (parent_device == (dev_t) -1)
+ if (!listed_incremental_option && parent_device == (dev_t) -1)
WARN ((0, 0, _("%s: is unchanged; not dumped"), p));
/* FIXME: recheck this return. */
return;
if (current_stat.st_nlink > 1
&& (S_ISREG (current_stat.st_mode)
-#ifdef S_ISCTG
|| S_ISCTG (current_stat.st_mode)
-#endif
-#ifdef S_ISCHR
|| S_ISCHR (current_stat.st_mode)
-#endif
-#ifdef S_ISBLK
|| S_ISBLK (current_stat.st_mode)
-#endif
-#ifdef S_ISFIFO
- || S_ISFIFO (current_stat.st_mode)
-#endif
- ))
+ || S_ISFIFO (current_stat.st_mode)))
{
struct link *lp;
while (!absolute_names_option && *link_name == '/')
{
- static int warned_once = 0;
-
+ static int warned_once;
if (!warned_once)
{
warned_once = 1;
- WARN ((0, 0, _("\
-Removing leading `/' from absolute links")));
+ WARN ((0, 0, _("Removing leading `/' from link names")));
}
link_name++;
}
current_stat.st_size = 0;
header = start_header (p, ¤t_stat);
- if (header == NULL)
+ if (! header)
{
exit_status = TAREXIT_FAILURE;
return;
/* Not found. Add it to the list of possible links. */
- lp = (struct link *)
- xmalloc ((size_t) (sizeof (struct link) + strlen (p)));
+ lp = xmalloc (sizeof (struct link) + strlen (p));
lp->ino = current_stat.st_ino;
lp->dev = current_stat.st_dev;
strcpy (lp->name, p);
/* This is not a link to a previously dumped file, so dump it. */
if (S_ISREG (current_stat.st_mode)
-#ifdef S_ISCTG
- || S_ISCTG (current_stat.st_mode)
-#endif
- )
+ || S_ISCTG (current_stat.st_mode))
{
int f; /* file descriptor */
size_t bufsize;
int header_moved;
char isextended = 0;
int upperbound;
-#if 0
- static int cried_once = 0;
-#endif
header_moved = 0;
int counter;
header = start_header (p, ¤t_stat);
- if (header == NULL)
+ if (! header)
{
exit_status = TAREXIT_FAILURE;
return;
<file>. It might be kind of disconcerting if the
shrunken file size was the one that showed up. */
- OFF_TO_OCT (current_stat.st_size,
- header->oldgnu_header.realsize);
+ OFF_TO_CHARS (current_stat.st_size,
+ header->oldgnu_header.realsize);
/* This will be the new "size" of the file, i.e., the size
of the file minus the blocks of holes that we're
find_new_file_size (&filesize, upperbound);
current_stat.st_size = filesize;
- OFF_TO_OCT (filesize, header->header.size);
+ OFF_TO_CHARS (filesize, header->header.size);
for (counter = 0; counter < SPARSES_IN_OLDGNU_HEADER; counter++)
{
if (!sparsearray[counter].numbytes)
break;
- OFF_TO_OCT (sparsearray[counter].offset,
- header->oldgnu_header.sp[counter].offset);
- SIZE_TO_OCT (sparsearray[counter].numbytes,
- header->oldgnu_header.sp[counter].numbytes);
+ OFF_TO_CHARS (sparsearray[counter].offset,
+ header->oldgnu_header.sp[counter].offset);
+ SIZE_TO_CHARS (sparsearray[counter].numbytes,
+ header->oldgnu_header.sp[counter].numbytes);
}
}
files when archive is meant for /dev/null. */
if (dev_null_output
- || (sizeleft == 0 && 0444 == (0444 & current_stat.st_mode)))
+ || (sizeleft == 0
+ && MODE_R == (MODE_R & current_stat.st_mode)))
f = -1;
else
{
if (!header_moved)
{
header = start_header (p, ¤t_stat);
- if (header == NULL)
+ if (! header)
{
if (f >= 0)
close (f);
return;
}
}
-#ifdef S_ISCTG
+
/* Mark contiguous files, if we support them. */
if (archive_format != V7_FORMAT && S_ISCTG (current_stat.st_mode))
header->header.typeflag = CONTTYPE;
-#endif
+
isextended = header->oldgnu_header.isextended;
save_typeflag = header->header.typeflag;
finish_header (header);
extend:
exhdr = find_next_block ();
-
- if (exhdr == NULL)
+ if (! exhdr)
{
exit_status = TAREXIT_FAILURE;
return;
if (counter + index_offset > upperbound)
break;
- SIZE_TO_OCT (sparsearray[counter + index_offset].numbytes,
- exhdr->sparse_header.sp[counter].numbytes);
- OFF_TO_OCT (sparsearray[counter + index_offset].offset,
- exhdr->sparse_header.sp[counter].offset);
+ SIZE_TO_CHARS (sparsearray[counter + index_offset].numbytes,
+ exhdr->sparse_header.sp[counter].numbytes);
+ OFF_TO_CHARS (sparsearray[counter + index_offset].offset,
+ exhdr->sparse_header.sp[counter].offset);
}
set_next_block_after (exhdr);
#if 0
}
if (save_typeflag == GNUTYPE_SPARSE)
{
- if (finish_sparse_file (f, &sizeleft, current_stat.st_size, p))
+ if (f < 0
+ || finish_sparse_file (f, &sizeleft, current_stat.st_size, p))
goto padit;
}
else
bufsize = sizeleft;
count = bufsize % BLOCKSIZE;
if (count)
- memset (start->buffer + sizeleft, 0,
- (size_t) (BLOCKSIZE - count));
+ memset (start->buffer + sizeleft, 0, BLOCKSIZE - count);
}
if (f < 0)
count = bufsize;
else
- count = read (f, start->buffer, bufsize);
+ count = safe_read (f, start->buffer, bufsize);
if (count < 0)
{
char buf[UINTMAX_STRSIZE_BOUND];
- ERROR ((0, errno, _("\
-Read error at byte %s, reading %lu bytes, in file %s"),
+ ERROR ((0, errno,
+ _("Read error at byte %s, reading %lu bytes, in file %s"),
STRINGIFY_BIGINT (current_stat.st_size - sizeleft,
buf),
(unsigned long) bufsize, p));
}
if (multi_volume_option)
- assign_string (&save_name, NULL);
+ assign_string (&save_name, 0);
if (f >= 0)
{
sizeleft -= BLOCKSIZE;
}
if (multi_volume_option)
- assign_string (&save_name, NULL);
+ assign_string (&save_name, 0);
if (f >= 0)
{
close (f);
return;
}
-#ifdef S_ISLNK
+#ifdef HAVE_READLINK
else if (S_ISLNK (current_stat.st_mode))
{
int size;
- char *buffer = (char *) alloca (PATH_MAX + 1);
+ char *buffer = alloca (PATH_MAX + 1);
size = readlink (p, buffer, PATH_MAX + 1);
if (size < 0)
current_stat.st_size = 0; /* force 0 size on symlink */
header = start_header (p, ¤t_stat);
- if (header == NULL)
+ if (! header)
{
exit_status = TAREXIT_FAILURE;
return;
}
return;
}
-#endif /* S_ISLNK */
+#endif
else if (S_ISDIR (current_stat.st_mode))
{
files, we'd better put the / on the name. */
header = start_header (namebuf, ¤t_stat);
- if (header == NULL)
+ if (! header)
{
exit_status = TAREXIT_FAILURE;
return; /* eg name too long */
p_buffer += tmp;
}
totsize++;
- OFF_TO_OCT (totsize, header->header.size);
+ OFF_TO_CHARS (totsize, header->header.size);
finish_header (header);
p_buffer = buffer;
sizeleft = totsize;
bufsize = sizeleft;
count = bufsize % BLOCKSIZE;
if (count)
- memset (start->buffer + sizeleft, 0,
- (size_t) (BLOCKSIZE - count));
+ memset (start->buffer + sizeleft, 0, BLOCKSIZE - count);
}
memcpy (start->buffer, p_buffer, bufsize);
sizeleft -= bufsize;
set_next_block_after (start + (bufsize - 1) / BLOCKSIZE);
}
if (multi_volume_option)
- assign_string (&save_name, NULL);
+ assign_string (&save_name, 0);
if (atime_preserve_option)
utime (p, &restore_times);
return;
return;
}
- /* Hack to remove "./" from the front of all the file names. */
-
- if (len == 2 && namebuf[0] == '.' && namebuf[1] == '/')
- len = 0;
-
/* FIXME: Should speed this up by cd-ing into the dir. */
while (entry = readdir (directory), entry)
{
- /* Skip `.' and `..'. */
+ /* Skip `.', `..', and excluded file names. */
if (is_dot_or_dotdot (entry->d_name))
continue;
if ((int) NAMLEN (entry) + len >= buflen)
{
buflen = len + NAMLEN (entry);
- namebuf = (char *) xrealloc (namebuf, buflen + 1);
+ namebuf = xrealloc (namebuf, buflen + 1);
#if 0
namebuf[len] = '\0';
ERROR ((0, 0, _("File name %s%s too long"),
#endif
}
strcpy (namebuf + len, entry->d_name);
- if (exclude_option && check_exclude (namebuf))
- continue;
- dump_file (namebuf, our_device, 0);
+ if (!excluded_name (namebuf))
+ dump_file (namebuf, our_device, 0);
}
closedir (directory);
return;
}
-#ifdef S_ISCHR
else if (S_ISCHR (current_stat.st_mode))
type = CHRTYPE;
-#endif
-
-#ifdef S_ISBLK
else if (S_ISBLK (current_stat.st_mode))
type = BLKTYPE;
-#endif
-
- /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK. */
-
-#if (_ISP__M68K == 0) && (_ISP__A88K == 0) && defined(S_ISFIFO)
- else if (S_ISFIFO (current_stat.st_mode))
- type = FIFOTYPE;
-#endif
-
-#ifdef S_ISSOCK
- else if (S_ISSOCK (current_stat.st_mode))
+ else if (S_ISFIFO (current_stat.st_mode)
+ || S_ISSOCK (current_stat.st_mode))
type = FIFOTYPE;
-#endif
-
else
goto unknown;
current_stat.st_size = 0; /* force 0 size */
header = start_header (p, ¤t_stat);
- if (header == NULL)
+ if (! header)
{
exit_status = TAREXIT_FAILURE;
return; /* eg name too long */
header->header.typeflag = type;
-#if defined(S_IFBLK) || defined(S_IFCHR)
if (type != FIFOTYPE)
{
- MAJOR_TO_OCT (major (current_stat.st_rdev), header->header.devmajor);
- MINOR_TO_OCT (minor (current_stat.st_rdev), header->header.devminor);
+ MAJOR_TO_CHARS (major (current_stat.st_rdev), header->header.devmajor);
+ MINOR_TO_CHARS (minor (current_stat.st_rdev), header->header.devminor);
}
-#endif
finish_header (header);
if (remove_files_option)