+ memset (header->buffer, 0, sizeof (header->buffer));
+ memcpy (header->header.prefix, name, i);
+ memcpy (header->header.name, name + i + 1, length - i - 1);
+
+ return header;
+}
+
+/* Write a long link name, depending on the current archive format */
+static void
+write_long_link (struct tar_stat_info *st)
+{
+ switch (archive_format)
+ {
+ case POSIX_FORMAT:
+ xheader_store ("linkpath", st, NULL);
+ break;
+
+ case V7_FORMAT: /* old V7 tar format */
+ case USTAR_FORMAT:
+ case STAR_FORMAT:
+ ERROR ((0, 0,
+ _("%s: link name is too long; not dumped"),
+ quotearg_colon (st->link_name)));
+ break;
+
+ case OLDGNU_FORMAT:
+ case GNU_FORMAT:
+ write_gnu_long_link (st, st->link_name, GNUTYPE_LONGLINK);
+ break;
+
+ default:
+ abort(); /*FIXME*/
+ }
+}
+
+static union block *
+write_long_name (struct tar_stat_info *st)
+{
+ switch (archive_format)
+ {
+ case POSIX_FORMAT:
+ xheader_store ("path", st, NULL);
+ break;
+
+ case V7_FORMAT:
+ if (strlen (st->file_name) > NAME_FIELD_SIZE-1)
+ {
+ ERROR ((0, 0, _("%s: file name is too long (max %d); not dumped"),
+ quotearg_colon (st->file_name),
+ NAME_FIELD_SIZE - 1));
+ return NULL;
+ }
+ break;
+
+ case USTAR_FORMAT:
+ case STAR_FORMAT:
+ return write_ustar_long_name (st->file_name);
+
+ case OLDGNU_FORMAT:
+ case GNU_FORMAT:
+ write_gnu_long_link (st, st->file_name, GNUTYPE_LONGNAME);
+ break;
+
+ default:
+ abort(); /*FIXME*/
+ }
+ return write_short_name (st);
+}
+
+union block *
+write_extended (bool global, struct tar_stat_info *st, union block *old_header)
+{
+ union block *header, hp;
+ char *p;
+ int type;
+
+ if (extended_header.buffer || extended_header.stk == NULL)
+ return old_header;
+
+ xheader_finish (&extended_header);
+ memcpy (hp.buffer, old_header, sizeof (hp));
+ if (global)
+ {
+ type = XGLTYPE;
+ p = xheader_ghdr_name ();
+ }
+ else
+ {
+ type = XHDTYPE;
+ p = xheader_xhdr_name (st);
+ }
+ xheader_write (type, p, &extended_header);
+ free (p);
+ header = find_next_block ();
+ memcpy (header, &hp.buffer, sizeof (hp.buffer));
+ return header;
+}
+
+static union block *
+write_header_name (struct tar_stat_info *st)
+{
+ if (archive_format == POSIX_FORMAT && !string_ascii_p (st->file_name))
+ {
+ xheader_store ("path", st, NULL);
+ return write_short_name (st);
+ }
+ else if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT)
+ < strlen (st->file_name))
+ return write_long_name (st);
+ else
+ return write_short_name (st);
+}
+
+\f
+/* Header handling. */