mirror of
https://github.com/MidnightCommander/mc
synced 2024-12-22 20:36:50 +03:00
Ticket #1952: tar: support long file names in archive.
Initial changeset: tar.c: update code to be close to GNU tar. Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
parent
86a9e0be2c
commit
78a25f7800
@ -255,6 +255,8 @@ AC_TYPE_MODE_T
|
|||||||
gl_PROMOTED_TYPE_MODE_T
|
gl_PROMOTED_TYPE_MODE_T
|
||||||
AC_TYPE_PID_T
|
AC_TYPE_PID_T
|
||||||
AC_TYPE_UID_T
|
AC_TYPE_UID_T
|
||||||
|
AC_CHECK_TYPE([major_t], [], [AC_DEFINE([major_t], [int], [Type of major device numbers.])])
|
||||||
|
AC_CHECK_TYPE([minor_t], [], [AC_DEFINE([minor_t], [int], [Type of minor device numbers.])])
|
||||||
|
|
||||||
AC_STRUCT_ST_BLOCKS
|
AC_STRUCT_ST_BLOCKS
|
||||||
AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev, struct stat.st_mtim])
|
AC_CHECK_MEMBERS([struct stat.st_blksize, struct stat.st_rdev, struct stat.st_mtim])
|
||||||
|
@ -37,10 +37,14 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h> /* isspace() */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <inttypes.h> /* uintmax_t */
|
||||||
|
#include <limits.h> /* CHAR_BIT, INT_MAX, etc */
|
||||||
|
#include <stdint.h> /* UINTMAX_MAX, etc */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <string.h> /* memset() */
|
||||||
|
|
||||||
#ifdef hpux
|
#ifdef hpux
|
||||||
/* major() and minor() macros (among other things) defined here for hpux */
|
/* major() and minor() macros (among other things) defined here for hpux */
|
||||||
@ -135,6 +139,41 @@
|
|||||||
|
|
||||||
#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
|
#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
|
||||||
|
|
||||||
|
/* Log base 2 of common values. */
|
||||||
|
#define LG_8 3
|
||||||
|
#define LG_64 6
|
||||||
|
#define LG_256 8
|
||||||
|
|
||||||
|
/* Bits used in the mode field, values in octal. */
|
||||||
|
#define TSUID 04000 /* set UID on execution */
|
||||||
|
#define TSGID 02000 /* set GID on execution */
|
||||||
|
#define TSVTX 01000 /* reserved */
|
||||||
|
/* file permissions */
|
||||||
|
#define TUREAD 00400 /* read by owner */
|
||||||
|
#define TUWRITE 00200 /* write by owner */
|
||||||
|
#define TUEXEC 00100 /* execute/search by owner */
|
||||||
|
#define TGREAD 00040 /* read by group */
|
||||||
|
#define TGWRITE 00020 /* write by group */
|
||||||
|
#define TGEXEC 00010 /* execute/search by group */
|
||||||
|
#define TOREAD 00004 /* read by other */
|
||||||
|
#define TOWRITE 00002 /* write by other */
|
||||||
|
#define TOEXEC 00001 /* execute/search by other */
|
||||||
|
|
||||||
|
/* These macros work even on ones'-complement hosts (!).
|
||||||
|
The extra casts work around some compiler bugs. */
|
||||||
|
#define TYPE_SIGNED(t) (!((t) 0 < (t) (-1)))
|
||||||
|
#define TYPE_MINIMUM(t) (TYPE_SIGNED (t) ? ~(t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)
|
||||||
|
#define TYPE_MAXIMUM(t) (~(t) 0 - TYPE_MINIMUM (t))
|
||||||
|
|
||||||
|
#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,hbits) mode_from_header (where, sizeof (where), hbits)
|
||||||
|
#define OFF_FROM_HEADER(where) off_from_header (where, sizeof (where))
|
||||||
|
#define TIME_FROM_HEADER(where) time_from_header (where, sizeof (where))
|
||||||
|
#define UID_FROM_HEADER(where) uid_from_header (where, sizeof (where))
|
||||||
|
#define UINTMAX_FROM_HEADER(where) uintmax_from_header (where, sizeof (where))
|
||||||
|
|
||||||
/*** file scope type declarations ****************************************************************/
|
/*** file scope type declarations ****************************************************************/
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
@ -247,6 +286,19 @@ typedef struct
|
|||||||
|
|
||||||
/*** file scope variables ************************************************************************/
|
/*** file scope variables ************************************************************************/
|
||||||
|
|
||||||
|
/* Base 64 digits; see RFC 2045 Table 1. */
|
||||||
|
static char const base_64_digits[64] = {
|
||||||
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||||
|
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||||
|
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Table of base 64 digit values indexed by unsigned chars.
|
||||||
|
The value is 64 for unsigned chars that are not base 64 digits. */
|
||||||
|
static char base64_map[1 + (unsigned char) (-1)];
|
||||||
|
|
||||||
static struct vfs_s_subclass tarfs_subclass;
|
static struct vfs_s_subclass tarfs_subclass;
|
||||||
static struct vfs_class *vfs_tarfs_ops = VFS_CLASS (&tarfs_subclass);
|
static struct vfs_class *vfs_tarfs_ops = VFS_CLASS (&tarfs_subclass);
|
||||||
|
|
||||||
@ -258,33 +310,292 @@ static union block block_buf;
|
|||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
/*** file scope functions ************************************************************************/
|
/*** file scope functions ************************************************************************/
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
/**
|
|
||||||
* Quick and dirty octal conversion.
|
static void
|
||||||
*
|
tar_base64_init (void)
|
||||||
* Result is -1 if the field is invalid (all blank, or nonoctal).
|
|
||||||
*/
|
|
||||||
static long
|
|
||||||
tar_from_oct (int digs, const char *where)
|
|
||||||
{
|
{
|
||||||
long value;
|
size_t i;
|
||||||
|
|
||||||
|
memset (base64_map, 64, sizeof base64_map);
|
||||||
|
for (i = 0; i < 64; i++)
|
||||||
|
base64_map[(int) base_64_digits[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent @n using a signed integer I such that (uintmax_t) I == @n.
|
||||||
|
With a good optimizing compiler, this is equivalent to (intmax_t) i
|
||||||
|
and requires zero machine instructions. */
|
||||||
|
#if !(UINTMAX_MAX / 2 <= INTMAX_MAX)
|
||||||
|
#error "tar_represent_uintmax() returns intmax_t to represent uintmax_t"
|
||||||
|
#endif
|
||||||
|
static inline intmax_t
|
||||||
|
tar_represent_uintmax (uintmax_t n)
|
||||||
|
{
|
||||||
|
if (n <= INTMAX_MAX)
|
||||||
|
return n;
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Avoid signed integer overflow on picky platforms. */
|
||||||
|
intmax_t nd = n - INTMAX_MIN;
|
||||||
|
return nd + INTMAX_MIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Convert buffer at @where0 of size @digs from external format to intmax_t.
|
||||||
|
* @digs must be positive.
|
||||||
|
* If @type is non-NULL, data are of type @type.
|
||||||
|
* The buffer must represent a value in the range -@minval through @maxval;
|
||||||
|
* if the mathematically correct result V would be greater than INTMAX_MAX,
|
||||||
|
* return a negative integer V such that (uintmax_t) V yields the correct result.
|
||||||
|
* If @octal_only, allow only octal numbers instead of the other GNU extensions.
|
||||||
|
*
|
||||||
|
* Result is -1 if the field is invalid.
|
||||||
|
*/
|
||||||
|
#if !(INTMAX_MAX <= UINTMAX_MAX && - (INTMAX_MIN + 1) <= UINTMAX_MAX)
|
||||||
|
#error "tar_from_header() internally represents intmax_t as uintmax_t + sign"
|
||||||
|
#endif
|
||||||
|
#if !(UINTMAX_MAX / 2 <= INTMAX_MAX)
|
||||||
|
#error "tar_from_header() returns intmax_t to represent uintmax_t"
|
||||||
|
#endif
|
||||||
|
static intmax_t
|
||||||
|
tar_from_header (const char *where0, size_t digs, char const *type, intmax_t minval,
|
||||||
|
uintmax_t maxval, gboolean octal_only)
|
||||||
|
{
|
||||||
|
uintmax_t value = 0;
|
||||||
|
uintmax_t uminval = minval;
|
||||||
|
uintmax_t minus_minval = -uminval;
|
||||||
|
const char *where = where0;
|
||||||
|
char const *lim = where + digs;
|
||||||
|
gboolean negative = FALSE;
|
||||||
|
|
||||||
|
/* Accommodate buggy tar of unknown vintage, which outputs leading
|
||||||
|
NUL if the previous field overflows. */
|
||||||
|
if (*where == '\0')
|
||||||
|
where++;
|
||||||
|
|
||||||
|
/* Accommodate older tars, which output leading spaces. */
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
if (where == lim)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (!isspace ((unsigned char) *where))
|
||||||
|
break;
|
||||||
|
|
||||||
while (isspace ((unsigned char) *where))
|
|
||||||
{ /* Skip spaces */
|
|
||||||
where++;
|
where++;
|
||||||
if (--digs <= 0)
|
|
||||||
return -1; /* All blank field */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isodigit (*where))
|
||||||
|
{
|
||||||
|
char const *where1 = where;
|
||||||
|
gboolean overflow = FALSE;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
value += *where++ - '0';
|
||||||
|
if (where == lim || !isodigit (*where))
|
||||||
|
break;
|
||||||
|
overflow |= value != (value << LG_8 >> LG_8);
|
||||||
|
value <<= LG_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse the output of older, unportable tars, which generate
|
||||||
|
negative values in two's complement octal. If the leading
|
||||||
|
nonzero digit is 1, we can't recover the original value
|
||||||
|
reliably; so do this only if the digit is 2 or more. This
|
||||||
|
catches the common case of 32-bit negative time stamps. */
|
||||||
|
if ((overflow || maxval < value) && *where1 >= 2 && type != NULL)
|
||||||
|
{
|
||||||
|
/* Compute the negative of the input value, assuming two's complement. */
|
||||||
|
int digit;
|
||||||
|
|
||||||
|
digit = (*where1 - '0') | 4;
|
||||||
|
overflow = FALSE;
|
||||||
value = 0;
|
value = 0;
|
||||||
while (digs > 0 && isodigit (*where))
|
where = where1;
|
||||||
{ /* Scan till nonoctal */
|
|
||||||
value = (value << 3) | (*where++ - '0');
|
while (TRUE)
|
||||||
--digs;
|
{
|
||||||
|
value += 7 - digit;
|
||||||
|
where++;
|
||||||
|
if (where == lim || !isodigit (*where))
|
||||||
|
break;
|
||||||
|
digit = *where - '0';
|
||||||
|
overflow |= value != (value << LG_8 >> LG_8);
|
||||||
|
value <<= LG_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (digs > 0 && *where && !isspace ((unsigned char) *where))
|
value++;
|
||||||
return -1; /* Ended on non-space/nul */
|
overflow |= value == 0;
|
||||||
|
|
||||||
return value;
|
if (!overflow && value <= minus_minval)
|
||||||
|
negative = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (overflow)
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
else if (octal_only)
|
||||||
|
{
|
||||||
|
/* Suppress the following extensions. */
|
||||||
|
}
|
||||||
|
else if (*where == '-' || *where == '+')
|
||||||
|
{
|
||||||
|
/* Parse base-64 output produced only by tar test versions
|
||||||
|
1.13.6 (1999-08-11) through 1.13.11 (1999-08-23).
|
||||||
|
Support for this will be withdrawn in future tar releases. */
|
||||||
|
int dig;
|
||||||
|
|
||||||
|
negative = *where++ == '-';
|
||||||
|
|
||||||
|
while (where != lim && (dig = base64_map[(unsigned char) *where]) < 64)
|
||||||
|
{
|
||||||
|
if (value << LG_64 >> LG_64 != value)
|
||||||
|
return (-1);
|
||||||
|
value = (value << LG_64) | dig;
|
||||||
|
where++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (where <= lim - 2 && (*where == '\200' /* positive base-256 */
|
||||||
|
|| *where == '\377' /* negative base-256 */ ))
|
||||||
|
{
|
||||||
|
/* Parse base-256 output. A nonnegative number N is
|
||||||
|
represented as (256**DIGS)/2 + N; a negative number -N is
|
||||||
|
represented as (256**DIGS) - N, i.e. as two's complement.
|
||||||
|
The representation guarantees that the leading bit is
|
||||||
|
always on, so that we don't confuse this format with the
|
||||||
|
others (assuming ASCII bytes of 8 bits or more). */
|
||||||
|
|
||||||
|
int signbit;
|
||||||
|
uintmax_t topbits;
|
||||||
|
|
||||||
|
signbit = *where & (1 << (LG_256 - 2));
|
||||||
|
topbits =
|
||||||
|
(((uintmax_t) - signbit) << (CHAR_BIT * sizeof (uintmax_t) - LG_256 - (LG_256 - 2)));
|
||||||
|
|
||||||
|
value = (*where++ & ((1 << (LG_256 - 2)) - 1)) - signbit;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
value = (value << LG_256) + (unsigned char) *where++;
|
||||||
|
if (where == lim)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (((value << LG_256 >> LG_256) | topbits) != value)
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
negative = signbit != 0;
|
||||||
|
if (negative)
|
||||||
|
value = -value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (where != lim && *where != '\0' && !isspace ((unsigned char) *where))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (value <= (negative ? minus_minval : maxval))
|
||||||
|
return tar_represent_uintmax (negative ? -value : value);
|
||||||
|
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline gid_t
|
||||||
|
gid_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
return tar_from_header (p, s, "gid_t", TYPE_MINIMUM (gid_t), TYPE_MAXIMUM (gid_t), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline major_t
|
||||||
|
major_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
return tar_from_header (p, s, "major_t", TYPE_MINIMUM (major_t), TYPE_MAXIMUM (major_t), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline minor_t
|
||||||
|
minor_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
return tar_from_header (p, s, "minor_t", TYPE_MINIMUM (minor_t), TYPE_MAXIMUM (minor_t), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert @p to the file mode, as understood by tar.
|
||||||
|
* Store unrecognized mode bits (from 10th up) in @hbits.
|
||||||
|
* Set *hbits if there are any unrecognized bits.
|
||||||
|
* */
|
||||||
|
static inline mode_t
|
||||||
|
mode_from_header (const char *p, size_t s, gboolean * hbits)
|
||||||
|
{
|
||||||
|
unsigned int u;
|
||||||
|
mode_t mode;
|
||||||
|
|
||||||
|
/* Do not complain about unrecognized mode bits. */
|
||||||
|
u = tar_from_header (p, s, "mode_t", INTMAX_MIN, UINTMAX_MAX, FALSE);
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
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));
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
if (hbits != NULL)
|
||||||
|
*hbits = (u & ~07777) != 0;
|
||||||
|
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline off_t
|
||||||
|
off_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
/* Negative offsets are not allowed in tar files, so invoke
|
||||||
|
from_header with minimum value 0, not TYPE_MINIMUM (off_t). */
|
||||||
|
return tar_from_header (p, s, "off_t", 0, TYPE_MAXIMUM (off_t), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline time_t
|
||||||
|
time_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
return tar_from_header (p, s, "time_t", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline uid_t
|
||||||
|
uid_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
return tar_from_header (p, s, "uid_t", TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t), FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static inline uintmax_t
|
||||||
|
uintmax_from_header (const char *p, size_t s)
|
||||||
|
{
|
||||||
|
return tar_from_header (p, s, "uintmax_t", 0, UINTMAX_MAX, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
@ -325,7 +636,7 @@ tar_checksum (const union block *header)
|
|||||||
int unsigned_sum = 0; /* the POSIX one :-) */
|
int unsigned_sum = 0; /* the POSIX one :-) */
|
||||||
int signed_sum = 0; /* the Sun one :-( */
|
int signed_sum = 0; /* the Sun one :-( */
|
||||||
int recorded_sum;
|
int recorded_sum;
|
||||||
long parsed_sum;
|
int parsed_sum;
|
||||||
const char *p = header->buffer;
|
const char *p = header->buffer;
|
||||||
|
|
||||||
for (i = sizeof (*header); i-- != 0;)
|
for (i = sizeof (*header); i-- != 0;)
|
||||||
@ -347,8 +658,10 @@ tar_checksum (const union block *header)
|
|||||||
unsigned_sum += ' ' * sizeof (header->header.chksum);
|
unsigned_sum += ' ' * sizeof (header->header.chksum);
|
||||||
signed_sum += ' ' * sizeof (header->header.chksum);
|
signed_sum += ' ' * sizeof (header->header.chksum);
|
||||||
|
|
||||||
parsed_sum = tar_from_oct (8, header->header.chksum);
|
parsed_sum =
|
||||||
if (parsed_sum == -1)
|
tar_from_header (header->header.chksum, sizeof (header->header.chksum), NULL, 0,
|
||||||
|
INT_MAX, TRUE);
|
||||||
|
if (parsed_sum < 0)
|
||||||
return HEADER_FAILURE;
|
return HEADER_FAILURE;
|
||||||
|
|
||||||
recorded_sum = parsed_sum;
|
recorded_sum = parsed_sum;
|
||||||
@ -404,7 +717,7 @@ tar_decode_header (union block *header, tar_super_t * arch)
|
|||||||
if (header->header.typeflag == LNKTYPE || header->header.typeflag == DIRTYPE)
|
if (header->header.typeflag == LNKTYPE || header->header.typeflag == DIRTYPE)
|
||||||
size = 0; /* Links 0 size on tape */
|
size = 0; /* Links 0 size on tape */
|
||||||
else
|
else
|
||||||
size = tar_from_oct (1 + 12, header->header.size);
|
size = OFF_FROM_HEADER (header->header.size);
|
||||||
|
|
||||||
if (header->header.typeflag == GNUTYPE_DUMPDIR)
|
if (header->header.typeflag == GNUTYPE_DUMPDIR)
|
||||||
if (arch->type == TAR_UNKNOWN)
|
if (arch->type == TAR_UNKNOWN)
|
||||||
@ -420,7 +733,7 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union block *header
|
|||||||
{
|
{
|
||||||
tar_super_t *arch = TAR_SUPER (archive);
|
tar_super_t *arch = TAR_SUPER (archive);
|
||||||
|
|
||||||
st->st_mode = tar_from_oct (8, header->header.mode);
|
st->st_mode = MODE_FROM_HEADER (header->header.mode, NULL);
|
||||||
|
|
||||||
/* Adjust st->st_mode because there are tar-files with
|
/* Adjust st->st_mode because there are tar-files with
|
||||||
* typeflag==SYMTYPE and S_ISLNK(mod)==0. I don't
|
* typeflag==SYMTYPE and S_ISLNK(mod)==0. I don't
|
||||||
@ -453,10 +766,10 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union block *header
|
|||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
st->st_uid = *header->header.uname != '\0'
|
st->st_uid = *header->header.uname != '\0'
|
||||||
? (uid_t) vfs_finduid (header->header.uname)
|
? (uid_t) vfs_finduid (header->header.uname)
|
||||||
: tar_from_oct (8, header->header.uid);
|
: UID_FROM_HEADER (header->header.uid);
|
||||||
st->st_gid = *header->header.gname != '\0'
|
st->st_gid = *header->header.gname != '\0'
|
||||||
? (gid_t) vfs_findgid (header->header.gname)
|
? (gid_t) vfs_findgid (header->header.gname)
|
||||||
: tar_from_oct (8,header->header.gid);
|
: GID_FROM_HEADER (header->header.gid);
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
switch (header->header.typeflag)
|
switch (header->header.typeflag)
|
||||||
@ -465,8 +778,8 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union block *header
|
|||||||
case CHRTYPE:
|
case CHRTYPE:
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_RDEV
|
#ifdef HAVE_STRUCT_STAT_ST_RDEV
|
||||||
st->st_rdev =
|
st->st_rdev =
|
||||||
makedev (tar_from_oct (8, header->header.devmajor),
|
makedev (MAJOR_FROM_HEADER (header->header.devmajor),
|
||||||
tar_from_oct (8, header->header.devminor));
|
MINOR_FROM_HEADER (header->header.devminor));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -475,8 +788,8 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union block *header
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
st->st_uid = tar_from_oct (8, header->header.uid);
|
st->st_uid = UID_FROM_HEADER (header->header.uid);
|
||||||
st->st_gid = tar_from_oct (8, header->header.gid);
|
st->st_gid = GID_FROM_HEADER (header->header.gid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,13 +797,13 @@ tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union block *header
|
|||||||
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||||
st->st_atim.tv_nsec = st->st_mtim.tv_nsec = st->st_ctim.tv_nsec = 0;
|
st->st_atim.tv_nsec = st->st_mtim.tv_nsec = st->st_ctim.tv_nsec = 0;
|
||||||
#endif
|
#endif
|
||||||
st->st_mtime = tar_from_oct (1 + 12, header->header.mtime);
|
st->st_mtime = TIME_FROM_HEADER (header->header.mtime);
|
||||||
st->st_atime = 0;
|
st->st_atime = 0;
|
||||||
st->st_ctime = 0;
|
st->st_ctime = 0;
|
||||||
if (arch->type == TAR_GNU)
|
if (arch->type == TAR_GNU)
|
||||||
{
|
{
|
||||||
st->st_atime = tar_from_oct (1 + 12, header->oldgnu_header.atime);
|
st->st_atime = TIME_FROM_HEADER (header->oldgnu_header.atime);
|
||||||
st->st_ctime = tar_from_oct (1 + 12, header->oldgnu_header.ctime);
|
st->st_ctime = TIME_FROM_HEADER (header->oldgnu_header.ctime);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||||
@ -991,6 +1304,8 @@ vfs_init_tarfs (void)
|
|||||||
tarfs_subclass.free_archive = tar_free_archive;
|
tarfs_subclass.free_archive = tar_free_archive;
|
||||||
tarfs_subclass.fh_open = tar_fh_open;
|
tarfs_subclass.fh_open = tar_fh_open;
|
||||||
vfs_register_class (vfs_tarfs_ops);
|
vfs_register_class (vfs_tarfs_ops);
|
||||||
|
|
||||||
|
tar_base64_init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
Loading…
Reference in New Issue
Block a user