-static char *save_name; /* name of the file we are currently writing */
-static off_t save_totsize; /* total size of file we are writing, only
- valid if save_name is nonzero */
-static off_t save_sizeleft; /* where we are in the file we are writing,
- only valid if save_name is nonzero */
+
+/* When creating a multi-volume archive, each `bufmap' represents
+ a member stored (perhaps partly) in the current record buffer.
+ After flushing the record to the output media, all bufmaps that
+ represent fully written members are removed from the list, then
+ the sizeleft and start numbers in the remaining bufmaps are updated.
+
+ When reading from a multi-volume archive, the list degrades to a
+ single element, which keeps information about the member currently
+ being read.
+*/
+
+struct bufmap
+{
+ struct bufmap *next; /* Pointer to the next map entry */
+ size_t start; /* Offset of the first data block */
+ char *file_name; /* Name of the stored file */
+ off_t sizetotal; /* Size of the stored file */
+ off_t sizeleft; /* Size left to read/write */
+};
+static struct bufmap *bufmap_head, *bufmap_tail;
+
+/* This variable, when set, inhibits updating the bufmap chain after
+ a write. This is necessary when writing extended POSIX headers. */
+static int inhibit_map;
+
+void
+mv_begin_write (const char *file_name, off_t totsize, off_t sizeleft)
+{
+ if (multi_volume_option)
+ {
+ struct bufmap *bp = xmalloc (sizeof bp[0]);
+ if (bufmap_tail)
+ bufmap_tail->next = bp;
+ else
+ bufmap_head = bp;
+ bufmap_tail = bp;
+
+ bp->next = NULL;
+ bp->start = current_block - record_start;
+ bp->file_name = xstrdup (file_name);
+ bp->sizetotal = totsize;
+ bp->sizeleft = sizeleft;
+ }
+}
+
+static struct bufmap *
+bufmap_locate (size_t off)
+{
+ struct bufmap *map;
+
+ for (map = bufmap_head; map; map = map->next)
+ {
+ if (!map->next
+ || off < map->next->start * BLOCKSIZE)
+ break;
+ }
+ return map;
+}
+
+static void
+bufmap_free (struct bufmap *mark)
+{
+ struct bufmap *map;
+ for (map = bufmap_head; map && map != mark; )
+ {
+ struct bufmap *next = map->next;
+ free (map->file_name);
+ free (map);
+ map = next;
+ }
+ bufmap_head = map;
+ if (!bufmap_head)
+ bufmap_tail = bufmap_head;
+}
+
+static void
+bufmap_reset (struct bufmap *map, ssize_t fixup)
+{
+ bufmap_free (map);
+ if (map)
+ {
+ for (; map; map = map->next)
+ map->start += fixup;
+ }
+}