]> Dogcows Code - chaz/tar/blobdiff - src/list.c
Fix bug in OLDGNU format creation.
[chaz/tar] / src / list.c
index 2436901bdfbd35a332742059d5f786f2a0ddb002..bba430ad8531ed73ec15f8b707fa861e3de97321 100644 (file)
@@ -531,7 +531,9 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
               enum archive_format *format_pointer, int do_user_group)
 {
   enum archive_format format;
-
+  unsigned hbits; /* high bits of the file mode. */
+  mode_t mode = MODE_FROM_HEADER (header->header.mode, &hbits);
+  
   if (strcmp (header->header.magic, TMAGIC) == 0)
     {
       if (header->star_header.prefix[130] == 0
@@ -546,12 +548,12 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
        format = USTAR_FORMAT;
     }
   else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
-    format = OLDGNU_FORMAT;
+    format = hbits ? OLDGNU_FORMAT : GNU_FORMAT;
   else
     format = V7_FORMAT;
   *format_pointer = format;
 
-  stat_info->stat.st_mode = MODE_FROM_HEADER (header->header.mode);
+  stat_info->stat.st_mode = mode;
   stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
   stat_info->mtime.tv_nsec = 0;
   assign_string (&stat_info->uname,
@@ -885,25 +887,28 @@ minor_from_header (const char *p, size_t s)
                      (uintmax_t) TYPE_MAXIMUM (minor_t), false, false);
 }
 
+/* Convert P to the file mode, as understood by tar.
+   Store unrecognized mode bits (from 10th up) in HBITS. */
 mode_t
-mode_from_header (const char *p, size_t s)
+mode_from_header (const char *p, size_t s, unsigned *hbits)
 {
-  /* Do not complain about unrecognized mode bits.  */
   unsigned u = from_header (p, s, "mode_t",
                            - (uintmax_t) TYPE_MINIMUM (mode_t),
                            TYPE_MAXIMUM (uintmax_t), false, false);
-  return ((u & TSUID ? S_ISUID : 0)
-         | (u & TSGID ? S_ISGID : 0)
-         | (u & TSVTX ? S_ISVTX : 0)
-         | (u & TUREAD ? S_IRUSR : 0)
-         | (u & TUWRITE ? S_IWUSR : 0)
-         | (u & TUEXEC ? S_IXUSR : 0)
-         | (u & TGREAD ? S_IRGRP : 0)
-         | (u & TGWRITE ? S_IWGRP : 0)
-         | (u & TGEXEC ? S_IXGRP : 0)
-         | (u & TOREAD ? S_IROTH : 0)
-         | (u & TOWRITE ? S_IWOTH : 0)
-         | (u & TOEXEC ? S_IXOTH : 0));
+  mode_t mode = ((u & TSUID ? S_ISUID : 0)
+                | (u & TSGID ? S_ISGID : 0)
+                | (u & TSVTX ? S_ISVTX : 0)
+                | (u & TUREAD ? S_IRUSR : 0)
+                | (u & TUWRITE ? S_IWUSR : 0)
+                | (u & TUEXEC ? S_IXUSR : 0)
+                | (u & TGREAD ? S_IRGRP : 0)
+                | (u & TGWRITE ? S_IWGRP : 0)
+                | (u & TGEXEC ? S_IXGRP : 0)
+                | (u & TOREAD ? S_IROTH : 0)
+                | (u & TOWRITE ? S_IWOTH : 0)
+                | (u & TOEXEC ? S_IXOTH : 0));
+  *hbits = mode ^ u;
+  return mode;
 }
 
 off_t
This page took 0.021456 seconds and 4 git commands to generate.