/* Compression detection */
enum compress_type {
- ct_none,
+ ct_tar, /* Plain tar file */
+ ct_none, /* Unknown compression type */
ct_compress,
ct_gzip,
ct_bzip2,
- ct_lzma
+ ct_lzma,
+ ct_lzop
};
struct zip_magic
};
static struct zip_magic const magic[] = {
+ { ct_tar },
{ ct_none, },
{ ct_compress, 2, "\037\235", "compress", "-Z" },
{ ct_gzip, 2, "\037\213", "gzip", "-z" },
{ ct_bzip2, 3, "BZh", "bzip2", "-j" },
- { ct_lzma, 6, "\xFFLZMA", "lzma", "--lzma" }, /* FIXME: ???? */
+ { ct_lzma, 6, "\xFFLZMA", "lzma", "-J" }, /* FIXME: ???? */
+ { ct_lzop, 4, "\211LZO", "lzop", "--lzop" },
};
#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
/* Check if the file ARCHIVE is a compressed archive. */
enum compress_type
-check_compressed_archive ()
+check_compressed_archive (bool *pshort)
{
struct zip_magic const *p;
bool sfr;
- bool short_file = false;
+ bool temp;
+
+ if (!pshort)
+ pshort = &temp;
/* Prepare global data needed for find_next_block: */
record_end = record_start; /* set up for 1st record = # 0 */
sfr = read_full_records;
read_full_records = true; /* Suppress fatal error on reading a partial
record */
- if (find_next_block () == 0)
- short_file = true;
+ *pshort = find_next_block () == 0;
/* Restore global values */
read_full_records = sfr;
if (tar_checksum (record_start, true) == HEADER_SUCCESS)
/* Probably a valid header */
- return ct_none;
+ return ct_tar;
- for (p = magic + 1; p < magic + NMAGIC; p++)
+ for (p = magic + 2; p < magic + NMAGIC; p++)
if (memcmp (record_start->buffer, p->magic, p->length) == 0)
return p->type;
- if (short_file)
- ERROR ((0, 0, _("This does not look like a tar archive")));
-
return ct_none;
}
if (!multi_volume_option)
{
- enum compress_type type = check_compressed_archive ();
+ if (!use_compress_program_option)
+ {
+ bool shortfile;
+ enum compress_type type = check_compressed_archive (&shortfile);
- if (type == ct_none)
- return archive;
+ switch (type)
+ {
+ case ct_tar:
+ if (shortfile)
+ ERROR ((0, 0, _("This does not look like a tar archive")));
+ return archive;
+
+ case ct_none:
+ if (shortfile)
+ ERROR ((0, 0, _("This does not look like a tar archive")));
+ set_comression_program_by_suffix (archive_name_array[0], NULL);
+ if (!use_compress_program_option)
+ return archive;
+ break;
+ default:
+ use_compress_program_option = compress_program (type);
+ break;
+ }
+ }
+
/* FD is not needed any more */
rmtclose (archive);
check_compressed_archive */
/* Open compressed archive */
- use_compress_program_option = compress_program (type);
child_pid = sys_child_open_for_uncompress ();
read_full_records = true;
}
{
case ACCESS_READ:
{
+ bool shortfile;
enum compress_type type;
archive = STDIN_FILENO;
- type = check_compressed_archive ();
- if (type != ct_none)
+ type = check_compressed_archive (&shortfile);
+ if (type != ct_tar && type != ct_none)
FATAL_ERROR ((0, 0,
_("Archive is compressed. Use %s option"),
compress_option (type)));
+ if (shortfile)
+ ERROR ((0, 0, _("This does not look like a tar archive")));
}
break;
O_RDWR | O_CREAT | O_BINARY,
MODE_RW, rsh_command_option);
- if (check_compressed_archive () != ct_none)
- FATAL_ERROR ((0, 0,
- _("Cannot update compressed archives")));
+ switch (check_compressed_archive (NULL))
+ {
+ case ct_none:
+ case ct_tar:
+ break;
+
+ default:
+ FATAL_ERROR ((0, 0,
+ _("Cannot update compressed archives")));
+ }
break;
}
verify_volume ();
if (rmtclose (archive) != 0)
- close_warn (*archive_name_cursor);
+ close_error (*archive_name_cursor);
sys_wait_for_child (child_pid);
current_block = record_start;
if (rmtclose (archive) != 0)
- close_warn (*archive_name_cursor);
+ close_error (*archive_name_cursor);
archive_name_cursor++;
if (archive_name_cursor == archive_name_array + archive_names)
if (real_s_totsize - real_s_sizeleft != continued_file_offset)
{
- WARN ((0, 0, _("This volume is out of sequence")));
+ char totsizebuf[UINTMAX_STRSIZE_BOUND];
+ char s1buf[UINTMAX_STRSIZE_BOUND];
+ char s2buf[UINTMAX_STRSIZE_BOUND];
+
+ WARN ((0, 0, _("This volume is out of sequence (%s - %s != %s)"),
+ STRINGIFY_BIGINT (real_s_totsize, totsizebuf),
+ STRINGIFY_BIGINT (real_s_sizeleft, s1buf),
+ STRINGIFY_BIGINT (continued_file_offset, s2buf)));
+
return false;
}
}
return;
}
+ if (status % BLOCKSIZE)
+ {
+ ERROR ((0, 0, _("write did not end on a block boundary")));
+ archive_write_error (status);
+ }
+
/* In multi-volume mode. */
/* ENXIO is for the UNIX PC. */
if (status < 0 && errno != ENOSPC && errno != EIO && errno != ENXIO)
archive_write_error (status);
+ real_s_sizeleft -= status;
if (!new_volume (ACCESS_WRITE))
return;
copy_ptr = record_start->buffer + status;
copy_size = buffer_level - status;
+
/* Switch to the next buffer */
record_index = !record_index;
init_buffer ();