+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. */
+
+/* Make a header block for the file whose stat info is st,
+ and return its address. */
+
+union block *
+start_header (struct tar_stat_info *st)
+{
+ union block *header;
+
+ header = write_header_name (st);
+ if (!header)
+ return NULL;
+
+ /* Override some stat fields, if requested to do so. */
+
+ if (owner_option != (uid_t) -1)
+ st->stat.st_uid = owner_option;
+ if (group_option != (gid_t) -1)
+ st->stat.st_gid = group_option;
+ if (mode_option)
+ st->stat.st_mode =
+ ((st->stat.st_mode & ~MODE_ALL)
+ | mode_adjust (st->stat.st_mode, mode_option, initial_umask));
+
+ /* Paul Eggert tried the trivial test ($WRITER cf a b; $READER tvf a)
+ for a few tars and came up with the following interoperability
+ matrix:
+
+ WRITER
+ 1 2 3 4 5 6 7 8 9 READER
+ . . . . . . . . . 1 = SunOS 4.2 tar
+ # . . # # . . # # 2 = NEC SVR4.0.2 tar
+ . . . # # . . # . 3 = Solaris 2.1 tar
+ . . . . . . . . . 4 = GNU tar 1.11.1
+ . . . . . . . . . 5 = HP-UX 8.07 tar
+ . . . . . . . . . 6 = Ultrix 4.1
+ . . . . . . . . . 7 = AIX 3.2
+ . . . . . . . . . 8 = Hitachi HI-UX 1.03
+ . . . . . . . . . 9 = Omron UNIOS-B 4.3BSD 1.60Beta
+
+ . = works
+ # = ``impossible file type''
+
+ The following mask for old archive removes the `#'s in column 4
+ above, thus making GNU tar both a universal donor and a universal
+ acceptor for Paul's test. */
+
+ if (archive_format == V7_FORMAT || archive_format == USTAR_FORMAT)
+ MODE_TO_CHARS (st->stat.st_mode & MODE_ALL, header->header.mode);
+ else
+ MODE_TO_CHARS (st->stat.st_mode, header->header.mode);
+
+ {
+ uid_t uid = st->stat.st_uid;
+ if (archive_format == POSIX_FORMAT
+ && MAX_OCTAL_VAL (header->header.uid) < uid)
+ {
+ xheader_store ("uid", st, NULL);
+ uid = 0;
+ }
+ UID_TO_CHARS (uid, header->header.uid);
+ }
+
+ {
+ gid_t gid = st->stat.st_gid;
+ if (archive_format == POSIX_FORMAT
+ && MAX_OCTAL_VAL (header->header.gid) < gid)
+ {
+ xheader_store ("gid", st, NULL);
+ gid = 0;
+ }
+ GID_TO_CHARS (gid, header->header.gid);
+ }
+
+ {
+ off_t size = st->stat.st_size;
+ if (archive_format == POSIX_FORMAT
+ && MAX_OCTAL_VAL (header->header.size) < size)
+ {
+ xheader_store ("size", st, NULL);
+ size = 0;
+ }
+ OFF_TO_CHARS (size, header->header.size);
+ }