--- tar-1.23.orig/tests/incremental.at
+++ tar-1.23/tests/incremental.at
@@ -39,7 +39,7 @@
# command, behaviour of tar becomes variable, depending whether the system
# clock ticked over to the next second between creating the file and
# backing it up.
-sleep 1
+sleep 2
tar cf archive --listed=list structure
tar cfv archive --listed=list structure
--- tar-1.23.orig/src/list.c
+++ tar-1.23/src/list.c
@@ -144,9 +144,17 @@
read_header_auto);
if (status == HEADER_ZERO_BLOCK)
break;
+ /*
+ * According to POSIX tar specs, this is wrong, but on the web
+ * there are some tar specs that can trigger this, and some tar
+ * implementations create tars according to that spec. For now,
+ * let's not be pedantic about issuing the warning.
+ */
+#if 0
WARNOPT (WARN_ALONE_ZERO_BLOCK,
(0, 0, _("A lone zero block at %s"),
STRINGIFY_BIGINT (current_block_ordinal (), buf)));
+#endif
break;
}
status = prev_status;
--- tar-1.23.orig/src/extract.c
+++ tar-1.23/src/extract.c
@@ -888,12 +888,22 @@
struct stat st;
while ((fd = open (file_name, O_WRONLY | O_CREAT | O_EXCL, 0)) < 0)
- if (! maybe_recoverable (file_name, interdir_made))
- break;
+ {
+ switch (maybe_recoverable (file_name, interdir_made))
+ {
+ case RECOVER_OK:
+ continue;
+
+ case RECOVER_SKIP:
+ return 0;
+
+ case RECOVER_NO:
+ open_error (file_name);
+ return -1;
+ }
+ }
- if (fd < 0)
- open_error (file_name);
- else if (fstat (fd, &st) != 0)
+ if (fstat (fd, &st) != 0)
{
stat_error (file_name);
close (fd);
@@ -956,7 +966,8 @@
{
int interdir_made = 0;
char const *link_name;
-
+ int rc;
+
link_name = current_stat_info.link_name;
if (! absolute_names_option && contains_dot_dot (link_name))
@@ -996,8 +1007,10 @@
errno = e;
}
- while (maybe_recoverable (file_name, &interdir_made));
+ while ((rc = maybe_recoverable (file_name, &interdir_made)) == RECOVER_OK);
+ if (rc == RECOVER_SKIP)
+ return 0;
if (!(incremental_option && errno == EEXIST))
{
link_error (link_name, file_name);
@@ -1010,7 +1023,6 @@
extract_symlink (char *file_name, int typeflag)
{
#ifdef HAVE_SYMLINK
- int status;
int interdir_made = 0;
if (! absolute_names_option
@@ -1018,15 +1030,22 @@
|| contains_dot_dot (current_stat_info.link_name)))
return create_placeholder_file (file_name, true, &interdir_made);
- while ((status = symlink (current_stat_info.link_name, file_name)))
- if (!maybe_recoverable (file_name, &interdir_made))
- break;
-
- if (status == 0)
- set_stat (file_name, ¤t_stat_info, NULL, 0, 0, SYMTYPE);
- else
- symlink_error (current_stat_info.link_name, file_name);
- return status;
+ while (symlink (current_stat_info.link_name, file_name))
+ switch (maybe_recoverable (file_name, &interdir_made))
+ {
+ case RECOVER_OK:
+ continue;
+
+ case RECOVER_SKIP:
+ return 0;
+
+ case RECOVER_NO:
+ symlink_error (current_stat_info.link_name, file_name);
+ return -1;
+ }
+
+ set_stat (file_name, ¤t_stat_info, NULL, 0, 0, SYMTYPE);
+ return 0;
#else
static int warned_once;
@@ -1052,16 +1071,23 @@
mode_t invert_permissions =
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
- do
- status = mknod (file_name, mode ^ invert_permissions,
- current_stat_info.stat.st_rdev);
- while (status && maybe_recoverable (file_name, &interdir_made));
+ while (mknod (file_name, mode ^ invert_permissions,
+ current_stat_info.stat.st_rdev))
+ switch (maybe_recoverable (file_name, &interdir_made))
+ {
+ case RECOVER_OK:
+ continue;
+
+ case RECOVER_SKIP:
+ return 0;
+
+ case RECOVER_NO:
+ mknod_error (file_name);
+ return -1;
+ }
- if (status != 0)
- mknod_error (file_name);
- else
- set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
- ARCHIVED_PERMSTATUS, typeflag);
+ set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
+ ARCHIVED_PERMSTATUS, typeflag);
return status;
}
#endif
@@ -1077,15 +1103,22 @@
0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;
while ((status = mkfifo (file_name, mode)) != 0)
- if (!maybe_recoverable (file_name, &interdir_made))
- break;
+ switch (maybe_recoverable (file_name, &interdir_made))
+ {
+ case RECOVER_OK:
+ continue;
+
+ case RECOVER_SKIP:
+ return 0;
+
+ case RECOVER_NO:
+ mkfifo_error (file_name);
+ return -1;
+ }
- if (status == 0)
- set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
- ARCHIVED_PERMSTATUS, typeflag);
- else
- mkfifo_error (file_name);
- return status;
+ set_stat (file_name, ¤t_stat_info, NULL, invert_permissions,
+ ARCHIVED_PERMSTATUS, typeflag);
+ return 0;
}
#endif
--- tar-1.23.orig/src/create.c
+++ tar-1.23/src/create.c
@@ -747,7 +747,7 @@
return write_short_name (st);
}
else if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
- < strlen (st->file_name))
+ <= strlen (st->file_name))
return write_long_name (st);
else
return write_short_name (st);
@@ -1399,7 +1399,7 @@
block_ordinal = current_block_ordinal ();
assign_string (&st->link_name, link_name);
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
- < strlen (link_name))
+ <= strlen (link_name))
write_long_link (st);
st->stat.st_size = 0;
--- tar-1.23.orig/rmt/rmt.c
+++ tar-1.23/rmt/rmt.c
@@ -100,6 +100,7 @@
va_list ap;
va_start (ap, fmt);
vfprintf (stdout, fmt, ap);
+ fflush (stdout);
VDEBUG (10, "S: ", fmt, ap);
}
@@ -117,6 +118,7 @@
DEBUG1 (10, "S: %s\n", msg);
DEBUG1 (1, "error: %s\n", msg);
fprintf (stdout, "E%d\n%s\n", code, msg);
+ fflush (stdout);
}
void
@@ -225,44 +227,57 @@
int
decode_open_flag (const char *mstr, int *pmode)
{
+ int numeric_mode = 0;
int mode = 0;
+ const char *p;
- while (mstr)
+ mstr = skip_ws (mstr);
+ if (c_isdigit (*mstr))
{
- int v;
- const char *p;
-
- mstr = skip_ws (mstr);
- if (*mstr == 0)
- break;
- else if (c_isdigit (*mstr))
- v = strtol (mstr, (char**) &p, 10);
- else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p))
- {
- rmt_error_message (EINVAL, "invalid open mode");
- return 1;
- }
-
- mode |= v;
+ numeric_mode = strtol (mstr, (char**) &p, 10);
+ mstr = skip_ws (p);
+ }
- if (*p && c_isblank (*p))
- p = skip_ws (p);
- if (*p == 0)
- break;
- else if (*p == '|')
- {
- /* FIXMEL
- if (p[1] == 0)
- rmt_error_message (EINVAL, "invalid open mode");
- */
- mstr = p + 1;
- }
- else
+ if (*mstr)
+ {
+ while (mstr)
{
- rmt_error_message (EINVAL, "invalid open mode");
- return 1;
+ int v;
+
+ mstr = skip_ws (mstr);
+ if (*mstr == 0)
+ break;
+ else if (c_isdigit (*mstr))
+ v = strtol (mstr, (char**) &p, 10);
+ else if (xlat_kw (mstr, "O_", open_flag_kw, &v, &p))
+ {
+ rmt_error_message (EINVAL, "invalid open mode");
+ return 1;
+ }
+
+ mode |= v;
+
+ if (*p && c_isblank (*p))
+ p = skip_ws (p);
+ if (*p == 0)
+ break;
+ else if (*p == '|')
+ {
+ /* FIXMEL
+ if (p[1] == 0)
+ rmt_error_message (EINVAL, "invalid open mode");
+ */
+ mstr = p + 1;
+ }
+ else
+ {
+ rmt_error_message (EINVAL, "invalid open mode");
+ return 1;
+ }
}
}
+ else
+ mode = numeric_mode;
*pmode = mode;
return 0;
}
@@ -288,6 +303,10 @@
64|512
CREAT|TRUNC
+ In addition, a compined form is also allowed, i.e. a decimal mode followed
+ by its symbolic representation. In this case the symbolic representation
+ is given preference.
+
Reply
-----
A0\n on success, E<errno>\n<msg>\n on error.