+void
+compute_duration ()
+{
+ struct timespec now;
+ gettime (&now);
+ duration += ((now.tv_sec - start_time.tv_sec)
+ + (now.tv_nsec - start_time.tv_nsec) / 1e9);
+ set_start_time ();
+}
+
+\f
+/* Compression detection */
+
+enum compress_type {
+ ct_none,
+ ct_compress,
+ ct_gzip,
+ ct_bzip2
+};
+
+struct zip_magic
+{
+ enum compress_type type;
+ size_t length;
+ char *magic;
+ char *program;
+ char *option;
+};
+
+static struct zip_magic const magic[] = {
+ { ct_none, },
+ { ct_compress, 2, "\037\235", "compress", "-Z" },
+ { ct_gzip, 2, "\037\213", "gzip", "-z" },
+ { ct_bzip2, 3, "BZh", "bzip2", "-j" },
+};
+
+#define NMAGIC (sizeof(magic)/sizeof(magic[0]))
+
+#define compress_option(t) magic[t].option
+#define compress_program(t) magic[t].program
+
+/* Check if the file ARCHIVE is a compressed archive. */
+enum compress_type
+check_compressed_archive ()
+{
+ struct zip_magic const *p;
+ bool sfr;
+
+ /* 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 */
+ find_next_block ();
+
+ /* Restore global values */
+ read_full_records = sfr;
+
+ if (tar_checksum (record_start, true) == HEADER_SUCCESS)
+ /* Probably a valid header */
+ return ct_none;
+
+ for (p = magic + 1; p < magic + NMAGIC; p++)
+ if (memcmp (record_start->buffer, p->magic, p->length) == 0)
+ return p->type;
+
+ return ct_none;