+/* Decode things from a file HEADER block into STAT_INFO, also setting
+ *FORMAT_POINTER depending on the header block format. If
+ DO_USER_GROUP, decode the user/group information (this is useful
+ for extraction, but waste time when merely listing).
+
+ read_header() has already decoded the checksum and length, so we don't.
+
+ This routine should *not* be called twice for the same block, since
+ the two calls might use different DO_USER_GROUP values and thus
+ might end up with different uid/gid for the two calls. If anybody
+ wants the uid/gid they should decode it first, and other callers
+ should decode it without uid/gid before calling a routine,
+ e.g. print_header, that assumes decoded data. */
+void
+decode_header (union block *header, struct stat *stat_info,
+ enum archive_format *format_pointer, int do_user_group)
+{
+ enum archive_format format;
+
+ if (strcmp (header->header.magic, TMAGIC) == 0)
+ format = POSIX_FORMAT;
+ else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
+ format = OLDGNU_FORMAT;
+ else
+ format = V7_FORMAT;
+ *format_pointer = format;
+
+ stat_info->st_mode = MODE_FROM_HEADER (header->header.mode);
+ stat_info->st_mtime = TIME_FROM_HEADER (header->header.mtime);
+
+ if (format == OLDGNU_FORMAT && incremental_option)
+ {
+ stat_info->st_atime = TIME_FROM_HEADER (header->oldgnu_header.atime);
+ stat_info->st_ctime = TIME_FROM_HEADER (header->oldgnu_header.ctime);
+ }
+
+ if (format == V7_FORMAT)
+ {
+ stat_info->st_uid = UID_FROM_HEADER (header->header.uid);
+ stat_info->st_gid = GID_FROM_HEADER (header->header.gid);
+ stat_info->st_rdev = 0;
+ }
+ else
+ {
+ if (do_user_group)
+ {
+ /* FIXME: Decide if this should somewhat depend on -p. */
+
+ if (numeric_owner_option
+ || !*header->header.uname
+ || !uname_to_uid (header->header.uname, &stat_info->st_uid))
+ stat_info->st_uid = UID_FROM_HEADER (header->header.uid);
+
+ if (numeric_owner_option
+ || !*header->header.gname
+ || !gname_to_gid (header->header.gname, &stat_info->st_gid))
+ stat_info->st_gid = GID_FROM_HEADER (header->header.gid);
+ }
+ switch (header->header.typeflag)
+ {
+ case BLKTYPE:
+ stat_info->st_rdev
+ = makedev (MAJOR_FROM_HEADER (header->header.devmajor),
+ MINOR_FROM_HEADER (header->header.devminor));
+ break;
+
+ case CHRTYPE:
+ stat_info->st_rdev
+ = makedev (MAJOR_FROM_HEADER (header->header.devmajor),
+ MINOR_FROM_HEADER (header->header.devminor));
+ break;
+
+ default:
+ stat_info->st_rdev = 0;
+ }
+ }
+}