diff options
author | kientzle <kientzle@FreeBSD.org> | 2007-05-29 01:00:21 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2007-05-29 01:00:21 +0000 |
commit | 013be331bc10706807599a452a143f4744398e9f (patch) | |
tree | 793787ab8615d768ba51341dfd934a5fb3039728 /lib/libarchive/archive_read_support_format_tar.c | |
parent | c611006e893ac2bf962cabe02743954e3b3c3314 (diff) | |
download | FreeBSD-src-013be331bc10706807599a452a143f4744398e9f.zip FreeBSD-src-013be331bc10706807599a452a143f4744398e9f.tar.gz |
libarchive 2.2.3
* "compression_program" support uses an external program
* Portability: no longer uses "struct stat" as a primary
data interchange structure internally
* Part of the above: refactor archive_entry to separate
out copy_stat() and stat() functions
* More complete tests for archive_entry
* Finish archive_entry_clone()
* Isolate major()/minor()/makedev() in archive_entry; remove
these from everywhere else.
* Bug fix: properly handle decompression look-ahead at end-of-data
* Bug fixes to 'ar' support
* Fix memory leak in ZIP reader
* Portability: better timegm() emulation in iso9660 reader
* New write_disk flags to suppress auto dir creation and not
overwrite newer files (for future cpio front-end)
* Simplify trailing-'/' fixup when writing tar and pax
* Test enhancements: fix various compiler warnings, improve
portability, add lots of new tests.
* Documentation: document new functions, first draft of
libarchive_internals.3
MFC after: 14 days
Thanks to: Joerg Sonnenberger (compression_program)
Thanks to: Kai Wang (ar)
Thanks to: Colin Percival (many small fixes)
Thanks to: Many others who sent me various patches and problem reports.
Diffstat (limited to 'lib/libarchive/archive_read_support_format_tar.c')
-rw-r--r-- | lib/libarchive/archive_read_support_format_tar.c | 279 |
1 files changed, 129 insertions, 150 deletions
diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c index d778b9d..c05a415 100644 --- a/lib/libarchive/archive_read_support_format_tar.c +++ b/lib/libarchive/archive_read_support_format_tar.c @@ -26,16 +26,6 @@ #include "archive_platform.h" __FBSDID("$FreeBSD$"); -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef MAJOR_IN_MKDEV -#include <sys/mkdev.h> -#else -#ifdef MAJOR_IN_SYSMACROS -#include <sys/sysmacros.h> -#endif -#endif #ifdef HAVE_ERRNO_H #include <errno.h> #endif @@ -47,9 +37,6 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_STRING_H #include <string.h> #endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif /* Obtain suitable wide-character manipulation functions. */ #ifdef HAVE_WCHAR_H @@ -180,25 +167,25 @@ static int gnu_read_sparse_data(struct archive_read *, struct tar *, static void gnu_parse_sparse_data(struct archive_read *, struct tar *, const struct gnu_sparse *sparse, int length); static int header_Solaris_ACL(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *); + struct archive_entry *, const void *); static int header_common(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *); + struct archive_entry *, const void *); static int header_old_tar(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *); + struct archive_entry *, const void *); static int header_pax_extensions(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *); + struct archive_entry *, const void *); static int header_pax_global(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *h); + struct archive_entry *, const void *h); static int header_longlink(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *h); + struct archive_entry *, const void *h); static int header_longname(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *h); + struct archive_entry *, const void *h); static int header_volume(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *h); + struct archive_entry *, const void *h); static int header_ustar(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *h); + struct archive_entry *, const void *h); static int header_gnutar(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, const void *h); + struct archive_entry *, const void *h); static int archive_read_format_tar_bid(struct archive_read *); static int archive_read_format_tar_cleanup(struct archive_read *); static int archive_read_format_tar_read_data(struct archive_read *a, @@ -207,10 +194,10 @@ static int archive_read_format_tar_skip(struct archive_read *a); static int archive_read_format_tar_read_header(struct archive_read *, struct archive_entry *); static int checksum(struct archive_read *, const void *); -static int pax_attribute(struct archive_entry *, struct stat *, +static int pax_attribute(struct archive_entry *, wchar_t *key, wchar_t *value); static int pax_header(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *, char *attr); + struct archive_entry *, char *attr); static void pax_time(const wchar_t *, int64_t *sec, long *nanos); static int read_body_to_string(struct archive_read *, struct tar *, struct archive_string *, const void *h); @@ -219,7 +206,7 @@ static int64_t tar_atol10(const wchar_t *, unsigned); static int64_t tar_atol256(const char *, unsigned); static int64_t tar_atol8(const char *, unsigned); static int tar_read_header(struct archive_read *, struct tar *, - struct archive_entry *, struct stat *); + struct archive_entry *); static int tohex(int c); static char *url_decode(const char *); static int utf8_decode(wchar_t *, const char *, size_t length); @@ -264,7 +251,7 @@ archive_read_format_tar_cleanup(struct archive_read *a) { struct tar *tar; - tar = (struct tar *)*(a->pformat_data); + tar = (struct tar *)(a->format->data); archive_string_free(&tar->acl_text); archive_string_free(&tar->entry_name); archive_string_free(&tar->entry_linkname); @@ -275,7 +262,7 @@ archive_read_format_tar_cleanup(struct archive_read *a) if (tar->pax_entry != NULL) free(tar->pax_entry); free(tar); - *(a->pformat_data) = NULL; + (a->format->data) = NULL; return (ARCHIVE_OK); } @@ -307,8 +294,8 @@ archive_read_format_tar_bid(struct archive_read *a) bid++; /* Now let's look at the actual header and see if it matches. */ - if (a->compression_read_ahead != NULL) - bytes_read = (a->compression_read_ahead)(a, &h, 512); + if (a->decompressor->read_ahead != NULL) + bytes_read = (a->decompressor->read_ahead)(a, &h, 512); else bytes_read = 0; /* Empty file. */ if (bytes_read < 0) @@ -412,26 +399,24 @@ archive_read_format_tar_read_header(struct archive_read *a, */ static int default_inode; static int default_dev; - struct stat st; struct tar *tar; const char *p; int r; size_t l; - memset(&st, 0, sizeof(st)); /* Assign default device/inode values. */ - st.st_dev = 1 + default_dev; /* Don't use zero. */ - st.st_ino = ++default_inode; /* Don't use zero. */ + archive_entry_set_dev(entry, 1 + default_dev); /* Don't use zero. */ + archive_entry_set_ino(entry, ++default_inode); /* Don't use zero. */ /* Limit generated st_ino number to 16 bits. */ if (default_inode >= 0xffff) { ++default_dev; default_inode = 0; } - tar = (struct tar *)*(a->pformat_data); + tar = (struct tar *)(a->format->data); tar->entry_offset = 0; - r = tar_read_header(a, tar, entry, &st); + r = tar_read_header(a, tar, entry); if (r == ARCHIVE_OK) { /* @@ -441,13 +426,9 @@ archive_read_format_tar_read_header(struct archive_read *a, */ p = archive_entry_pathname(entry); l = strlen(p); - if (S_ISREG(st.st_mode) && p[l-1] == '/') { - st.st_mode &= ~S_IFMT; - st.st_mode |= S_IFDIR; - } - - /* Copy the final stat data into the entry. */ - archive_entry_copy_stat(entry, &st); + if (archive_entry_filetype(entry) == AE_IFREG + && p[l-1] == '/') + archive_entry_set_filetype(entry, AE_IFDIR); } return (r); } @@ -460,7 +441,7 @@ archive_read_format_tar_read_data(struct archive_read *a, struct tar *tar; struct sparse_block *p; - tar = (struct tar *)*(a->pformat_data); + tar = (struct tar *)(a->format->data); if (tar->sparse_list != NULL) { /* Remove exhausted entries from sparse list. */ while (tar->sparse_list != NULL && @@ -476,7 +457,7 @@ archive_read_format_tar_read_data(struct archive_read *a, } if (tar->entry_bytes_remaining > 0) { - bytes_read = (a->compression_read_ahead)(a, buff, 1); + bytes_read = (a->decompressor->read_ahead)(a, buff, 1); if (bytes_read == 0) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Truncated tar archive"); @@ -499,10 +480,10 @@ archive_read_format_tar_read_data(struct archive_read *a, *offset = tar->entry_offset; tar->entry_offset += bytes_read; tar->entry_bytes_remaining -= bytes_read; - (a->compression_read_consume)(a, bytes_read); + (a->decompressor->consume)(a, bytes_read); return (ARCHIVE_OK); } else { - if ((a->compression_skip)(a, tar->entry_padding) < 0) + if ((a->decompressor->skip)(a, tar->entry_padding) < 0) return (ARCHIVE_FATAL); tar->entry_padding = 0; *buff = NULL; @@ -519,14 +500,14 @@ archive_read_format_tar_skip(struct archive_read *a) struct tar* tar; struct sparse_block *p; - tar = (struct tar *)*(a->pformat_data); + tar = (struct tar *)(a->format->data); /* * Compression layer skip functions are required to either skip the * length requested or fail, so we can rely upon the entire entry * plus padding being skipped. */ - bytes_skipped = (a->compression_skip)(a, tar->entry_bytes_remaining + + bytes_skipped = (a->decompressor->skip)(a, tar->entry_bytes_remaining + tar->entry_padding); if (bytes_skipped < 0) return (ARCHIVE_FATAL); @@ -550,7 +531,7 @@ archive_read_format_tar_skip(struct archive_read *a) */ static int tar_read_header(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st) + struct archive_entry *entry) { ssize_t bytes; int err; @@ -558,7 +539,7 @@ tar_read_header(struct archive_read *a, struct tar *tar, const struct archive_entry_header_ustar *header; /* Read 512-byte header record */ - bytes = (a->compression_read_ahead)(a, &h, 512); + bytes = (a->decompressor->read_ahead)(a, &h, 512); if (bytes < 512) { /* * If we're here, it's becase the _bid function accepted @@ -567,14 +548,14 @@ tar_read_header(struct archive_read *a, struct tar *tar, */ return (ARCHIVE_EOF); } - (a->compression_read_consume)(a, 512); + (a->decompressor->consume)(a, 512); /* Check for end-of-archive mark. */ if (((*(const char *)h)==0) && archive_block_is_null((const unsigned char *)h)) { /* Try to consume a second all-null record, as well. */ - bytes = (a->compression_read_ahead)(a, &h, 512); + bytes = (a->decompressor->read_ahead)(a, &h, 512); if (bytes > 0) - (a->compression_read_consume)(a, bytes); + (a->decompressor->consume)(a, bytes); archive_set_error(&a->archive, 0, NULL); return (ARCHIVE_EOF); } @@ -602,48 +583,48 @@ tar_read_header(struct archive_read *a, struct tar *tar, case 'A': /* Solaris tar ACL */ a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; a->archive.archive_format_name = "Solaris tar"; - err = header_Solaris_ACL(a, tar, entry, st, h); + err = header_Solaris_ACL(a, tar, entry, h); break; case 'g': /* POSIX-standard 'g' header. */ a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; a->archive.archive_format_name = "POSIX pax interchange format"; - err = header_pax_global(a, tar, entry, st, h); + err = header_pax_global(a, tar, entry, h); break; case 'K': /* Long link name (GNU tar, others) */ - err = header_longlink(a, tar, entry, st, h); + err = header_longlink(a, tar, entry, h); break; case 'L': /* Long filename (GNU tar, others) */ - err = header_longname(a, tar, entry, st, h); + err = header_longname(a, tar, entry, h); break; case 'V': /* GNU volume header */ - err = header_volume(a, tar, entry, st, h); + err = header_volume(a, tar, entry, h); break; case 'X': /* Used by SUN tar; same as 'x'. */ a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; a->archive.archive_format_name = "POSIX pax interchange format (Sun variant)"; - err = header_pax_extensions(a, tar, entry, st, h); + err = header_pax_extensions(a, tar, entry, h); break; case 'x': /* POSIX-standard 'x' header. */ a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; a->archive.archive_format_name = "POSIX pax interchange format"; - err = header_pax_extensions(a, tar, entry, st, h); + err = header_pax_extensions(a, tar, entry, h); break; default: if (memcmp(header->magic, "ustar \0", 8) == 0) { a->archive.archive_format = ARCHIVE_FORMAT_TAR_GNUTAR; a->archive.archive_format_name = "GNU tar format"; - err = header_gnutar(a, tar, entry, st, h); + err = header_gnutar(a, tar, entry, h); } else if (memcmp(header->magic, "ustar", 5) == 0) { if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE) { a->archive.archive_format = ARCHIVE_FORMAT_TAR_USTAR; a->archive.archive_format_name = "POSIX ustar format"; } - err = header_ustar(a, tar, entry, st, h); + err = header_ustar(a, tar, entry, h); } else { a->archive.archive_format = ARCHIVE_FORMAT_TAR; a->archive.archive_format_name = "tar (non-POSIX)"; - err = header_old_tar(a, tar, entry, st, h); + err = header_old_tar(a, tar, entry, h); } } --tar->header_recursion_depth; @@ -716,14 +697,14 @@ archive_block_is_null(const unsigned char *p) */ static int header_Solaris_ACL(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) + struct archive_entry *entry, const void *h) { int err, err2; char *p; wchar_t *wp; err = read_body_to_string(a, tar, &(tar->acl_text), h); - err2 = tar_read_header(a, tar, entry, st); + err2 = tar_read_header(a, tar, entry); err = err_combine(err, err2); /* XXX Ensure p doesn't overrun acl_text */ @@ -752,12 +733,12 @@ header_Solaris_ACL(struct archive_read *a, struct tar *tar, */ static int header_longlink(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) + struct archive_entry *entry, const void *h) { int err, err2; err = read_body_to_string(a, tar, &(tar->longlink), h); - err2 = tar_read_header(a, tar, entry, st); + err2 = tar_read_header(a, tar, entry); if (err == ARCHIVE_OK && err2 == ARCHIVE_OK) { /* Set symlink if symlink already set, else hardlink. */ archive_entry_set_link(entry, tar->longlink.s); @@ -770,13 +751,13 @@ header_longlink(struct archive_read *a, struct tar *tar, */ static int header_longname(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) + struct archive_entry *entry, const void *h) { int err, err2; err = read_body_to_string(a, tar, &(tar->longname), h); /* Read and parse "real" header, then override name. */ - err2 = tar_read_header(a, tar, entry, st); + err2 = tar_read_header(a, tar, entry); if (err == ARCHIVE_OK && err2 == ARCHIVE_OK) archive_entry_set_pathname(entry, tar->longname.s); return (err_combine(err, err2)); @@ -788,12 +769,12 @@ header_longname(struct archive_read *a, struct tar *tar, */ static int header_volume(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) + struct archive_entry *entry, const void *h) { (void)h; /* Just skip this and read the next header. */ - return (tar_read_header(a, tar, entry, st)); + return (tar_read_header(a, tar, entry)); } /* @@ -818,12 +799,12 @@ read_body_to_string(struct archive_read *a, struct tar *tar, padded_size = (size + 511) & ~ 511; dest = as->s; while (padded_size > 0) { - bytes_read = (a->compression_read_ahead)(a, &src, padded_size); + bytes_read = (a->decompressor->read_ahead)(a, &src, padded_size); if (bytes_read < 0) return (ARCHIVE_FATAL); if (bytes_read > padded_size) bytes_read = padded_size; - (a->compression_read_consume)(a, bytes_read); + (a->decompressor->consume)(a, bytes_read); bytes_to_copy = bytes_read; if ((off_t)bytes_to_copy > size) bytes_to_copy = (ssize_t)size; @@ -847,8 +828,8 @@ read_body_to_string(struct archive_read *a, struct tar *tar, * common parsing into one place. */ static int -header_common(struct archive_read *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) +header_common(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) { const struct archive_entry_header_ustar *header; char tartype; @@ -863,15 +844,14 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent archive_string_empty(&(tar->entry_linkname)); /* Parse out the numeric fields (all are octal) */ - st->st_mode = tar_atol(header->mode, sizeof(header->mode)); - st->st_uid = tar_atol(header->uid, sizeof(header->uid)); - st->st_gid = tar_atol(header->gid, sizeof(header->gid)); - st->st_size = tar_atol(header->size, sizeof(header->size)); - st->st_mtime = tar_atol(header->mtime, sizeof(header->mtime)); + archive_entry_set_mode(entry, tar_atol(header->mode, sizeof(header->mode))); + archive_entry_set_uid(entry, tar_atol(header->uid, sizeof(header->uid))); + archive_entry_set_gid(entry, tar_atol(header->gid, sizeof(header->gid))); + archive_entry_set_size(entry, tar_atol(header->size, sizeof(header->size))); + archive_entry_set_mtime(entry, tar_atol(header->mtime, sizeof(header->mtime)), 0); /* Handle the tar type flag appropriately. */ tartype = header->typeflag[0]; - st->st_mode &= ~S_IFMT; switch (tartype) { case '1': /* Hard link */ @@ -885,8 +865,8 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent * implies that the underlying entry is a regular * file. */ - if (st->st_size > 0) - st->st_mode |= S_IFREG; + if (archive_entry_size(entry) > 0) + archive_entry_set_filetype(entry, AE_IFREG); /* * A tricky point: Traditionally, tar readers have @@ -910,31 +890,31 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent * we encounter a hardlink entry for a file that is * itself an uncompressed tar archive. */ - if (st->st_size > 0 && + if (archive_entry_size(entry) > 0 && a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE && archive_read_format_tar_bid(a) > 50) - st->st_size = 0; + archive_entry_set_size(entry, 0); break; case '2': /* Symlink */ - st->st_mode |= S_IFLNK; - st->st_size = 0; + archive_entry_set_filetype(entry, AE_IFLNK); + archive_entry_set_size(entry, 0); archive_entry_set_symlink(entry, tar->entry_linkname.s); break; case '3': /* Character device */ - st->st_mode |= S_IFCHR; - st->st_size = 0; + archive_entry_set_filetype(entry, AE_IFCHR); + archive_entry_set_size(entry, 0); break; case '4': /* Block device */ - st->st_mode |= S_IFBLK; - st->st_size = 0; + archive_entry_set_filetype(entry, AE_IFBLK); + archive_entry_set_size(entry, 0); break; case '5': /* Dir */ - st->st_mode |= S_IFDIR; - st->st_size = 0; + archive_entry_set_filetype(entry, AE_IFDIR); + archive_entry_set_size(entry, 0); break; case '6': /* FIFO device */ - st->st_mode |= S_IFIFO; - st->st_size = 0; + archive_entry_set_filetype(entry, AE_IFIFO); + archive_entry_set_size(entry, 0); break; case 'D': /* GNU incremental directory type */ /* @@ -942,7 +922,7 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent * It might be nice someday to preprocess the file list and * provide it to the client, though. */ - st->st_mode |= S_IFDIR; + archive_entry_set_filetype(entry, AE_IFDIR); break; case 'M': /* GNU "Multi-volume" (remainder of file from last archive)*/ /* @@ -956,7 +936,7 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent /* The body of this entry is a script for renaming * previously-extracted entries. Ugh. It will never * be supported by libarchive. */ - st->st_mode |= S_IFREG; + archive_entry_set_filetype(entry, AE_IFREG); break; case 'S': /* GNU sparse files */ /* @@ -969,7 +949,7 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent * Per POSIX: non-recognized types should always be * treated as regular files. */ - st->st_mode |= S_IFREG; + archive_entry_set_filetype(entry, AE_IFREG); break; } return (0); @@ -979,8 +959,8 @@ header_common(struct archive_read *a, struct tar *tar, struct archive_entry *ent * Parse out header elements for "old-style" tar archives. */ static int -header_old_tar(struct archive_read *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) +header_old_tar(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) { const struct archive_entry_header_ustar *header; @@ -990,9 +970,9 @@ header_old_tar(struct archive_read *a, struct tar *tar, struct archive_entry *en archive_entry_set_pathname(entry, tar->entry_name.s); /* Grab rest of common fields */ - header_common(a, tar, entry, st, h); + header_common(a, tar, entry, h); - tar->entry_bytes_remaining = st->st_size; + tar->entry_bytes_remaining = archive_entry_size(entry); tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); return (0); } @@ -1002,25 +982,25 @@ header_old_tar(struct archive_read *a, struct tar *tar, struct archive_entry *en */ static int header_pax_global(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) + struct archive_entry *entry, const void *h) { int err, err2; err = read_body_to_string(a, tar, &(tar->pax_global), h); - err2 = tar_read_header(a, tar, entry, st); + err2 = tar_read_header(a, tar, entry); return (err_combine(err, err2)); } static int header_pax_extensions(struct archive_read *a, struct tar *tar, - struct archive_entry *entry, struct stat *st, const void *h) + struct archive_entry *entry, const void *h) { int err, err2; read_body_to_string(a, tar, &(tar->pax_header), h); /* Parse the next header. */ - err = tar_read_header(a, tar, entry, st); + err = tar_read_header(a, tar, entry); /* * TODO: Parse global/default options into 'entry' struct here @@ -1032,9 +1012,9 @@ header_pax_extensions(struct archive_read *a, struct tar *tar, * and then skip any fields in the standard header that were * defined in the pax header. */ - err2 = pax_header(a, tar, entry, st, tar->pax_header.s); + err2 = pax_header(a, tar, entry, tar->pax_header.s); err = err_combine(err, err2); - tar->entry_bytes_remaining = st->st_size; + tar->entry_bytes_remaining = archive_entry_size(entry); tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); return (err); } @@ -1045,8 +1025,8 @@ header_pax_extensions(struct archive_read *a, struct tar *tar, * handles "pax" or "extended ustar" entries. */ static int -header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) +header_ustar(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) { const struct archive_entry_header_ustar *header; struct archive_string *as; @@ -1066,7 +1046,7 @@ header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entr archive_entry_set_pathname(entry, as->s); /* Handle rest of common fields. */ - header_common(a, tar, entry, st, h); + header_common(a, tar, entry, h); /* Handle POSIX ustar fields. */ archive_strncpy(&(tar->entry_uname), header->uname, @@ -1079,12 +1059,13 @@ header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entr /* Parse out device numbers only for char and block specials. */ if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { - st->st_rdev = makedev( - tar_atol(header->rdevmajor, sizeof(header->rdevmajor)), + archive_entry_set_rdevmajor(entry, + tar_atol(header->rdevmajor, sizeof(header->rdevmajor))); + archive_entry_set_rdevminor(entry, tar_atol(header->rdevminor, sizeof(header->rdevminor))); } - tar->entry_bytes_remaining = st->st_size; + tar->entry_bytes_remaining = archive_entry_size(entry); tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); return (0); @@ -1097,8 +1078,8 @@ header_ustar(struct archive_read *a, struct tar *tar, struct archive_entry *entr * Returns non-zero if there's an error in the data. */ static int -pax_header(struct archive_read *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, char *attr) +pax_header(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, char *attr) { size_t attr_length, l, line_length; char *line, *p; @@ -1179,7 +1160,7 @@ pax_header(struct archive_read *a, struct tar *tar, struct archive_entry *entry, value = wp + 1; /* Identify this attribute and set it in the entry. */ - err2 = pax_attribute(entry, st, key, value); + err2 = pax_attribute(entry, key, value); err = err_combine(err, err2); /* Skip to next line */ @@ -1240,7 +1221,7 @@ pax_attribute_xattr(struct archive_entry *entry, * any of them look useful. */ static int -pax_attribute(struct archive_entry *entry, struct stat *st, +pax_attribute(struct archive_entry *entry, wchar_t *key, wchar_t *value) { int64_t s; @@ -1266,32 +1247,28 @@ pax_attribute(struct archive_entry *entry, struct stat *st, __archive_entry_acl_parse_w(entry, value, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); else if (wcscmp(key, L"SCHILY.devmajor")==0) - st->st_rdev = makedev(tar_atol10(value, wcslen(value)), - minor(st->st_rdev)); + archive_entry_set_rdevmajor(entry, tar_atol10(value, wcslen(value))); else if (wcscmp(key, L"SCHILY.devminor")==0) - st->st_rdev = makedev(major(st->st_rdev), - tar_atol10(value, wcslen(value))); + archive_entry_set_rdevminor(entry, tar_atol10(value, wcslen(value))); else if (wcscmp(key, L"SCHILY.fflags")==0) archive_entry_copy_fflags_text_w(entry, value); else if (wcscmp(key, L"SCHILY.dev")==0) - st->st_dev = tar_atol10(value, wcslen(value)); + archive_entry_set_dev(entry, tar_atol10(value, wcslen(value))); else if (wcscmp(key, L"SCHILY.ino")==0) - st->st_ino = tar_atol10(value, wcslen(value)); + archive_entry_set_ino(entry, tar_atol10(value, wcslen(value))); else if (wcscmp(key, L"SCHILY.nlink")==0) - st->st_nlink = tar_atol10(value, wcslen(value)); + archive_entry_set_nlink(entry, tar_atol10(value, wcslen(value))); break; case 'a': if (wcscmp(key, L"atime")==0) { pax_time(value, &s, &n); - st->st_atime = s; - ARCHIVE_STAT_SET_ATIME_NANOS(st, n); + archive_entry_set_atime(entry, s, n); } break; case 'c': if (wcscmp(key, L"ctime")==0) { pax_time(value, &s, &n); - st->st_ctime = s; - ARCHIVE_STAT_SET_CTIME_NANOS(st, n); + archive_entry_set_ctime(entry, s, n); } else if (wcscmp(key, L"charset")==0) { /* TODO: Publish charset information in entry. */ } else if (wcscmp(key, L"comment")==0) { @@ -1300,7 +1277,7 @@ pax_attribute(struct archive_entry *entry, struct stat *st, break; case 'g': if (wcscmp(key, L"gid")==0) - st->st_gid = tar_atol10(value, wcslen(value)); + archive_entry_set_gid(entry, tar_atol10(value, wcslen(value))); else if (wcscmp(key, L"gname")==0) archive_entry_copy_gname_w(entry, value); break; @@ -1316,8 +1293,7 @@ pax_attribute(struct archive_entry *entry, struct stat *st, case 'm': if (wcscmp(key, L"mtime")==0) { pax_time(value, &s, &n); - st->st_mtime = s; - ARCHIVE_STAT_SET_MTIME_NANOS(st, n); + archive_entry_set_mtime(entry, s, n); } break; case 'p': @@ -1331,11 +1307,11 @@ pax_attribute(struct archive_entry *entry, struct stat *st, /* POSIX has reserved 'security.*' */ /* Someday: if (wcscmp(key, L"security.acl")==0) { ... } */ if (wcscmp(key, L"size")==0) - st->st_size = tar_atol10(value, wcslen(value)); + archive_entry_set_size(entry, tar_atol10(value, wcslen(value))); break; case 'u': if (wcscmp(key, L"uid")==0) - st->st_uid = tar_atol10(value, wcslen(value)); + archive_entry_set_uid(entry, tar_atol10(value, wcslen(value))); else if (wcscmp(key, L"uname")==0) archive_entry_copy_uname_w(entry, value); break; @@ -1399,8 +1375,8 @@ pax_time(const wchar_t *p, int64_t *ps, long *pn) * Parse GNU tar header */ static int -header_gnutar(struct archive_read *a, struct tar *tar, struct archive_entry *entry, - struct stat *st, const void *h) +header_gnutar(struct archive_read *a, struct tar *tar, + struct archive_entry *entry, const void *h) { const struct archive_entry_header_gnutar *header; @@ -1413,7 +1389,7 @@ header_gnutar(struct archive_read *a, struct tar *tar, struct archive_entry *ent */ /* Grab fields common to all tar variants. */ - header_common(a, tar, entry, st, h); + header_common(a, tar, entry, h); /* Copy filename over (to ensure null termination). */ header = (const struct archive_entry_header_gnutar *)h; @@ -1434,22 +1410,25 @@ header_gnutar(struct archive_read *a, struct tar *tar, struct archive_entry *ent archive_entry_set_gname(entry, tar->entry_gname.s); /* Parse out device numbers only for char and block specials */ - if (header->typeflag[0] == '3' || header->typeflag[0] == '4') - st->st_rdev = makedev ( - tar_atol(header->rdevmajor, sizeof(header->rdevmajor)), + if (header->typeflag[0] == '3' || header->typeflag[0] == '4') { + archive_entry_set_rdevmajor(entry, + tar_atol(header->rdevmajor, sizeof(header->rdevmajor))); + archive_entry_set_rdevminor(entry, tar_atol(header->rdevminor, sizeof(header->rdevminor))); - else - st->st_rdev = 0; + } else + archive_entry_set_rdev(entry, 0); - tar->entry_bytes_remaining = st->st_size; + tar->entry_bytes_remaining = archive_entry_size(entry); tar->entry_padding = 0x1ff & (-tar->entry_bytes_remaining); /* Grab GNU-specific fields. */ - st->st_atime = tar_atol(header->atime, sizeof(header->atime)); - st->st_ctime = tar_atol(header->ctime, sizeof(header->ctime)); + archive_entry_set_atime(entry, + tar_atol(header->atime, sizeof(header->atime)), 0); + archive_entry_set_ctime(entry, + tar_atol(header->ctime, sizeof(header->ctime)), 0); if (header->realsize[0] != 0) { - st->st_size = tar_atol(header->realsize, - sizeof(header->realsize)); + archive_entry_set_size(entry, + tar_atol(header->realsize, sizeof(header->realsize))); } if (header->sparse[0].offset[0] != 0) { @@ -1481,7 +1460,7 @@ gnu_read_sparse_data(struct archive_read *a, struct tar *tar, return (ARCHIVE_OK); do { - bytes_read = (a->compression_read_ahead)(a, &data, 512); + bytes_read = (a->decompressor->read_ahead)(a, &data, 512); if (bytes_read < 0) return (ARCHIVE_FATAL); if (bytes_read < 512) { @@ -1490,7 +1469,7 @@ gnu_read_sparse_data(struct archive_read *a, struct tar *tar, "detected while reading sparse file data"); return (ARCHIVE_FATAL); } - (a->compression_read_consume)(a, 512); + (a->decompressor->consume)(a, 512); ext = (const struct extended *)data; gnu_parse_sparse_data(a, tar, ext->sparse, 21); } while (ext->isextended[0] != 0); |