Date: Sun, 15 Apr 2007 17:15:10 GMT From: Matt Jacob <mjacob@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 118181 for review Message-ID: <200704151715.l3FHFAxe075281@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118181 Change 118181 by mjacob@mjexp on 2007/04/15 17:14:35 IFC Affected files ... .. //depot/projects/mjexp/lib/libarchive/Makefile#9 integrate .. //depot/projects/mjexp/lib/libarchive/archive.h.in#10 integrate .. //depot/projects/mjexp/lib/libarchive/archive_platform.h#6 integrate .. //depot/projects/mjexp/lib/libarchive/archive_read_extract.c#8 integrate .. //depot/projects/mjexp/lib/libarchive/archive_read_support_format_ar.c#3 integrate .. //depot/projects/mjexp/lib/libarchive/archive_read_support_format_tar.c#9 integrate .. //depot/projects/mjexp/lib/libarchive/archive_read_support_format_zip.c#5 integrate .. //depot/projects/mjexp/lib/libarchive/archive_write_disk.c#6 integrate .. //depot/projects/mjexp/lib/libarchive/archive_write_set_compression_none.c#6 integrate .. //depot/projects/mjexp/lib/libarchive/archive_write_set_format_ar.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/archive_write_set_format_by_name.c#4 integrate .. //depot/projects/mjexp/lib/libarchive/config_freebsd.h#4 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_acl_basic.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_acl_pax.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_read_data_large.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_read_extract.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_read_format_ar.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_read_large.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_read_position.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_read_truncated.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_tar_filenames.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_write_disk_perms.c#3 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_write_disk_secure.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_write_format_ar.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_write_format_tar.c#2 integrate .. //depot/projects/mjexp/lib/libarchive/test/test_write_open_memory.c#2 integrate .. //depot/projects/mjexp/sys/cam/cam_ccb.h#4 integrate .. //depot/projects/mjexp/sys/cam/cam_periph.c#4 integrate .. //depot/projects/mjexp/sys/cam/cam_periph.h#2 integrate .. //depot/projects/mjexp/sys/cam/cam_sim.c#2 integrate .. //depot/projects/mjexp/sys/cam/cam_sim.h#2 integrate .. //depot/projects/mjexp/sys/cam/cam_xpt.c#8 integrate .. //depot/projects/mjexp/sys/cam/cam_xpt.h#5 integrate .. //depot/projects/mjexp/sys/cam/cam_xpt_periph.h#2 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_cd.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_ch.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_da.c#7 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_low.c#4 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_pass.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_pt.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_sa.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_ses.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_sg.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_targ_bh.c#3 integrate .. //depot/projects/mjexp/sys/cam/scsi/scsi_target.c#4 integrate .. //depot/projects/mjexp/sys/compat/linprocfs/linprocfs.c#10 integrate .. //depot/projects/mjexp/sys/contrib/opensolaris/uts/common/fs/dnlc.c#3 integrate .. //depot/projects/mjexp/sys/dev/aac/aac_cam.c#5 integrate .. //depot/projects/mjexp/sys/dev/advansys/advansys.c#5 integrate .. //depot/projects/mjexp/sys/dev/advansys/adwcam.c#6 integrate .. //depot/projects/mjexp/sys/dev/aha/aha.c#5 integrate .. //depot/projects/mjexp/sys/dev/ahb/ahb.c#7 integrate .. //depot/projects/mjexp/sys/dev/aic/aic.c#4 integrate .. //depot/projects/mjexp/sys/dev/aic7xxx/aic79xx_osm.c#4 integrate .. //depot/projects/mjexp/sys/dev/aic7xxx/aic7xxx_osm.c#4 integrate .. //depot/projects/mjexp/sys/dev/amd/amd.c#6 integrate .. //depot/projects/mjexp/sys/dev/amr/amr_cam.c#4 integrate .. //depot/projects/mjexp/sys/dev/arcmsr/arcmsr.c#10 integrate .. //depot/projects/mjexp/sys/dev/asr/asr.c#6 integrate .. //depot/projects/mjexp/sys/dev/ata/atapi-cam.c#6 integrate .. //depot/projects/mjexp/sys/dev/buslogic/bt.c#5 integrate .. //depot/projects/mjexp/sys/dev/ciss/ciss.c#6 integrate .. //depot/projects/mjexp/sys/dev/cxgb/sys/uipc_mvec.c#4 integrate .. //depot/projects/mjexp/sys/dev/dpt/dpt_scsi.c#5 integrate .. //depot/projects/mjexp/sys/dev/esp/ncr53c9x.c#4 integrate .. //depot/projects/mjexp/sys/dev/firewire/sbp.c#6 integrate .. //depot/projects/mjexp/sys/dev/firewire/sbp_targ.c#3 integrate .. //depot/projects/mjexp/sys/dev/hptmv/entry.c#5 integrate .. //depot/projects/mjexp/sys/dev/iir/iir.c#4 integrate .. //depot/projects/mjexp/sys/dev/isp/isp_freebsd.c#16 integrate .. //depot/projects/mjexp/sys/dev/mly/mly.c#6 integrate .. //depot/projects/mjexp/sys/dev/mpt/mpt_cam.c#16 integrate .. //depot/projects/mjexp/sys/dev/ppbus/vpo.c#3 integrate .. //depot/projects/mjexp/sys/dev/rr232x/osm_bsd.c#3 integrate .. //depot/projects/mjexp/sys/dev/sym/sym_hipd.c#6 integrate .. //depot/projects/mjexp/sys/dev/trm/trm.c#6 integrate .. //depot/projects/mjexp/sys/dev/twa/tw_osl_cam.c#4 integrate .. //depot/projects/mjexp/sys/dev/usb/umass.c#7 integrate .. //depot/projects/mjexp/sys/dev/wds/wd7000.c#4 integrate .. //depot/projects/mjexp/sys/fs/procfs/procfs_dbregs.c#2 integrate .. //depot/projects/mjexp/sys/fs/procfs/procfs_fpregs.c#2 integrate .. //depot/projects/mjexp/sys/fs/procfs/procfs_regs.c#2 integrate .. //depot/projects/mjexp/sys/netinet/sctp_output.c#9 integrate .. //depot/projects/mjexp/sys/netinet/sctp_structs.h#8 integrate .. //depot/projects/mjexp/sys/netinet/sctp_uio.h#8 integrate .. //depot/projects/mjexp/sys/netinet/sctp_var.h#7 integrate .. //depot/projects/mjexp/sys/netinet/sctputil.h#6 integrate .. //depot/projects/mjexp/sys/nfsserver/nfs_srvsock.c#4 integrate .. //depot/projects/mjexp/sys/pci/ncr.c#5 integrate .. //depot/projects/mjexp/sys/sys/proc.h#12 integrate Differences ... ==== //depot/projects/mjexp/lib/libarchive/Makefile#9 (text+ko) ==== @@ -1,4 +1,4 @@ -# $FreeBSD: src/lib/libarchive/Makefile,v 1.68 2007/04/14 18:24:42 kientzle Exp $ +# $FreeBSD: src/lib/libarchive/Makefile,v 1.70 2007/04/15 00:53:38 kientzle Exp $ LIB= archive DPADD= ${LIBBZ2} ${LIBZ} @@ -9,7 +9,7 @@ # Major: Bumped ONLY when API/ABI breakage happens (see SHLIB_MAJOR) # Minor: Bumped when significant new features are added # Revision: Bumped on any notable change -VERSION= 2.0.30 +VERSION= 2.0.31 ARCHIVE_API_MAJOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/\..*//' ARCHIVE_API_MINOR!= echo ${VERSION} | sed -e 's/[^0-9]/./g' -e 's/[0-9]*\.//' -e 's/\..*//' @@ -59,6 +59,7 @@ archive_read_support_compression_gzip.c \ archive_read_support_compression_none.c \ archive_read_support_format_all.c \ + archive_read_support_format_ar.c \ archive_read_support_format_cpio.c \ archive_read_support_format_empty.c \ archive_read_support_format_iso9660.c \ ==== //depot/projects/mjexp/lib/libarchive/archive.h.in#10 (text+ko) ==== @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.41 2007/04/03 05:34:36 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.42 2007/04/14 22:34:10 kientzle Exp $ */ #ifndef ARCHIVE_H_INCLUDED @@ -178,7 +178,7 @@ #define ARCHIVE_FORMAT_ZIP 0x50000 #define ARCHIVE_FORMAT_EMPTY 0x60000 #define ARCHIVE_FORMAT_AR 0x70000 -#define ARCHIVE_FORMAT_AR_SVR4 (ARCHIVE_FORMAT_AR | 1) +#define ARCHIVE_FORMAT_AR_GNU (ARCHIVE_FORMAT_AR | 1) #define ARCHIVE_FORMAT_AR_BSD (ARCHIVE_FORMAT_AR | 2) /*- ==== //depot/projects/mjexp/lib/libarchive/archive_platform.h#6 (text+ko) ==== @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libarchive/archive_platform.h,v 1.25 2007/04/12 04:44:21 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive_platform.h,v 1.26 2007/04/15 00:53:38 kientzle Exp $ */ /* @@ -67,6 +67,23 @@ #include <stdint.h> #endif +/* Some platforms lack the standard *_MAX definitions. */ +#if !HAVE_DECL_SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif +#if !HAVE_DECL_UINT32_MAX +#define UINT32_MAX (~(uint32_t)0) +#endif +#if !HAVE_DECL_UINT64_MAX +#define UINT64_MAX (~(uint64_t)0) +#endif +#if !HAVE_DECL_INT64_MAX +#define INT64_MAX ((int64_t)(UINT64_MAX >> 1)) +#endif +#if !HAVE_DECL_INT64_MIN +#define INT64_MIN ((int64_t)(~INT64_MAX)) +#endif + /* * If this platform has <sys/acl.h>, acl_create(), acl_init(), * acl_set_file(), and ACL_USER, we assume it has the rest of the ==== //depot/projects/mjexp/lib/libarchive/archive_read_extract.c#8 (text+ko) ==== @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.55 2007/04/07 03:37:59 cperciva Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.57 2007/04/15 01:01:20 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -95,8 +95,13 @@ archive_write_disk_set_skip_file(a->extract->ad, a->skip_file_dev, a->skip_file_ino); r = archive_write_header(a->extract->ad, entry); - if (r == ARCHIVE_OK) - /* If there's an FD, pour data into it. */ + if (r != ARCHIVE_OK) + /* If _write_header failed, copy the error. */ + archive_set_error(&a->archive, + archive_errno(extract->ad), + "%s", archive_error_string(extract->ad)); + else + /* Otherwise, pour data into the entry. */ r = copy_data(_a, a->extract->ad); r2 = archive_write_finish_entry(a->extract->ad); /* Use the first message. */ ==== //depot/projects/mjexp/lib/libarchive/archive_read_support_format_ar.c#3 (text+ko) ==== @@ -26,8 +26,11 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_ar.c,v 1.3 2007/04/14 08:42:50 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_ar.c,v 1.5 2007/04/15 00:53:38 kientzle Exp $"); +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #ifdef HAVE_ERRNO_H #include <errno.h> #endif @@ -70,16 +73,6 @@ #define AR_fmag_offset 58 #define AR_fmag_size 2 -/* - * "ar" magic numbers. - */ -#define ARMAG "!<arch>\n" -#define SARMAG 8 /* strlen(ARMAG); */ -#define AR_EFMT1 "#1/" -#define SAR_EFMT1 3 /* strlen(AR_EFMT1); */ -#define ARFMAG "`\n" -#define SARFMAG 2 /* strlen(ARFMAG); */ - #define isdigit(x) (x) >= '0' && (x) <= '9' static int archive_read_format_ar_bid(struct archive_read *a); @@ -89,32 +82,12 @@ static int archive_read_format_ar_skip(struct archive_read *a); static int archive_read_format_ar_read_header(struct archive_read *a, struct archive_entry *e); -static int64_t ar_atol8(const char *p, unsigned char_cnt); -static int64_t ar_atol10(const char *p, unsigned char_cnt); -static int ar_parse_string_table(struct archive_read *, struct ar *, +static uint64_t ar_atol8(const char *p, unsigned char_cnt); +static uint64_t ar_atol10(const char *p, unsigned char_cnt); +static int ar_parse_gnu_filename_table(struct archive_read *, struct ar *, const void *, size_t); - -/* - * ANSI C99 defines constants for these, but not everyone supports - * those constants, so I define a couple of static variables here and - * compute the values. These calculations should be portable to any - * 2s-complement architecture. - */ -#ifdef UINT64_MAX -static const uint64_t max_uint64 = UINT64_MAX; -#else -static const uint64_t max_uint64 = ~(uint64_t)0; -#endif -#ifdef INT64_MAX -static const int64_t max_int64 = INT64_MAX; -#else -static const int64_t max_int64 = (int64_t)((~(uint64_t)0) >> 1); -#endif -#ifdef INT64_MIN -static const int64_t min_int64 = INT64_MIN; -#else -static const int64_t min_int64 = (int64_t)(~((~(uint64_t)0) >> 1)); -#endif +static int ar_parse_common_header(struct ar *ar, struct archive_entry *, + const char *h); int archive_read_support_format_ar(struct archive *_a) @@ -177,16 +150,15 @@ if (ar->bid > 0) return (ar->bid); - bytes_read = (a->compression_read_ahead)(a, &h, SARMAG); - if (bytes_read < SARMAG) - return (-1); - /* - * Verify the global header. + * Verify the 8-byte file signature. * TODO: Do we need to check more than this? */ - if (strncmp((const char*)h, ARMAG, SARMAG) == 0) { - ar->bid = SARMAG; + bytes_read = (a->compression_read_ahead)(a, &h, 8); + if (bytes_read < 8) + return (-1); + if (strncmp((const char*)h, "!<arch>\n", 8) == 0) { + ar->bid = 64; return (ar->bid); } return (-1); @@ -196,199 +168,247 @@ archive_read_format_ar_read_header(struct archive_read *a, struct archive_entry *entry) { - int r; - size_t bsd_append; - ssize_t bytes; - int64_t nval; - size_t tab_size; - char *fname, *p; + char filename[AR_name_size + 1]; struct ar *ar; + uint64_t number; /* Used to hold parsed numbers before validation. */ + ssize_t bytes_read; + size_t bsd_name_length, entry_size; + char *p; const void *b; const char *h; + int r; - bsd_append = 0; + ar = (struct ar*)*(a->pformat_data); - if (!a->archive.archive_format) { - a->archive.archive_format = ARCHIVE_FORMAT_AR; - a->archive.archive_format_name = "Unix Archiver"; - } - if (a->archive.file_position == 0) { /* * We are now at the beginning of the archive, * so we need first consume the ar global header. */ - (a->compression_read_consume)(a, SARMAG); + (a->compression_read_consume)(a, 8); + /* Set a default format code for now. */ + a->archive.archive_format = ARCHIVE_FORMAT_AR; } - /* Read 60-byte header */ - bytes = (a->compression_read_ahead)(a, &b, 60); - if (bytes < 60) { - /* - * We just encountered an incomplete ar file, - * though the _bid function accepted it. - */ + /* Read the header for the next file entry. */ + bytes_read = (a->compression_read_ahead)(a, &b, 60); + if (bytes_read < 60) { + /* Broken header. */ return (ARCHIVE_EOF); } (a->compression_read_consume)(a, 60); - h = (const char *)b; - /* Consistency check */ - if (strncmp(h + AR_fmag_offset, ARFMAG, SARFMAG) != 0) { + /* Verify the magic signature on the file header. */ + if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) { archive_set_error(&a->archive, EINVAL, "Consistency check failed"); return (ARCHIVE_WARN); } - ar = (struct ar*)*(a->pformat_data); + /* Copy filename into work buffer. */ + strncpy(filename, h + AR_name_offset, AR_name_size); + filename[AR_name_size] = '\0'; - if (strncmp(h + AR_name_offset, "//", 2) == 0) { + /* + * Guess the format variant based on the filename. + */ + if (a->archive.archive_format == ARCHIVE_FORMAT_AR) { + /* We don't already know the variant, so let's guess. */ + /* + * Biggest clue is presence of '/': GNU starts special + * filenames with '/', appends '/' as terminator to + * non-special names, so anything with '/' should be + * GNU except for BSD long filenames. + */ + if (strncmp(filename, "#1/", 3) == 0) + a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; + else if (strchr(filename, '/') != NULL) + a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; + else if (strncmp(filename, "__.SYMDEF", 9) == 0) + a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; /* - * An archive member with ar_name "//" is an archive - * string table. + * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/' + * if name exactly fills 16-byte field? If so, we + * can't assume entries without '/' are BSD. XXX */ - nval = ar_atol10(h + AR_size_offset, AR_size_size); - if (nval < 0 || nval > SIZE_MAX) { + } + + /* Update format name from the code. */ + if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) + a->archive.archive_format_name = "ar (GNU/SVR4)"; + else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) + a->archive.archive_format_name = "ar (BSD)"; + else + a->archive.archive_format_name = "ar"; + + /* + * Remove trailing spaces from the filename. GNU and BSD + * variants both pad filename area out with spaces. + * This will only be wrong if GNU/SVR4 'ar' implementations + * omit trailing '/' for 16-char filenames and we have + * a 16-char filename that ends in ' '. + */ + p = filename + AR_name_size - 1; + while (p >= filename && *p == ' ') { + *p = '\0'; + p--; + } + + /* + * Remove trailing slash unless first character is '/'. + * (BSD entries never end in '/', so this will only trim + * GNU-format entries. GNU special entries start with '/' + * and are not terminated in '/', so we don't trim anything + * that starts with '/'.) + */ + if (filename[0] != '/' && *p == '/') + *p = '\0'; + + /* + * '//' is the GNU filename table. + * Later entries can refer to names in this table. + */ + if (strcmp(filename, "//") == 0) { + /* This must come before any call to _read_ahead. */ + ar_parse_common_header(ar, entry, h); + archive_entry_copy_pathname(entry, filename); + archive_entry_set_mode(entry, + S_IFREG | (archive_entry_mode(entry) & 0777)); + /* Get the size of the filename table. */ + number = ar_atol10(h + AR_size_offset, AR_size_size); + if (number > SIZE_MAX) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "String table too large"); + "Filename table too large"); return (ARCHIVE_FATAL); } - tab_size = (size_t)nval; - bytes = (a->compression_read_ahead)(a, &b, tab_size); - if (bytes <= 0) + entry_size = (size_t)number; + /* Read the filename table into memory. */ + bytes_read = (a->compression_read_ahead)(a, &b, entry_size); + if (bytes_read <= 0) return (ARCHIVE_FATAL); - if (bytes < nval) { + if ((size_t)bytes_read < entry_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Truncated input file"); return (ARCHIVE_FATAL); } + /* + * Don't consume the contents, so the client will + * also get a shot at reading it. + */ - r = ar_parse_string_table(a, ar, b, tab_size); - if (r == ARCHIVE_OK) { - /* - * Archive string table only have ar_name and ar_size fileds - * in its header. - */ - archive_entry_copy_pathname(entry, "//"); - h = (const char *)b; - nval = ar_atol10(h + AR_size_offset, AR_size_size); - archive_entry_set_size(entry, nval); - - ar->entry_offset = 0; - ar->entry_bytes_remaining = nval; - ar->entry_padding = ar->entry_bytes_remaining % 2; - } - return (r); + /* Parse the filename table. */ + return (ar_parse_gnu_filename_table(a, ar, b, entry_size)); } - if (h[AR_name_offset] == '/' && isdigit(h[AR_name_offset + 1])) { + /* + * GNU variant handles long filenames by storing /<number> + * to indicate a name stored in the filename table. + */ + if (filename[0] == '/' && isdigit(filename[1])) { + number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); /* - * Archive member is common format with SVR4/GNU variant. - * "/" followed by one or more digit(s) in the ar_name - * filed indicates an index to the string table. + * If we can't look up the real name, warn and return + * the entry with the wrong name. */ - if (ar->strtab == NULL) { + if (ar->strtab == NULL || number > ar->strtab_size) { archive_set_error(&a->archive, EINVAL, - "String table does not exist"); + "Can't find long filename for entry"); + archive_entry_copy_pathname(entry, filename); + /* Parse the time, owner, mode, size fields. */ + ar_parse_common_header(ar, entry, h); return (ARCHIVE_WARN); } - nval = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); - if (nval < 0 || nval > ar->strtab_size) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "String table overflow"); - return (ARCHIVE_FATAL); - } - archive_entry_copy_pathname(entry, &ar->strtab[(size_t)nval]); - goto remain; + archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]); + /* Parse the time, owner, mode, size fields. */ + return (ar_parse_common_header(ar, entry, h)); } - if (strncmp(h + AR_name_offset, AR_EFMT1, SAR_EFMT1) == 0) { - /* - * Archive member is common format with BSD variant. - * AR_EFMT1 is followed by one or more digit(s) indicating - * the length of the real filename which is appended - * to the header. - */ - nval = ar_atol10(h + AR_name_offset + SAR_EFMT1, - AR_name_size - SAR_EFMT1); - if (nval < 0 || nval >= SIZE_MAX) { + /* + * BSD handles long filenames by storing "#1/" followed by the + * length of filename as a decimal number, then prepends the + * the filename to the file contents. + */ + if (strncmp(filename, "#1/", 3) == 0) { + /* Parse the time, owner, mode, size fields. */ + /* This must occur before _read_ahead is called again. */ + ar_parse_common_header(ar, entry, h); + + /* Parse the size of the name, adjust the file size. */ + number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); + if ((off_t)number > ar->entry_bytes_remaining) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Bad input file size"); return (ARCHIVE_FATAL); } - bsd_append = (size_t)nval; - bytes = (a->compression_read_ahead)(a, &b, bsd_append); - if (bytes <= 0) + bsd_name_length = (size_t)number; + ar->entry_bytes_remaining -= bsd_name_length; + /* Adjust file size reported to client. */ + archive_entry_set_size(entry, ar->entry_bytes_remaining); + + /* Read the long name into memory. */ + bytes_read = (a->compression_read_ahead)(a, &b, bsd_name_length); + if (bytes_read <= 0) return (ARCHIVE_FATAL); - if (bytes < nval) { + if ((size_t)bytes_read < bsd_name_length) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Truncated input file"); return (ARCHIVE_FATAL); } + (a->compression_read_consume)(a, bsd_name_length); - (a->compression_read_consume)(a, bsd_append); - - fname = (char *)malloc(bsd_append + 1); - if (fname == NULL) { + /* Store it in the entry. */ + p = (char *)malloc(bsd_name_length + 1); + if (p == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate fname buffer"); return (ARCHIVE_FATAL); } - strncpy(fname, b, bsd_append); - fname[bsd_append] = '\0'; - archive_entry_copy_pathname(entry, fname); - free(fname); - fname = NULL; - - goto remain; + strncpy(p, b, bsd_name_length); + p[bsd_name_length] = '\0'; + archive_entry_copy_pathname(entry, p); + free(p); + return (ARCHIVE_OK); } /* - * "/" followed by one or more spaces indicate a - * SVR4/GNU archive symbol table. - * + * "/" is the SVR4/GNU archive symbol table. */ - if (strncmp(h + AR_name_offset, "/ ", 2) == 0) { + if (strcmp(filename, "/") == 0) { archive_entry_copy_pathname(entry, "/"); - goto remain; + /* Parse the time, owner, mode, size fields. */ + r = ar_parse_common_header(ar, entry, h); + /* Force the file type to a regular file. */ + archive_entry_set_mode(entry, + S_IFREG | (archive_entry_mode(entry) & 0777)); + return (r); } + /* - * "__.SYMDEF" indicates a BSD archive symbol table. + * "__.SYMDEF" is a BSD archive symbol table. */ - if (strncmp(h + AR_name_offset, "__.SYMDEF", 9) == 0) { - archive_entry_copy_pathname(entry, "__.SYMDEF"); - goto remain; + if (strcmp(filename, "__.SYMDEF") == 0) { + archive_entry_copy_pathname(entry, filename); + /* Parse the time, owner, mode, size fields. */ + return (ar_parse_common_header(ar, entry, h)); } /* - * Otherwise, the ar_name fields stores the real - * filename. - * SVR4/GNU variant append a '/' to mark the end of - * filename, while BSD variant use a space. + * Otherwise, this is a standard entry. The filename + * has already been trimmed as much as possible, based + * on our current knowledge of the format. */ - fname = (char *)malloc(AR_name_size + 1); - strncpy(fname, h + AR_name_offset, AR_name_size); - fname[AR_name_size] = '\0'; + archive_entry_copy_pathname(entry, filename); + return (ar_parse_common_header(ar, entry, h)); +} - if ((p = strchr(fname, '/')) != NULL) { - /* SVR4/GNU format */ - *p = '\0'; - archive_entry_copy_pathname(entry, fname); - free(fname); - fname = NULL; - goto remain; - } - - /* BSD format */ - if ((p = strchr(fname, ' ')) != NULL) - *p = '\0'; - archive_entry_copy_pathname(entry, fname); - free(fname); - fname = NULL; +static int +ar_parse_common_header(struct ar *ar, struct archive_entry *entry, + const char *h) +{ + uint64_t n; -remain: /* Copy remaining header */ archive_entry_set_mtime(entry, (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L); @@ -398,28 +418,12 @@ (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size)); archive_entry_set_mode(entry, (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size)); - nval = ar_atol10(h + AR_size_offset, AR_size_size); + n = ar_atol10(h + AR_size_offset, AR_size_size); ar->entry_offset = 0; - ar->entry_padding = nval % 2; - - /* - * For BSD variant, we should subtract the length of - * the appended filename string from ar_size to get the - * real file size. But remember we should do this only - * after we had calculated the padding. - */ - if (bsd_append > nval) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "Truncated input file"); - return (ARCHIVE_FATAL); - } - if (bsd_append > 0) - nval -= bsd_append; - - archive_entry_set_size(entry, nval); - ar->entry_bytes_remaining = nval; - + ar->entry_padding = n % 2; + archive_entry_set_size(entry, n); + ar->entry_bytes_remaining = n; return (ARCHIVE_OK); } @@ -441,7 +445,6 @@ } if (bytes_read < 0) return (ARCHIVE_FATAL); - /* XXX I don't get this. */ if (bytes_read > ar->entry_bytes_remaining) bytes_read = (ssize_t)ar->entry_bytes_remaining; *size = bytes_read; @@ -496,7 +499,7 @@ } static int -ar_parse_string_table(struct archive_read *a, struct ar *ar, +ar_parse_gnu_filename_table(struct archive_read *a, struct ar *ar, const void *h, size_t size) { char *p; @@ -550,68 +553,53 @@ return (ARCHIVE_WARN); } -static int64_t +static uint64_t ar_atol8(const char *p, unsigned char_cnt) { - int64_t l, limit, last_digit_limit; - int digit, sign, base; + uint64_t l, limit, last_digit_limit; + unsigned int digit, base; base = 8; - limit = max_int64 / base; - last_digit_limit = max_int64 % base; + limit = UINT64_MAX / base; + last_digit_limit = UINT64_MAX % base; - while (*p == ' ' || *p == '\t') + while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) p++; - if (*p == '-') { - sign = -1; - p++; - } else - sign = 1; l = 0; digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt-- > 0) { + while (*p >= '0' && digit < base && char_cnt-- > 0) { if (l>limit || (l == limit && digit > last_digit_limit)) { - l = max_uint64; /* Truncate on overflow. */ + l = UINT64_MAX; /* Truncate on overflow. */ break; } l = (l * base) + digit; digit = *++p - '0'; } - return (sign < 0) ? -l : l; + return (l); } -/* - * XXX This is not really correct for negative numbers, - * as min_int64_t can never be returned. That one is unused BTW. - */ -static int64_t +static uint64_t ar_atol10(const char *p, unsigned char_cnt) { - int64_t l, limit, last_digit_limit; - int base, digit, sign; + uint64_t l, limit, last_digit_limit; + unsigned int base, digit; base = 10; - limit = max_int64 / base; - last_digit_limit = max_int64 % base; + limit = UINT64_MAX / base; + last_digit_limit = UINT64_MAX % base; - while (*p == ' ' || *p == '\t') - p++; - if (*p == '-') { - sign = -1; + while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) p++; - } else - sign = 1; - l = 0; digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt-- > 0) { + while (*p >= '0' && digit < base && char_cnt-- > 0) { if (l > limit || (l == limit && digit > last_digit_limit)) { - l = max_uint64; /* Truncate on overflow. */ + l = UINT64_MAX; /* Truncate on overflow. */ break; } l = (l * base) + digit; digit = *++p - '0'; } - return (sign < 0) ? -l : l; + return (l); } ==== //depot/projects/mjexp/lib/libarchive/archive_read_support_format_tar.c#9 (text+ko) ==== @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.53 2007/04/12 04:42:57 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.54 2007/04/15 00:53:38 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> @@ -225,28 +225,6 @@ static int utf8_decode(wchar_t *, const char *, size_t length); static char *wide_to_narrow(const wchar_t *wval); -/* - * ANSI C99 defines constants for these, but not everyone supports - * those constants, so I define a couple of static variables here and - * compute the values. These calculations should be portable to any - * 2s-complement architecture. - */ -#ifdef UINT64_MAX -static const uint64_t max_uint64 = UINT64_MAX; -#else -static const uint64_t max_uint64 = ~(uint64_t)0; -#endif -#ifdef INT64_MAX -static const int64_t max_int64 = INT64_MAX; -#else -static const int64_t max_int64 = (int64_t)((~(uint64_t)0) >> 1); -#endif -#ifdef INT64_MIN -static const int64_t min_int64 = INT64_MIN; -#else -static const int64_t min_int64 = (int64_t)(~((~(uint64_t)0) >> 1)); -#endif - int archive_read_support_format_gnutar(struct archive *a) { @@ -1379,8 +1357,8 @@ int sign; int64_t limit, last_digit_limit; - limit = max_int64 / 10; - last_digit_limit = max_int64 % 10; + limit = INT64_MAX / 10; + last_digit_limit = INT64_MAX % 10; s = 0; sign = 1; @@ -1392,7 +1370,7 @@ digit = *p - '0'; if (s > limit || (s == limit && digit > last_digit_limit)) { - s = max_uint64; + s = UINT64_MAX; break; } s = (s * 10) + digit; @@ -1593,8 +1571,8 @@ int digit, sign, base; base = 8; - limit = max_int64 / base; - last_digit_limit = max_int64 % base; + limit = INT64_MAX / base; + last_digit_limit = INT64_MAX % base; while (*p == ' ' || *p == '\t') p++; @@ -1608,7 +1586,7 @@ digit = *p - '0'; while (digit >= 0 && digit < base && char_cnt-- > 0) { if (l>limit || (l == limit && digit > last_digit_limit)) { - l = max_uint64; /* Truncate on overflow. */ + l = UINT64_MAX; /* Truncate on overflow. */ break; } l = (l * base) + digit; @@ -1630,8 +1608,8 @@ int base, digit, sign; base = 10; - limit = max_int64 / base; - last_digit_limit = max_int64 % base; + limit = INT64_MAX / base; + last_digit_limit = INT64_MAX % base; while (*p == ' ' || *p == '\t') p++; @@ -1645,7 +1623,7 @@ digit = *p - '0'; while (digit >= 0 && digit < base && char_cnt-- > 0) { if (l > limit || (l == limit && digit > last_digit_limit)) { - l = max_uint64; /* Truncate on overflow. */ + l = UINT64_MAX; /* Truncate on overflow. */ break; } l = (l * base) + digit; @@ -1668,8 +1646,8 @@ int64_t l, upper_limit, lower_limit; const unsigned char *p = (const unsigned char *)_p; - upper_limit = max_int64 / 256; - lower_limit = min_int64 / 256; + upper_limit = INT64_MAX / 256; + lower_limit = INT64_MIN / 256; /* Pad with 1 or 0 bits, depending on sign. */ if ((0x40 & *p) == 0x40) @@ -1679,10 +1657,10 @@ l = (l << 6) | (0x3f & *p++); while (--char_cnt > 0) { if (l > upper_limit) { - l = max_int64; /* Truncate on overflow */ + l = INT64_MAX; /* Truncate on overflow */ break; } else if (l < lower_limit) { - l = min_int64; + l = INT64_MIN; break; } l = (l << 8) | (0xff & (int64_t)*p++); ==== //depot/projects/mjexp/lib/libarchive/archive_read_support_format_zip.c#5 (text+ko) ==== @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_zip.c,v 1.11 2007/03/03 07:37:36 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_zip.c,v 1.12 2007/04/15 00:53:38 kientzle Exp $"); #ifdef HAVE_SYS_STAT_H #include <sys/stat.h> @@ -137,9 +137,6 @@ static time_t zip_time(const char *); static void process_extra(const void* extra, struct zip* zip); -/* Largest 32-bit unsigned value, stored in a 64-bit constant. */ -static const uint64_t max_uint32 = (((uint64_t)1) << 32) - 1; - int archive_read_support_format_zip(struct archive *_a) { @@ -412,8 +409,8 @@ return (ARCHIVE_WARN); } /* Size field only stores the lower 32 bits of the actual size. */ - if ((zip->uncompressed_size & max_uint32) - != (zip->entry_uncompressed_bytes_read & max_uint32)) { + if ((zip->uncompressed_size & UINT32_MAX) + != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "ZIP uncompressed data is wrong size"); return (ARCHIVE_WARN); ==== //depot/projects/mjexp/lib/libarchive/archive_write_disk.c#6 (text+ko) ==== @@ -25,7 +25,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.8 2007/04/14 02:37:22 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.10 2007/04/15 04:43:12 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> @@ -897,7 +897,7 @@ times.modtime = p->mtime; times.actime = p->atime; - utime(p->name, times); + utime(p->name, ×); #endif } if (p->fixup & TODO_MODE_BASE) @@ -922,6 +922,10 @@ struct archive_write_disk *a = (struct archive_write_disk *)_a; int ret; ret = _archive_write_close(&a->archive); + if (a->cleanup_gid != NULL && a->lookup_gid_data != NULL) + (a->cleanup_gid)(a->lookup_gid_data); + if (a->cleanup_uid != NULL && a->lookup_uid_data != NULL) + (a->cleanup_uid)(a->lookup_uid_data); archive_string_free(&a->_name_data); archive_string_free(&a->archive.error_string); archive_string_free(&a->path_safe); @@ -1452,7 +1456,7 @@ >>> TRUNCATED FOR MAIL (1000 lines) <<<
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704151715.l3FHFAxe075281>