[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] oldgnu file format changes (file permissions field).
From: |
Sergey Poznyakoff |
Subject: |
Re: [Bug-tar] oldgnu file format changes (file permissions field). |
Date: |
Sun, 04 Oct 2009 23:14:49 +0300 |
Igor Zhbanov <address@hidden> ha escrit:
> Hello!
Hi,
> I have found that tarĀ“s after 1.16 creates binary different archives
> in oldgnu format.
> The difference is in file mode field.
Thanks. Please try the attached patch.
Regards,
Sergey
diff --git a/src/common.h b/src/common.h
index 73865ec..1a6ca8b 100644
--- a/src/common.h
+++ b/src/common.h
@@ -557,7 +557,8 @@ char const *tartime (struct timespec t, bool full_time);
#define GID_FROM_HEADER(where) gid_from_header (where, sizeof (where))
#define MAJOR_FROM_HEADER(where) major_from_header (where, sizeof (where))
#define MINOR_FROM_HEADER(where) minor_from_header (where, sizeof (where))
-#define MODE_FROM_HEADER(where) mode_from_header (where, sizeof (where))
+#define MODE_FROM_HEADER(where, hbits) \
+ mode_from_header (where, sizeof (where), hbits)
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
#define SIZE_FROM_HEADER(where) size_from_header (where, sizeof (where))
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
@@ -567,7 +568,7 @@ char const *tartime (struct timespec t, bool full_time);
gid_t gid_from_header (const char *buf, size_t size);
major_t major_from_header (const char *buf, size_t size);
minor_t minor_from_header (const char *buf, size_t size);
-mode_t mode_from_header (const char *buf, size_t size);
+mode_t mode_from_header (const char *buf, size_t size, unsigned *hbits);
off_t off_from_header (const char *buf, size_t size);
size_t size_from_header (const char *buf, size_t size);
time_t time_from_header (const char *buf, size_t size);
diff --git a/src/create.c b/src/create.c
index 6f3113e..79c80ce 100644
--- a/src/create.c
+++ b/src/create.c
@@ -402,8 +402,7 @@ mode_to_chars (mode_t v, char *p, size_t s)
&& S_IROTH == TOREAD && S_IWOTH == TOWRITE && S_IXOTH == TOEXEC
&& archive_format != POSIX_FORMAT
&& archive_format != USTAR_FORMAT
- && archive_format != GNU_FORMAT
- && archive_format != OLDGNU_FORMAT)
+ && archive_format != GNU_FORMAT)
{
negative = v < 0;
u = v;
diff --git a/src/list.c b/src/list.c
index 2436901..bba430a 100644
--- a/src/list.c
+++ b/src/list.c
@@ -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