diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile index c377f9b2d477..eb1c172235bb 100644 --- a/lib/libarchive/Makefile +++ b/lib/libarchive/Makefile @@ -34,6 +34,7 @@ SRCS= archive_check_magic.c \ archive_entry_stat.c \ archive_entry_strmode.c \ archive_entry_link_resolver.c \ + archive_entry_xattr.c \ archive_read.c \ archive_read_data_into_fd.c \ archive_read_disk.c \ diff --git a/lib/libarchive/archive_entry.c b/lib/libarchive/archive_entry.c index 16166aa85ae4..1202a8a28297 100644 --- a/lib/libarchive/archive_entry.c +++ b/lib/libarchive/archive_entry.c @@ -32,12 +32,12 @@ __FBSDID("$FreeBSD$"); #ifdef HAVE_SYS_TYPES_H #include #endif -#ifdef MAJOR_IN_MKDEV +#if MAJOR_IN_MKDEV #include -#else -#ifdef MAJOR_IN_SYSMACROS +#define HAVE_MAJOR +#elif MAJOR_IN_SYSMACROS #include -#endif +#define HAVE_MAJOR #endif #ifdef HAVE_LIMITS_H #include @@ -75,6 +75,13 @@ __FBSDID("$FreeBSD$"); #undef max #define max(a, b) ((a)>(b)?(a):(b)) +#if !defined(HAVE_MAJOR) && !defined(major) +/* Replacement for major/minor/makedev. */ +#define major(x) ((int)(0x00ff & ((x) >> 8))) +#define minor(x) ((int)(0xffff00ff & (x))) +#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) +#endif + /* Play games to come up with a suitable makedev() definition. */ #ifdef __QNXNTO__ /* QNX. */ @@ -215,7 +222,7 @@ static const wchar_t * aes_get_wcs(struct aes *aes) { wchar_t *w; - int r; + size_t r; /* Return WCS form if we already have it. */ if (aes->aes_set & AES_SET_WCS) @@ -233,7 +240,7 @@ aes_get_wcs(struct aes *aes) if (w == NULL) __archive_errx(1, "No memory for aes_get_wcs()"); r = mbstowcs(w, aes->aes_mbs.s, wcs_length); - if (r > 0) { + if (r != (size_t)-1 && r != 0) { w[r] = 0; aes->aes_set |= AES_SET_WCS; return (aes->aes_wcs = w); @@ -618,6 +625,12 @@ archive_entry_ino(struct archive_entry *entry) return (entry->ae_stat.aest_ino); } +int64_t +archive_entry_ino64(struct archive_entry *entry) +{ + return (entry->ae_stat.aest_ino); +} + mode_t archive_entry_mode(struct archive_entry *entry) { @@ -817,6 +830,13 @@ archive_entry_set_ino(struct archive_entry *entry, unsigned long ino) entry->ae_stat.aest_ino = ino; } +void +archive_entry_set_ino64(struct archive_entry *entry, int64_t ino) +{ + entry->stat_valid = 0; + entry->ae_stat.aest_ino = ino; +} + void archive_entry_set_hardlink(struct archive_entry *entry, const char *target) { @@ -847,6 +867,16 @@ archive_entry_copy_hardlink_w(struct archive_entry *entry, const wchar_t *target entry->ae_set &= ~AE_SET_HARDLINK; } +int +archive_entry_update_hardlink_utf8(struct archive_entry *entry, const char *target) +{ + if (target != NULL) + entry->ae_set |= AE_SET_HARDLINK; + else + entry->ae_set &= ~AE_SET_HARDLINK; + return (aes_update_utf8(&entry->ae_hardlink, target)); +} + void archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns) { @@ -1095,6 +1125,16 @@ archive_entry_copy_symlink_w(struct archive_entry *entry, const wchar_t *linknam entry->ae_set &= ~AE_SET_SYMLINK; } +int +archive_entry_update_symlink_utf8(struct archive_entry *entry, const char *linkname) +{ + if (linkname != NULL) + entry->ae_set |= AE_SET_SYMLINK; + else + entry->ae_set &= ~AE_SET_SYMLINK; + return (aes_update_utf8(&entry->ae_symlink, linkname)); +} + void archive_entry_set_uid(struct archive_entry *entry, uid_t u) { @@ -1186,7 +1226,7 @@ archive_entry_acl_add_entry_w(struct archive_entry *entry, archive_entry_acl_add_entry_w_len(entry, type, permset, tag, id, name, wcslen(name)); } -void +static void archive_entry_acl_add_entry_w_len(struct archive_entry *entry, int type, int permset, int tag, int id, const wchar_t *name, size_t len) { @@ -1595,7 +1635,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, const wchar_t *end; } field[4], name; - int fields; + int fields, n; int type, tag, permset, id; wchar_t sep; @@ -1615,6 +1655,10 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, ++fields; } while (sep == L':'); + /* Set remaining fields to blank. */ + for (n = fields; n < 4; ++n) + field[n].start = field[n].end = NULL; + /* Check for a numeric ID in field 1 or 3. */ id = -1; isint_w(field[1].start, field[1].end, &id); @@ -1626,7 +1670,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, * Solaris extension: "defaultuser::rwx" is the * default ACL corresponding to "user::rwx", etc. */ - if (field[0].end-field[0].start > 7 + if (field[0].end - field[0].start > 7 && wmemcmp(field[0].start, L"default", 7) == 0) { type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; field[0].start += 7; @@ -1653,7 +1697,7 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, } else if (prefix_w(field[0].start, field[0].end, L"other")) { if (fields == 2 && field[1].start < field[1].end - && ismode_w(field[1].start, field[2].end, &permset)) { + && ismode_w(field[1].start, field[1].end, &permset)) { /* This is Solaris-style "other:rwx" */ } else if (fields == 3 && field[1].start == field[1].end @@ -1686,98 +1730,6 @@ __archive_entry_acl_parse_w(struct archive_entry *entry, return (ARCHIVE_OK); } -/* - * extended attribute handling - */ - -void -archive_entry_xattr_clear(struct archive_entry *entry) -{ - struct ae_xattr *xp; - - while (entry->xattr_head != NULL) { - xp = entry->xattr_head->next; - free(entry->xattr_head->name); - free(entry->xattr_head->value); - free(entry->xattr_head); - entry->xattr_head = xp; - } - - entry->xattr_head = NULL; -} - -void -archive_entry_xattr_add_entry(struct archive_entry *entry, - const char *name, const void *value, size_t size) -{ - struct ae_xattr *xp; - - for (xp = entry->xattr_head; xp != NULL; xp = xp->next) - ; - - if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL) - /* XXX Error XXX */ - return; - - xp->name = strdup(name); - if ((xp->value = malloc(size)) != NULL) { - memcpy(xp->value, value, size); - xp->size = size; - } else - xp->size = 0; - - xp->next = entry->xattr_head; - entry->xattr_head = xp; -} - - -/* - * returns number of the extended attribute entries - */ -int -archive_entry_xattr_count(struct archive_entry *entry) -{ - struct ae_xattr *xp; - int count = 0; - - for (xp = entry->xattr_head; xp != NULL; xp = xp->next) - count++; - - return count; -} - -int -archive_entry_xattr_reset(struct archive_entry * entry) -{ - entry->xattr_p = entry->xattr_head; - - return archive_entry_xattr_count(entry); -} - -int -archive_entry_xattr_next(struct archive_entry * entry, - const char **name, const void **value, size_t *size) -{ - if (entry->xattr_p) { - *name = entry->xattr_p->name; - *value = entry->xattr_p->value; - *size = entry->xattr_p->size; - - entry->xattr_p = entry->xattr_p->next; - - return (ARCHIVE_OK); - } else { - *name = NULL; - *value = NULL; - *size = (size_t)0; - return (ARCHIVE_WARN); - } -} - -/* - * end of xattr handling - */ - /* * Parse a string to a positive decimal integer. Returns true if * the string is non-empty and consists only of decimal digits, @@ -1814,6 +1766,8 @@ ismode_w(const wchar_t *start, const wchar_t *end, int *permset) { const wchar_t *p; + if (start >= end) + return (0); p = start; *permset = 0; while (p < end) { @@ -1988,6 +1942,18 @@ static struct flag { { "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 }, { "nouunlink", L"nouunlink", UF_NOUNLINK, 0 }, #endif +#ifdef EXT2_UNRM_FL + { "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0}, +#endif + +#ifdef EXT2_BTREE_FL + { "nobtree", L"nobtree", EXT2_BTREE_FL, 0 }, +#endif + +#ifdef EXT2_ECOMPR_FL + { "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 }, +#endif + #ifdef EXT2_COMPR_FL /* 'c' */ { "nocompress", L"nocompress", EXT2_COMPR_FL, 0 }, #endif @@ -1995,6 +1961,46 @@ static struct flag { #ifdef EXT2_NOATIME_FL /* 'A' */ { "noatime", L"noatime", 0, EXT2_NOATIME_FL}, #endif + +#ifdef EXT2_DIRTY_FL + { "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0}, +#endif + +#ifdef EXT2_COMPRBLK_FL +#ifdef EXT2_NOCOMPR_FL + { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL}, +#else + { "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0}, +#endif +#endif +#ifdef EXT2_DIRSYNC_FL + { "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0}, +#endif +#ifdef EXT2_INDEX_FL + { "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0}, +#endif +#ifdef EXT2_IMAGIC_FL + { "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0}, +#endif +#ifdef EXT3_JOURNAL_DATA_FL + { "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0}, +#endif +#ifdef EXT2_SECRM_FL + { "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0}, +#endif +#ifdef EXT2_SYNC_FL + { "nosync", L"nosync", EXT2_SYNC_FL, 0}, +#endif +#ifdef EXT2_NOTAIL_FL + { "notail", L"notail", 0, EXT2_NOTAIL_FL}, +#endif +#ifdef EXT2_TOPDIR_FL + { "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0}, +#endif +#ifdef EXT2_RESERVED_FL + { "noreserved", L"noreserved", EXT2_RESERVED_FL, 0}, +#endif + { NULL, NULL, 0, 0 } }; diff --git a/lib/libarchive/archive_entry.h b/lib/libarchive/archive_entry.h index a2748fdff67a..7ed2dde2c426 100644 --- a/lib/libarchive/archive_entry.h +++ b/lib/libarchive/archive_entry.h @@ -40,14 +40,25 @@ #include /* for wchar_t */ #include +#if defined(_WIN32) && !defined(__CYGWIN__) +#include +#endif + /* Get appropriate definitions of standard POSIX-style types. */ /* These should match the types used in 'struct stat' */ #if defined(_WIN32) && !defined(__CYGWIN__) #define __LA_INT64_T __int64 -#define __LA_UID_T unsigned int -#define __LA_GID_T unsigned int -#define __LA_DEV_T unsigned int -#define __LA_MODE_T unsigned short +# if defined(__BORLANDC__) +# define __LA_UID_T uid_t +# define __LA_GID_T gid_t +# define __LA_DEV_T dev_t +# define __LA_MODE_T mode_t +# else +# define __LA_UID_T short +# define __LA_GID_T short +# define __LA_DEV_T unsigned int +# define __LA_MODE_T unsigned short +# endif #else #include #define __LA_INT64_T int64_t @@ -194,6 +205,7 @@ __LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *); __LA_DECL const char *archive_entry_hardlink(struct archive_entry *); __LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *); __LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *); +__LA_DECL __LA_INT64_T archive_entry_ino64(struct archive_entry *); __LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *); __LA_DECL time_t archive_entry_mtime(struct archive_entry *); __LA_DECL long archive_entry_mtime_nsec(struct archive_entry *); @@ -227,6 +239,10 @@ __LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *); __LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long); __LA_DECL void archive_entry_unset_atime(struct archive_entry *); +#if defined(_WIN32) && !defined(__CYGWIN__) +__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, + BY_HANDLE_FILE_INFORMATION *); +#endif __LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long); __LA_DECL void archive_entry_unset_birthtime(struct archive_entry *); __LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long); @@ -251,7 +267,14 @@ __LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char __LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *); +#if ARCHIVE_VERSION_NUMBER >= 3000000 +/* Starting with libarchive 3.0, this will be synonym for ino64. */ +__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INT64_T); +#else __LA_DECL void archive_entry_set_ino(struct archive_entry *, unsigned long); +#endif +__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INT64_T); __LA_DECL void archive_entry_set_link(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *); @@ -274,6 +297,7 @@ __LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char __LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *); +__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *); __LA_DECL void archive_entry_set_uid(struct archive_entry *, __LA_UID_T); __LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *); __LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *); diff --git a/lib/libarchive/archive_entry_private.h b/lib/libarchive/archive_entry_private.h index 4614a4f8e2d0..d59021c24875 100644 --- a/lib/libarchive/archive_entry_private.h +++ b/lib/libarchive/archive_entry_private.h @@ -25,6 +25,10 @@ * $FreeBSD$ */ +#ifndef __LIBARCHIVE_BUILD +#error This header is only to be used internally to libarchive. +#endif + #ifndef ARCHIVE_ENTRY_PRIVATE_H_INCLUDED #define ARCHIVE_ENTRY_PRIVATE_H_INCLUDED @@ -115,7 +119,7 @@ struct archive_entry { int64_t aest_birthtime; uint32_t aest_birthtime_nsec; gid_t aest_gid; - ino_t aest_ino; + int64_t aest_ino; mode_t aest_mode; uint32_t aest_nlink; uint64_t aest_size; diff --git a/lib/libarchive/archive_entry_xattr.c b/lib/libarchive/archive_entry_xattr.c new file mode 100644 index 000000000000..b7e53e31544e --- /dev/null +++ b/lib/libarchive/archive_entry_xattr.c @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2003-2007 Tim Kientzle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "archive_platform.h" +__FBSDID("$FreeBSD$"); + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_LIMITS_H +#include +#endif +#ifdef HAVE_LINUX_FS_H +#include /* for Linux file flags */ +#endif +/* + * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. + * As the include guards don't agree, the order of include is important. + */ +#ifdef HAVE_LINUX_EXT2_FS_H +#include /* for Linux file flags */ +#endif +#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) +#include /* for Linux file flags */ +#endif +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_WCHAR_H +#include +#endif + +#include "archive.h" +#include "archive_entry.h" +#include "archive_private.h" +#include "archive_entry_private.h" + +/* + * extended attribute handling + */ + +void +archive_entry_xattr_clear(struct archive_entry *entry) +{ + struct ae_xattr *xp; + + while (entry->xattr_head != NULL) { + xp = entry->xattr_head->next; + free(entry->xattr_head->name); + free(entry->xattr_head->value); + free(entry->xattr_head); + entry->xattr_head = xp; + } + + entry->xattr_head = NULL; +} + +void +archive_entry_xattr_add_entry(struct archive_entry *entry, + const char *name, const void *value, size_t size) +{ + struct ae_xattr *xp; + + for (xp = entry->xattr_head; xp != NULL; xp = xp->next) + ; + + if ((xp = (struct ae_xattr *)malloc(sizeof(struct ae_xattr))) == NULL) + /* XXX Error XXX */ + return; + + xp->name = strdup(name); + if ((xp->value = malloc(size)) != NULL) { + memcpy(xp->value, value, size); + xp->size = size; + } else + xp->size = 0; + + xp->next = entry->xattr_head; + entry->xattr_head = xp; +} + + +/* + * returns number of the extended attribute entries + */ +int +archive_entry_xattr_count(struct archive_entry *entry) +{ + struct ae_xattr *xp; + int count = 0; + + for (xp = entry->xattr_head; xp != NULL; xp = xp->next) + count++; + + return count; +} + +int +archive_entry_xattr_reset(struct archive_entry * entry) +{ + entry->xattr_p = entry->xattr_head; + + return archive_entry_xattr_count(entry); +} + +int +archive_entry_xattr_next(struct archive_entry * entry, + const char **name, const void **value, size_t *size) +{ + if (entry->xattr_p) { + *name = entry->xattr_p->name; + *value = entry->xattr_p->value; + *size = entry->xattr_p->size; + + entry->xattr_p = entry->xattr_p->next; + + return (ARCHIVE_OK); + } else { + *name = NULL; + *value = NULL; + *size = (size_t)0; + return (ARCHIVE_WARN); + } +} + +/* + * end of xattr handling + */