libarchive: import changes from upstream
Libarchive 3.5.2 New features: PR #1502: Support for PWB and v7 binary cpio formats PR #1509: Support of deflate algorithm in symbolic link decompression for ZIP archives Important bugfixes: IS #1044: fix extraction of hardlinks to symlinks PR #1480: Fix truncation of size values during 7zip archive extraction on 32bit architectures PR #1504: fix rar header skiming PR #1514: ZIP excessive disk read - fix location of central directory PR #1520: fix double-free in CAB reader PR #1521: Fixed leak of rar before ending with error PR #1530: Handle short writes from archive_write_callback PR #1532: 7zip: Use compression settings from file also for file header IS #1566: do not follow symlinks when processing the fixup list MFC after: 2 weeks Relnotes: yes
This commit is contained in:
commit
ddce862ad8
@ -1,3 +1,5 @@
|
|||||||
|
Aug 22, 2021: libarchive 3.5.2 released
|
||||||
|
|
||||||
Dec 26, 2020: libarchive 3.5.1 released
|
Dec 26, 2020: libarchive 3.5.1 released
|
||||||
|
|
||||||
Dec 01, 2020: libarchive 3.5.0 released
|
Dec 01, 2020: libarchive 3.5.0 released
|
||||||
|
@ -79,6 +79,7 @@ Currently, the library automatically detects and reads the following formats:
|
|||||||
* POSIX octet-oriented cpio
|
* POSIX octet-oriented cpio
|
||||||
* SVR4 ASCII cpio
|
* SVR4 ASCII cpio
|
||||||
* Binary cpio (big-endian or little-endian)
|
* Binary cpio (big-endian or little-endian)
|
||||||
|
* PWB binary cpio
|
||||||
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
|
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
|
||||||
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
|
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
|
||||||
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
|
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
|
||||||
@ -110,6 +111,8 @@ The library can create archives in any of the following formats:
|
|||||||
* Old V7 tar format
|
* Old V7 tar format
|
||||||
* POSIX octet-oriented cpio
|
* POSIX octet-oriented cpio
|
||||||
* SVR4 "newc" cpio
|
* SVR4 "newc" cpio
|
||||||
|
* Binary cpio (little-endian)
|
||||||
|
* PWB binary cpio
|
||||||
* shar archives
|
* shar archives
|
||||||
* ZIP archives (with uncompressed or "deflate" compressed entries)
|
* ZIP archives (with uncompressed or "deflate" compressed entries)
|
||||||
* GNU and BSD 'ar' archives
|
* GNU and BSD 'ar' archives
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $FreeBSD$
|
* $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -82,6 +82,13 @@ all operating modes.
|
|||||||
.It Fl 0 , Fl Fl null
|
.It Fl 0 , Fl Fl null
|
||||||
Read filenames separated by NUL characters instead of newlines.
|
Read filenames separated by NUL characters instead of newlines.
|
||||||
This is necessary if any of the filenames being read might contain newlines.
|
This is necessary if any of the filenames being read might contain newlines.
|
||||||
|
.It Fl 6 , Fl Fl pwb
|
||||||
|
When reading a binary format archive, assume it's the earlier one,
|
||||||
|
from the PWB variant of 6th Edition UNIX.
|
||||||
|
When writing a cpio archive, use the PWB format.
|
||||||
|
.It Fl 7 , Fl Fl binary
|
||||||
|
(o mode only)
|
||||||
|
When writing a cpio archive, use the (newer, non-PWB) binary format.
|
||||||
.It Fl A
|
.It Fl A
|
||||||
(o mode only)
|
(o mode only)
|
||||||
Append to the specified archive.
|
Append to the specified archive.
|
||||||
|
@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
/*
|
/*
|
||||||
* Short options for cpio. Please keep this sorted.
|
* Short options for cpio. Please keep this sorted.
|
||||||
*/
|
*/
|
||||||
static const char *short_options = "0AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuVvW:yZz";
|
static const char *short_options = "067AaBC:cdE:F:f:H:hI:iJjLlmnO:opR:rtuVvW:yZz";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Long options for cpio. Please keep this sorted.
|
* Long options for cpio. Please keep this sorted.
|
||||||
@ -62,6 +62,7 @@ static const struct option {
|
|||||||
int equivalent; /* Equivalent short option. */
|
int equivalent; /* Equivalent short option. */
|
||||||
} cpio_longopts[] = {
|
} cpio_longopts[] = {
|
||||||
{ "b64encode", 0, OPTION_B64ENCODE },
|
{ "b64encode", 0, OPTION_B64ENCODE },
|
||||||
|
{ "binary", 0, '7' },
|
||||||
{ "create", 0, 'o' },
|
{ "create", 0, 'o' },
|
||||||
{ "dereference", 0, 'L' },
|
{ "dereference", 0, 'L' },
|
||||||
{ "dot", 0, 'V' },
|
{ "dot", 0, 'V' },
|
||||||
@ -86,6 +87,7 @@ static const struct option {
|
|||||||
{ "pass-through", 0, 'p' },
|
{ "pass-through", 0, 'p' },
|
||||||
{ "preserve-modification-time", 0, 'm' },
|
{ "preserve-modification-time", 0, 'm' },
|
||||||
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },
|
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },
|
||||||
|
{ "pwb", 0, '6' },
|
||||||
{ "quiet", 0, OPTION_QUIET },
|
{ "quiet", 0, OPTION_QUIET },
|
||||||
{ "unconditional", 0, 'u' },
|
{ "unconditional", 0, 'u' },
|
||||||
{ "uuencode", 0, OPTION_UUENCODE },
|
{ "uuencode", 0, OPTION_UUENCODE },
|
||||||
|
@ -192,6 +192,12 @@ main(int argc, char *argv[])
|
|||||||
case '0': /* GNU convention: --null, -0 */
|
case '0': /* GNU convention: --null, -0 */
|
||||||
cpio->option_null = 1;
|
cpio->option_null = 1;
|
||||||
break;
|
break;
|
||||||
|
case '6': /* in/out: assume/create 6th edition (PWB) format */
|
||||||
|
cpio->option_pwb = 1;
|
||||||
|
break;
|
||||||
|
case '7': /* out: create archive using 7th Edition binary format */
|
||||||
|
cpio->format = "bin";
|
||||||
|
break;
|
||||||
case 'A': /* NetBSD/OpenBSD */
|
case 'A': /* NetBSD/OpenBSD */
|
||||||
cpio->option_append = 1;
|
cpio->option_append = 1;
|
||||||
break;
|
break;
|
||||||
@ -400,11 +406,12 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
switch (cpio->mode) {
|
switch (cpio->mode) {
|
||||||
case 'o':
|
case 'o':
|
||||||
/* TODO: Implement old binary format in libarchive,
|
if (cpio->format == NULL) {
|
||||||
use that here. */
|
if (cpio->option_pwb)
|
||||||
if (cpio->format == NULL)
|
cpio->format = "pwb";
|
||||||
cpio->format = "odc"; /* Default format */
|
else
|
||||||
|
cpio->format = "cpio";
|
||||||
|
}
|
||||||
mode_out(cpio);
|
mode_out(cpio);
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
@ -462,7 +469,7 @@ static const char *long_help_msg =
|
|||||||
" -v Verbose filenames -V one dot per file\n"
|
" -v Verbose filenames -V one dot per file\n"
|
||||||
"Create: %p -o [options] < [list of files] > [archive]\n"
|
"Create: %p -o [options] < [list of files] > [archive]\n"
|
||||||
" -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n"
|
" -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n"
|
||||||
" --format {odc|newc|ustar} Select archive format\n"
|
" --format {pwb|bin|odc|newc|ustar} Select archive format\n"
|
||||||
"List: %p -it < [archive]\n"
|
"List: %p -it < [archive]\n"
|
||||||
"Extract: %p -i [options] < [archive]\n";
|
"Extract: %p -i [options] < [archive]\n";
|
||||||
|
|
||||||
@ -970,6 +977,8 @@ mode_in(struct cpio *cpio)
|
|||||||
lafe_errc(1, 0, "Couldn't allocate archive object");
|
lafe_errc(1, 0, "Couldn't allocate archive object");
|
||||||
archive_read_support_filter_all(a);
|
archive_read_support_filter_all(a);
|
||||||
archive_read_support_format_all(a);
|
archive_read_support_format_all(a);
|
||||||
|
if (cpio->option_pwb)
|
||||||
|
archive_read_set_options(a, "pwb");
|
||||||
if (cpio->passphrase != NULL)
|
if (cpio->passphrase != NULL)
|
||||||
r = archive_read_add_passphrase(a, cpio->passphrase);
|
r = archive_read_add_passphrase(a, cpio->passphrase);
|
||||||
else
|
else
|
||||||
@ -1080,6 +1089,8 @@ mode_list(struct cpio *cpio)
|
|||||||
lafe_errc(1, 0, "Couldn't allocate archive object");
|
lafe_errc(1, 0, "Couldn't allocate archive object");
|
||||||
archive_read_support_filter_all(a);
|
archive_read_support_filter_all(a);
|
||||||
archive_read_support_format_all(a);
|
archive_read_support_format_all(a);
|
||||||
|
if (cpio->option_pwb)
|
||||||
|
archive_read_set_options(a, "pwb");
|
||||||
if (cpio->passphrase != NULL)
|
if (cpio->passphrase != NULL)
|
||||||
r = archive_read_add_passphrase(a, cpio->passphrase);
|
r = archive_read_add_passphrase(a, cpio->passphrase);
|
||||||
else
|
else
|
||||||
|
@ -62,6 +62,7 @@ struct cpio {
|
|||||||
int option_list; /* -t */
|
int option_list; /* -t */
|
||||||
char option_null; /* --null */
|
char option_null; /* --null */
|
||||||
int option_numeric_uid_gid; /* -n */
|
int option_numeric_uid_gid; /* -n */
|
||||||
|
int option_pwb; /* -6 */
|
||||||
int option_rename; /* -r */
|
int option_rename; /* -r */
|
||||||
char *destdir;
|
char *destdir;
|
||||||
size_t destdir_len;
|
size_t destdir_len;
|
||||||
|
@ -230,6 +230,8 @@ DEFINE_TEST(test_basic)
|
|||||||
basic_cpio("copy_odc", "--format=odc", "", msg, msg);
|
basic_cpio("copy_odc", "--format=odc", "", msg, msg);
|
||||||
basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
|
basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
|
||||||
basic_cpio("copy_cpio", "-H odc", "", msg, msg);
|
basic_cpio("copy_cpio", "-H odc", "", msg, msg);
|
||||||
|
msg = "1 block\n";
|
||||||
|
basic_cpio("copy_bin", "-H bin", "", msg, msg);
|
||||||
msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
|
msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
|
||||||
basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
|
basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||||
*/
|
*/
|
||||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||||
#define ARCHIVE_VERSION_NUMBER 3005001
|
#define ARCHIVE_VERSION_NUMBER 3005002
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stddef.h> /* for wchar_t */
|
#include <stddef.h> /* for wchar_t */
|
||||||
@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
|
|||||||
/*
|
/*
|
||||||
* Textual name/version of the library, useful for version displays.
|
* Textual name/version of the library, useful for version displays.
|
||||||
*/
|
*/
|
||||||
#define ARCHIVE_VERSION_ONLY_STRING "3.5.1"
|
#define ARCHIVE_VERSION_ONLY_STRING "3.5.2"
|
||||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||||
__LA_DECL const char * archive_version_string(void);
|
__LA_DECL const char * archive_version_string(void);
|
||||||
|
|
||||||
@ -319,6 +319,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
|
|||||||
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
|
#define ARCHIVE_FORMAT_CPIO_SVR4_NOCRC (ARCHIVE_FORMAT_CPIO | 4)
|
||||||
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
#define ARCHIVE_FORMAT_CPIO_SVR4_CRC (ARCHIVE_FORMAT_CPIO | 5)
|
||||||
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
|
#define ARCHIVE_FORMAT_CPIO_AFIO_LARGE (ARCHIVE_FORMAT_CPIO | 6)
|
||||||
|
#define ARCHIVE_FORMAT_CPIO_PWB (ARCHIVE_FORMAT_CPIO | 7)
|
||||||
#define ARCHIVE_FORMAT_SHAR 0x20000
|
#define ARCHIVE_FORMAT_SHAR 0x20000
|
||||||
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
#define ARCHIVE_FORMAT_SHAR_BASE (ARCHIVE_FORMAT_SHAR | 1)
|
||||||
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
|
#define ARCHIVE_FORMAT_SHAR_DUMP (ARCHIVE_FORMAT_SHAR | 2)
|
||||||
@ -800,7 +801,10 @@ __LA_DECL int archive_write_set_format_7zip(struct archive *);
|
|||||||
__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
|
__LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
|
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_cpio(struct archive *);
|
__LA_DECL int archive_write_set_format_cpio(struct archive *);
|
||||||
|
__LA_DECL int archive_write_set_format_cpio_bin(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
|
||||||
|
__LA_DECL int archive_write_set_format_cpio_odc(struct archive *);
|
||||||
|
__LA_DECL int archive_write_set_format_cpio_pwb(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
|
__LA_DECL int archive_write_set_format_gnutar(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
|
__LA_DECL int archive_write_set_format_iso9660(struct archive *);
|
||||||
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
__LA_DECL int archive_write_set_format_mtree(struct archive *);
|
||||||
|
@ -319,7 +319,7 @@ translate_acl(struct archive_read_disk *a,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
set_acl(struct archive *a, int fd, const char *name,
|
set_acl(struct archive *a, int fd, const char *name,
|
||||||
struct archive_acl *abstract_acl,
|
struct archive_acl *abstract_acl, __LA_MODE_T mode,
|
||||||
int ae_requested_type, const char *tname)
|
int ae_requested_type, const char *tname)
|
||||||
{
|
{
|
||||||
int acl_type = 0;
|
int acl_type = 0;
|
||||||
@ -364,6 +364,13 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (acl_type == ACL_TYPE_DEFAULT && !S_ISDIR(mode)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
archive_set_error(a, errno,
|
||||||
|
"Cannot set default ACL on non-directory");
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
acl = acl_init(entries);
|
acl = acl_init(entries);
|
||||||
if (acl == (acl_t)NULL) {
|
if (acl == (acl_t)NULL) {
|
||||||
archive_set_error(a, errno,
|
archive_set_error(a, errno,
|
||||||
@ -542,7 +549,10 @@ set_acl(struct archive *a, int fd, const char *name,
|
|||||||
else if (acl_set_link_np(name, acl_type, acl) != 0)
|
else if (acl_set_link_np(name, acl_type, acl) != 0)
|
||||||
#else
|
#else
|
||||||
/* FreeBSD older than 8.0 */
|
/* FreeBSD older than 8.0 */
|
||||||
else if (acl_set_file(name, acl_type, acl) != 0)
|
else if (S_ISLNK(mode)) {
|
||||||
|
/* acl_set_file() follows symbolic links, skip */
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
} else if (acl_set_file(name, acl_type, acl) != 0)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (errno == EOPNOTSUPP) {
|
if (errno == EOPNOTSUPP) {
|
||||||
@ -677,14 +687,14 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
|
||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
& ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
|
||||||
if (ret != ARCHIVE_OK)
|
if (ret != ARCHIVE_OK)
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
if ((archive_acl_types(abstract_acl)
|
if ((archive_acl_types(abstract_acl)
|
||||||
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
& ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
|
||||||
|
|
||||||
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
/* Simultaneous POSIX.1e and NFSv4 is not supported */
|
||||||
@ -693,7 +703,7 @@ archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
|
|||||||
#if ARCHIVE_ACL_FREEBSD_NFS4
|
#if ARCHIVE_ACL_FREEBSD_NFS4
|
||||||
else if ((archive_acl_types(abstract_acl) &
|
else if ((archive_acl_types(abstract_acl) &
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
|
||||||
ret = set_acl(a, fd, name, abstract_acl,
|
ret = set_acl(a, fd, name, abstract_acl, mode,
|
||||||
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||||
|
|
||||||
/* Note: Compiler will complain if this does not match archive.h! */
|
/* Note: Compiler will complain if this does not match archive.h! */
|
||||||
#define ARCHIVE_VERSION_NUMBER 3005001
|
#define ARCHIVE_VERSION_NUMBER 3005002
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: archive_entry.h is for use outside of libarchive; the
|
* Note: archive_entry.h is for use outside of libarchive; the
|
||||||
|
@ -384,6 +384,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
|
|||||||
/* Empty pattern only matches the empty string. */
|
/* Empty pattern only matches the empty string. */
|
||||||
if (p == NULL || *p == '\0')
|
if (p == NULL || *p == '\0')
|
||||||
return (s == NULL || *s == '\0');
|
return (s == NULL || *s == '\0');
|
||||||
|
else if (s == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/* Leading '^' anchors the start of the pattern. */
|
/* Leading '^' anchors the start of the pattern. */
|
||||||
if (*p == '^') {
|
if (*p == '^') {
|
||||||
@ -424,6 +426,8 @@ __archive_pathmatch_w(const wchar_t *p, const wchar_t *s, int flags)
|
|||||||
/* Empty pattern only matches the empty string. */
|
/* Empty pattern only matches the empty string. */
|
||||||
if (p == NULL || *p == L'\0')
|
if (p == NULL || *p == L'\0')
|
||||||
return (s == NULL || *s == L'\0');
|
return (s == NULL || *s == L'\0');
|
||||||
|
else if (s == NULL)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/* Leading '^' anchors the start of the pattern. */
|
/* Leading '^' anchors the start of the pattern. */
|
||||||
if (*p == L'^') {
|
if (*p == L'^') {
|
||||||
|
@ -46,6 +46,13 @@
|
|||||||
#define __LA_DEAD
|
#define __LA_DEAD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && (__GNUC__ > 2 || \
|
||||||
|
(__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
|
||||||
|
#define __LA_UNUSED __attribute__((__unused__))
|
||||||
|
#else
|
||||||
|
#define __LA_UNUSED
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
|
#define ARCHIVE_WRITE_MAGIC (0xb0c5c0deU)
|
||||||
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
|
#define ARCHIVE_READ_MAGIC (0xdeb0c5U)
|
||||||
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)
|
||||||
|
@ -173,7 +173,7 @@ arc4_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
arc4_addrandom(u_char *dat, int datlen)
|
arc4_addrandom(uint8_t *dat, int datlen)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
uint8_t si;
|
uint8_t si;
|
||||||
@ -196,7 +196,7 @@ arc4_stir(void)
|
|||||||
struct {
|
struct {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
u_char rnd[KEYSIZE];
|
uint8_t rnd[KEYSIZE];
|
||||||
} rdat;
|
} rdat;
|
||||||
|
|
||||||
if (!rs_initialized) {
|
if (!rs_initialized) {
|
||||||
@ -216,7 +216,7 @@ arc4_stir(void)
|
|||||||
/* We'll just take whatever was on the stack too... */
|
/* We'll just take whatever was on the stack too... */
|
||||||
}
|
}
|
||||||
|
|
||||||
arc4_addrandom((u_char *)&rdat, KEYSIZE);
|
arc4_addrandom((uint8_t *)&rdat, KEYSIZE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Discard early keystream, as per recommendations in:
|
* Discard early keystream, as per recommendations in:
|
||||||
@ -258,7 +258,7 @@ arc4_getbyte(void)
|
|||||||
static void
|
static void
|
||||||
arc4random_buf(void *_buf, size_t n)
|
arc4random_buf(void *_buf, size_t n)
|
||||||
{
|
{
|
||||||
u_char *buf = (u_char *)_buf;
|
uint8_t *buf = (uint8_t *)_buf;
|
||||||
_ARC4_LOCK();
|
_ARC4_LOCK();
|
||||||
arc4_stir_if_needed();
|
arc4_stir_if_needed();
|
||||||
while (n--) {
|
while (n--) {
|
||||||
|
@ -1522,8 +1522,40 @@ get_xfer_size(struct tree *t, int fd, const char *path)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \
|
#if defined(HAVE_STATVFS)
|
||||||
&& !defined(ST_LOCAL)
|
static inline __LA_UNUSED void
|
||||||
|
set_statvfs_transfer_size(struct filesystem *fs, const struct statvfs *sfs)
|
||||||
|
{
|
||||||
|
fs->xfer_align = sfs->f_frsize > 0 ? (long)sfs->f_frsize : -1;
|
||||||
|
fs->max_xfer_size = -1;
|
||||||
|
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
|
||||||
|
fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
#else
|
||||||
|
fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_STRUCT_STATFS)
|
||||||
|
static inline __LA_UNUSED void
|
||||||
|
set_statfs_transfer_size(struct filesystem *fs, const struct statfs *sfs)
|
||||||
|
{
|
||||||
|
fs->xfer_align = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
fs->max_xfer_size = -1;
|
||||||
|
#if defined(HAVE_STRUCT_STATFS_F_IOSIZE)
|
||||||
|
fs->min_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_iosize > 0 ? (long)sfs->f_iosize : -1;
|
||||||
|
#else
|
||||||
|
fs->min_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
fs->incr_xfer_size = sfs->f_bsize > 0 ? (long)sfs->f_bsize : -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_STRUCT_STATFS) && defined(HAVE_STATFS) && \
|
||||||
|
defined(HAVE_FSTATFS) && defined(MNT_LOCAL) && !defined(ST_LOCAL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
|
* Gather current filesystem properties on FreeBSD, OpenBSD and Mac OS X.
|
||||||
@ -1593,10 +1625,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||||
t->current_filesystem->xfer_align = sfs.f_bsize;
|
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = sfs.f_iosize;
|
|
||||||
t->current_filesystem->incr_xfer_size = sfs.f_iosize;
|
|
||||||
}
|
}
|
||||||
if (sfs.f_flags & MNT_LOCAL)
|
if (sfs.f_flags & MNT_LOCAL)
|
||||||
t->current_filesystem->remote = 0;
|
t->current_filesystem->remote = 0;
|
||||||
@ -1688,15 +1717,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
|
||||||
* for pathconf() function. */
|
* for pathconf() function. */
|
||||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
#if defined(HAVE_STRUCT_STATVFS_F_IOSIZE)
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_iosize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_iosize;
|
|
||||||
#else
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (svfs.f_flag & ST_LOCAL)
|
if (svfs.f_flag & ST_LOCAL)
|
||||||
t->current_filesystem->remote = 0;
|
t->current_filesystem->remote = 0;
|
||||||
@ -1803,15 +1824,9 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||||
#if defined(HAVE_STATVFS)
|
#if defined(HAVE_STATVFS)
|
||||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
|
|
||||||
#else
|
#else
|
||||||
t->current_filesystem->xfer_align = sfs.f_frsize;
|
set_statfs_transfer_size(t->current_filesystem, &sfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = sfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = sfs.f_bsize;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
switch (sfs.f_type) {
|
switch (sfs.f_type) {
|
||||||
@ -1918,10 +1933,7 @@ setup_current_filesystem(struct archive_read_disk *a)
|
|||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
} else if (xr == 1) {
|
} else if (xr == 1) {
|
||||||
/* pathconf(_PC_REX_*) operations are not supported. */
|
/* pathconf(_PC_REX_*) operations are not supported. */
|
||||||
t->current_filesystem->xfer_align = svfs.f_frsize;
|
set_statvfs_transfer_size(t->current_filesystem, &svfs);
|
||||||
t->current_filesystem->max_xfer_size = -1;
|
|
||||||
t->current_filesystem->min_xfer_size = svfs.f_bsize;
|
|
||||||
t->current_filesystem->incr_xfer_size = svfs.f_bsize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(ST_NOATIME)
|
#if defined(ST_NOATIME)
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "archive_platform.h"
|
#include "archive_platform.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26 17:00:22 kientzle Exp $");
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -188,9 +188,18 @@ used when translating file names.
|
|||||||
.El
|
.El
|
||||||
.It Format cpio
|
.It Format cpio
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
|
.It Cm compat-2x
|
||||||
|
Libarchive 2.x incorrectly encoded Unicode filenames on
|
||||||
|
some platforms.
|
||||||
|
This option mimics the libarchive 2.x filename handling
|
||||||
|
so that such archives can be read correctly.
|
||||||
.It Cm hdrcharset
|
.It Cm hdrcharset
|
||||||
The value is used as a character set name that will be
|
The value is used as a character set name that will be
|
||||||
used when translating file names.
|
used when translating file names.
|
||||||
|
.It Cm pwb
|
||||||
|
When reading a binary CPIO archive, assume that it is
|
||||||
|
in the original PWB cpio format, and handle file mode
|
||||||
|
bits accordingly. The default is to assume v7 format.
|
||||||
.El
|
.El
|
||||||
.It Format iso9660
|
.It Format iso9660
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
|
@ -216,7 +216,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
|
|||||||
archive_set_error(
|
archive_set_error(
|
||||||
&self->archive->archive,
|
&self->archive->archive,
|
||||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
"Unrecoginized rpm header");
|
"Unrecognized rpm header");
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
}
|
}
|
||||||
rpm->state = ST_ARCHIVE;
|
rpm->state = ST_ARCHIVE;
|
||||||
|
@ -248,7 +248,7 @@ bid_get_line(struct archive_read_filter *filter,
|
|||||||
*ravail = *avail;
|
*ravail = *avail;
|
||||||
*b += diff;
|
*b += diff;
|
||||||
*avail -= diff;
|
*avail -= diff;
|
||||||
tested = len;/* Skip some bytes we already determinated. */
|
tested = len;/* Skip some bytes we already determined. */
|
||||||
len = get_line(*b + tested, *avail - tested, nl);
|
len = get_line(*b + tested, *avail - tested, nl);
|
||||||
if (len >= 0)
|
if (len >= 0)
|
||||||
len += tested;
|
len += tested;
|
||||||
|
@ -808,8 +808,12 @@ archive_read_format_7zip_read_data(struct archive_read *a,
|
|||||||
if (zip->end_of_entry)
|
if (zip->end_of_entry)
|
||||||
return (ARCHIVE_EOF);
|
return (ARCHIVE_EOF);
|
||||||
|
|
||||||
bytes = read_stream(a, buff,
|
const uint64_t max_read_size = 16 * 1024 * 1024; // Don't try to read more than 16 MB at a time
|
||||||
(size_t)zip->entry_bytes_remaining, 0);
|
size_t bytes_to_read = max_read_size;
|
||||||
|
if ((uint64_t)bytes_to_read > zip->entry_bytes_remaining) {
|
||||||
|
bytes_to_read = zip->entry_bytes_remaining;
|
||||||
|
}
|
||||||
|
bytes = read_stream(a, buff, bytes_to_read, 0);
|
||||||
if (bytes < 0)
|
if (bytes < 0)
|
||||||
return ((int)bytes);
|
return ((int)bytes);
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
@ -1493,7 +1497,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
|||||||
zip->ppmd7_stat = -1;
|
zip->ppmd7_stat = -1;
|
||||||
archive_set_error(&a->archive,
|
archive_set_error(&a->archive,
|
||||||
ARCHIVE_ERRNO_MISC,
|
ARCHIVE_ERRNO_MISC,
|
||||||
"Failed to initialize PPMd range decorder");
|
"Failed to initialize PPMd range decoder");
|
||||||
return (ARCHIVE_FAILED);
|
return (ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
if (zip->ppstream.overconsumed) {
|
if (zip->ppstream.overconsumed) {
|
||||||
@ -3031,10 +3035,10 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
|
|||||||
"Truncated 7-Zip file body");
|
"Truncated 7-Zip file body");
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
}
|
}
|
||||||
if (bytes_avail > (ssize_t)zip->pack_stream_inbytes_remaining)
|
if ((uint64_t)bytes_avail > zip->pack_stream_inbytes_remaining)
|
||||||
bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
|
bytes_avail = (ssize_t)zip->pack_stream_inbytes_remaining;
|
||||||
zip->pack_stream_inbytes_remaining -= bytes_avail;
|
zip->pack_stream_inbytes_remaining -= bytes_avail;
|
||||||
if (bytes_avail > (ssize_t)zip->folder_outbytes_remaining)
|
if ((uint64_t)bytes_avail > zip->folder_outbytes_remaining)
|
||||||
bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
|
bytes_avail = (ssize_t)zip->folder_outbytes_remaining;
|
||||||
zip->folder_outbytes_remaining -= bytes_avail;
|
zip->folder_outbytes_remaining -= bytes_avail;
|
||||||
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
|
zip->uncompressed_buffer_bytes_remaining = bytes_avail;
|
||||||
|
@ -2110,7 +2110,6 @@ lzx_decode_init(struct lzx_stream *strm, int w_bits)
|
|||||||
ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
|
ds->pos_tbl = malloc(sizeof(ds->pos_tbl[0]) * w_slot);
|
||||||
if (ds->pos_tbl == NULL)
|
if (ds->pos_tbl == NULL)
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
lzx_huffman_free(&(ds->mt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (footer = 0; footer < 18; footer++)
|
for (footer = 0; footer < 18; footer++)
|
||||||
|
@ -185,6 +185,8 @@ struct cpio {
|
|||||||
struct archive_string_conv *opt_sconv;
|
struct archive_string_conv *opt_sconv;
|
||||||
struct archive_string_conv *sconv_default;
|
struct archive_string_conv *sconv_default;
|
||||||
int init_default_conversion;
|
int init_default_conversion;
|
||||||
|
|
||||||
|
int option_pwb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int64_t atol16(const char *, unsigned);
|
static int64_t atol16(const char *, unsigned);
|
||||||
@ -343,6 +345,10 @@ archive_read_format_cpio_options(struct archive_read *a,
|
|||||||
ret = ARCHIVE_FATAL;
|
ret = ARCHIVE_FATAL;
|
||||||
}
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
|
} else if (strcmp(key, "pwb") == 0) {
|
||||||
|
if (val != NULL && val[0] != 0)
|
||||||
|
cpio->option_pwb = 1;
|
||||||
|
return (ARCHIVE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: The "warn" return is just to inform the options
|
/* Note: The "warn" return is just to inform the options
|
||||||
@ -891,6 +897,12 @@ header_bin_le(struct archive_read *a, struct cpio *cpio,
|
|||||||
archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256);
|
archive_entry_set_dev(entry, header[bin_dev_offset] + header[bin_dev_offset + 1] * 256);
|
||||||
archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256);
|
archive_entry_set_ino(entry, header[bin_ino_offset] + header[bin_ino_offset + 1] * 256);
|
||||||
archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256);
|
archive_entry_set_mode(entry, header[bin_mode_offset] + header[bin_mode_offset + 1] * 256);
|
||||||
|
if (cpio->option_pwb) {
|
||||||
|
/* turn off random bits left over from V6 inode */
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
|
||||||
|
if ((archive_entry_mode(entry) & AE_IFMT) == 0)
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
|
||||||
|
}
|
||||||
archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256);
|
archive_entry_set_uid(entry, header[bin_uid_offset] + header[bin_uid_offset + 1] * 256);
|
||||||
archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256);
|
archive_entry_set_gid(entry, header[bin_gid_offset] + header[bin_gid_offset + 1] * 256);
|
||||||
archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256);
|
archive_entry_set_nlink(entry, header[bin_nlink_offset] + header[bin_nlink_offset + 1] * 256);
|
||||||
@ -930,6 +942,12 @@ header_bin_be(struct archive_read *a, struct cpio *cpio,
|
|||||||
archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
|
archive_entry_set_dev(entry, header[bin_dev_offset] * 256 + header[bin_dev_offset + 1]);
|
||||||
archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
|
archive_entry_set_ino(entry, header[bin_ino_offset] * 256 + header[bin_ino_offset + 1]);
|
||||||
archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
|
archive_entry_set_mode(entry, header[bin_mode_offset] * 256 + header[bin_mode_offset + 1]);
|
||||||
|
if (cpio->option_pwb) {
|
||||||
|
/* turn off random bits left over from V6 inode */
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) & 067777);
|
||||||
|
if ((archive_entry_mode(entry) & AE_IFMT) == 0)
|
||||||
|
archive_entry_set_mode(entry, archive_entry_mode(entry) | AE_IFREG);
|
||||||
|
}
|
||||||
archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
|
archive_entry_set_uid(entry, header[bin_uid_offset] * 256 + header[bin_uid_offset + 1]);
|
||||||
archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
|
archive_entry_set_gid(entry, header[bin_gid_offset] * 256 + header[bin_gid_offset + 1]);
|
||||||
archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
|
archive_entry_set_nlink(entry, header[bin_nlink_offset] * 256 + header[bin_nlink_offset + 1]);
|
||||||
|
@ -408,7 +408,7 @@ next_line(struct archive_read *a,
|
|||||||
*ravail = *avail;
|
*ravail = *avail;
|
||||||
*b += diff;
|
*b += diff;
|
||||||
*avail -= diff;
|
*avail -= diff;
|
||||||
tested = len;/* Skip some bytes we already determinated. */
|
tested = len;/* Skip some bytes we already determined. */
|
||||||
len = get_line_size(*b + len, *avail - len, nl);
|
len = get_line_size(*b + len, *avail - len, nl);
|
||||||
if (len >= 0)
|
if (len >= 0)
|
||||||
len += tested;
|
len += tested;
|
||||||
@ -1074,7 +1074,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
|||||||
continue;
|
continue;
|
||||||
/* Non-printable characters are not allowed */
|
/* Non-printable characters are not allowed */
|
||||||
for (s = p;s < p + len - 1; s++) {
|
for (s = p;s < p + len - 1; s++) {
|
||||||
if (!isprint(*s)) {
|
if (!isprint((unsigned char)*s)) {
|
||||||
r = ARCHIVE_FATAL;
|
r = ARCHIVE_FATAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2035,13 +2035,13 @@ mtree_atol(char **p, int base)
|
|||||||
|
|
||||||
if (**p == '-') {
|
if (**p == '-') {
|
||||||
limit = INT64_MIN / base;
|
limit = INT64_MIN / base;
|
||||||
last_digit_limit = INT64_MIN % base;
|
last_digit_limit = -(INT64_MIN % base);
|
||||||
++(*p);
|
++(*p);
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
digit = parsedigit(**p);
|
digit = parsedigit(**p);
|
||||||
while (digit >= 0 && digit < base) {
|
while (digit >= 0 && digit < base) {
|
||||||
if (l < limit || (l == limit && digit > last_digit_limit))
|
if (l < limit || (l == limit && digit >= last_digit_limit))
|
||||||
return INT64_MIN;
|
return INT64_MIN;
|
||||||
l = (l * base) - digit;
|
l = (l * base) - digit;
|
||||||
digit = parsedigit(*++(*p));
|
digit = parsedigit(*++(*p));
|
||||||
|
@ -958,17 +958,17 @@ archive_read_format_rar_read_header(struct archive_read *a,
|
|||||||
crc32_val = 0;
|
crc32_val = 0;
|
||||||
while (skip > 0) {
|
while (skip > 0) {
|
||||||
size_t to_read = skip;
|
size_t to_read = skip;
|
||||||
ssize_t did_read;
|
if (to_read > 32 * 1024)
|
||||||
if (to_read > 32 * 1024) {
|
|
||||||
to_read = 32 * 1024;
|
to_read = 32 * 1024;
|
||||||
}
|
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
|
||||||
if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Bad RAR file");
|
||||||
return (ARCHIVE_FATAL);
|
return (ARCHIVE_FATAL);
|
||||||
}
|
}
|
||||||
p = h;
|
p = h;
|
||||||
crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
|
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
|
||||||
__archive_read_consume(a, did_read);
|
__archive_read_consume(a, to_read);
|
||||||
skip -= did_read;
|
skip -= to_read;
|
||||||
}
|
}
|
||||||
if ((crc32_val & 0xffff) != crc32_expected) {
|
if ((crc32_val & 0xffff) != crc32_expected) {
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
@ -4076,6 +4076,7 @@ int archive_read_support_format_rar5(struct archive *_a) {
|
|||||||
if(ARCHIVE_OK != rar5_init(rar)) {
|
if(ARCHIVE_OK != rar5_init(rar)) {
|
||||||
archive_set_error(&ar->archive, ENOMEM,
|
archive_set_error(&ar->archive, ENOMEM,
|
||||||
"Can't allocate rar5 filter buffer");
|
"Can't allocate rar5 filter buffer");
|
||||||
|
free(rar);
|
||||||
return ARCHIVE_FATAL;
|
return ARCHIVE_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1908,7 +1908,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
|||||||
}
|
}
|
||||||
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
|
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
|
||||||
tar->sparse_numbytes = tar_atol10(value, strlen(value));
|
tar->sparse_numbytes = tar_atol10(value, strlen(value));
|
||||||
if (tar->sparse_numbytes != -1) {
|
if (tar->sparse_offset != -1) {
|
||||||
if (gnu_add_sparse_entry(a, tar,
|
if (gnu_add_sparse_entry(a, tar,
|
||||||
tar->sparse_offset, tar->sparse_numbytes)
|
tar->sparse_offset, tar->sparse_numbytes)
|
||||||
!= ARCHIVE_OK)
|
!= ARCHIVE_OK)
|
||||||
@ -2645,14 +2645,14 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
|
|||||||
|
|
||||||
maxval = INT64_MIN;
|
maxval = INT64_MIN;
|
||||||
limit = -(INT64_MIN / base);
|
limit = -(INT64_MIN / base);
|
||||||
last_digit_limit = INT64_MIN % base;
|
last_digit_limit = -(INT64_MIN % base);
|
||||||
}
|
}
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
if (char_cnt != 0) {
|
if (char_cnt != 0) {
|
||||||
digit = *p - '0';
|
digit = *p - '0';
|
||||||
while (digit >= 0 && digit < base && char_cnt != 0) {
|
while (digit >= 0 && digit < base && char_cnt != 0) {
|
||||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
if (l>limit || (l == limit && digit >= last_digit_limit)) {
|
||||||
return maxval; /* Truncate on overflow. */
|
return maxval; /* Truncate on overflow. */
|
||||||
}
|
}
|
||||||
l = (l * base) + digit;
|
l = (l * base) + digit;
|
||||||
|
@ -142,6 +142,7 @@ struct zip {
|
|||||||
/* Structural information about the archive. */
|
/* Structural information about the archive. */
|
||||||
struct archive_string format_name;
|
struct archive_string format_name;
|
||||||
int64_t central_directory_offset;
|
int64_t central_directory_offset;
|
||||||
|
int64_t central_directory_offset_adjusted;
|
||||||
size_t central_directory_entries_total;
|
size_t central_directory_entries_total;
|
||||||
size_t central_directory_entries_on_this_disk;
|
size_t central_directory_entries_on_this_disk;
|
||||||
int has_encrypted_entries;
|
int has_encrypted_entries;
|
||||||
@ -246,6 +247,17 @@ struct zip {
|
|||||||
/* Many systems define min or MIN, but not all. */
|
/* Many systems define min or MIN, but not all. */
|
||||||
#define zipmin(a,b) ((a) < (b) ? (a) : (b))
|
#define zipmin(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
|
#ifdef HAVE_ZLIB_H
|
||||||
|
static int
|
||||||
|
zip_read_data_deflate(struct archive_read *a, const void **buff,
|
||||||
|
size_t *size, int64_t *offset);
|
||||||
|
#endif
|
||||||
|
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||||
|
static int
|
||||||
|
zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
|
||||||
|
size_t *size, int64_t *offset);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
|
/* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
|
||||||
* streams inside ZIP files. It has 2 purposes: one is to fetch the next
|
* streams inside ZIP files. It has 2 purposes: one is to fetch the next
|
||||||
* compressed byte from the stream, second one is to increase the counter how
|
* compressed byte from the stream, second one is to increase the counter how
|
||||||
@ -899,81 +911,6 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
|
|||||||
return ARCHIVE_OK;
|
return ARCHIVE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
|
||||||
/*
|
|
||||||
* Auxiliary function to uncompress data chunk from zipx archive
|
|
||||||
* (zip with lzma compression).
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
zipx_lzma_uncompress_buffer(const char *compressed_buffer,
|
|
||||||
size_t compressed_buffer_size,
|
|
||||||
char *uncompressed_buffer,
|
|
||||||
size_t uncompressed_buffer_size)
|
|
||||||
{
|
|
||||||
int status = ARCHIVE_FATAL;
|
|
||||||
// length of 'lzma properties data' in lzma compressed
|
|
||||||
// data segment (stream) inside zip archive
|
|
||||||
const size_t lzma_params_length = 5;
|
|
||||||
// offset of 'lzma properties data' from the beginning of lzma stream
|
|
||||||
const size_t lzma_params_offset = 4;
|
|
||||||
// end position of 'lzma properties data' in lzma stream
|
|
||||||
const size_t lzma_params_end = lzma_params_offset + lzma_params_length;
|
|
||||||
if (compressed_buffer == NULL ||
|
|
||||||
compressed_buffer_size < lzma_params_end ||
|
|
||||||
uncompressed_buffer == NULL)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
// prepare header for lzma_alone_decoder to replace zipx header
|
|
||||||
// (see comments in 'zipx_lzma_alone_init' for justification)
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
struct _alone_header
|
|
||||||
{
|
|
||||||
uint8_t bytes[5]; // lzma_params_length
|
|
||||||
uint64_t uncompressed_size;
|
|
||||||
} alone_header;
|
|
||||||
#pragma pack(pop)
|
|
||||||
// copy 'lzma properties data' blob
|
|
||||||
memcpy(&alone_header.bytes[0], compressed_buffer + lzma_params_offset,
|
|
||||||
lzma_params_length);
|
|
||||||
alone_header.uncompressed_size = UINT64_MAX;
|
|
||||||
|
|
||||||
// prepare new compressed buffer, see 'zipx_lzma_alone_init' for details
|
|
||||||
const size_t lzma_alone_buffer_size =
|
|
||||||
compressed_buffer_size - lzma_params_end + sizeof(alone_header);
|
|
||||||
unsigned char *lzma_alone_compressed_buffer =
|
|
||||||
(unsigned char*) malloc(lzma_alone_buffer_size);
|
|
||||||
if (lzma_alone_compressed_buffer == NULL)
|
|
||||||
return status;
|
|
||||||
// copy lzma_alone header into new buffer
|
|
||||||
memcpy(lzma_alone_compressed_buffer, (void*) &alone_header,
|
|
||||||
sizeof(alone_header));
|
|
||||||
// copy compressed data into new buffer
|
|
||||||
memcpy(lzma_alone_compressed_buffer + sizeof(alone_header),
|
|
||||||
compressed_buffer + lzma_params_end,
|
|
||||||
compressed_buffer_size - lzma_params_end);
|
|
||||||
|
|
||||||
// create and fill in lzma_alone_decoder stream
|
|
||||||
lzma_stream stream = LZMA_STREAM_INIT;
|
|
||||||
lzma_ret ret = lzma_alone_decoder(&stream, UINT64_MAX);
|
|
||||||
if (ret == LZMA_OK)
|
|
||||||
{
|
|
||||||
stream.next_in = lzma_alone_compressed_buffer;
|
|
||||||
stream.avail_in = lzma_alone_buffer_size;
|
|
||||||
stream.total_in = 0;
|
|
||||||
stream.next_out = (unsigned char*)uncompressed_buffer;
|
|
||||||
stream.avail_out = uncompressed_buffer_size;
|
|
||||||
stream.total_out = 0;
|
|
||||||
ret = lzma_code(&stream, LZMA_RUN);
|
|
||||||
if (ret == LZMA_OK || ret == LZMA_STREAM_END)
|
|
||||||
status = ARCHIVE_OK;
|
|
||||||
}
|
|
||||||
lzma_end(&stream);
|
|
||||||
free(lzma_alone_compressed_buffer);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Assumes file pointer is at beginning of local file header.
|
* Assumes file pointer is at beginning of local file header.
|
||||||
*/
|
*/
|
||||||
@ -1242,36 +1179,30 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||||||
linkname_length = (size_t)zip_entry->compressed_size;
|
linkname_length = (size_t)zip_entry->compressed_size;
|
||||||
|
|
||||||
archive_entry_set_size(entry, 0);
|
archive_entry_set_size(entry, 0);
|
||||||
p = __archive_read_ahead(a, linkname_length, NULL);
|
|
||||||
if (p == NULL) {
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
||||||
"Truncated Zip file");
|
|
||||||
return ARCHIVE_FATAL;
|
|
||||||
}
|
|
||||||
// take into account link compression if any
|
// take into account link compression if any
|
||||||
size_t linkname_full_length = linkname_length;
|
size_t linkname_full_length = linkname_length;
|
||||||
if (zip->entry->compression != 0)
|
if (zip->entry->compression != 0)
|
||||||
{
|
{
|
||||||
// symlink target string appeared to be compressed
|
// symlink target string appeared to be compressed
|
||||||
int status = ARCHIVE_FATAL;
|
int status = ARCHIVE_FATAL;
|
||||||
char *uncompressed_buffer =
|
const void *uncompressed_buffer;
|
||||||
(char*) malloc(zip_entry->uncompressed_size);
|
|
||||||
if (uncompressed_buffer == NULL)
|
|
||||||
{
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"No memory for lzma decompression");
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (zip->entry->compression)
|
switch (zip->entry->compression)
|
||||||
{
|
{
|
||||||
|
#if HAVE_ZLIB_H
|
||||||
|
case 8: /* Deflate compression. */
|
||||||
|
zip->entry_bytes_remaining = zip_entry->compressed_size;
|
||||||
|
status = zip_read_data_deflate(a, &uncompressed_buffer,
|
||||||
|
&linkname_full_length, NULL);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
#if HAVE_LZMA_H && HAVE_LIBLZMA
|
||||||
case 14: /* ZIPx LZMA compression. */
|
case 14: /* ZIPx LZMA compression. */
|
||||||
/*(see zip file format specification, section 4.4.5)*/
|
/*(see zip file format specification, section 4.4.5)*/
|
||||||
status = zipx_lzma_uncompress_buffer(p,
|
zip->entry_bytes_remaining = zip_entry->compressed_size;
|
||||||
linkname_length,
|
status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
|
||||||
uncompressed_buffer,
|
&linkname_full_length, NULL);
|
||||||
(size_t)zip_entry->uncompressed_size);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: /* Unsupported compression. */
|
default: /* Unsupported compression. */
|
||||||
@ -1280,8 +1211,6 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||||||
if (status == ARCHIVE_OK)
|
if (status == ARCHIVE_OK)
|
||||||
{
|
{
|
||||||
p = uncompressed_buffer;
|
p = uncompressed_buffer;
|
||||||
linkname_full_length =
|
|
||||||
(size_t)zip_entry->uncompressed_size;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1294,6 +1223,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
|
|||||||
return ARCHIVE_FAILED;
|
return ARCHIVE_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = __archive_read_ahead(a, linkname_length, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == NULL) {
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||||
|
"Truncated Zip file");
|
||||||
|
return ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
sconv = zip->sconv;
|
sconv = zip->sconv;
|
||||||
if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
|
if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
|
||||||
@ -1663,7 +1602,8 @@ zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
|
|||||||
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
|
/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
|
||||||
* that is a part of XZ Utils. The stream format stored inside ZIPX
|
* that is a part of XZ Utils. The stream format stored inside ZIPX
|
||||||
* file is a modified "lzma alone" file format, that was used by the
|
* file is a modified "lzma alone" file format, that was used by the
|
||||||
* `lzma` utility which was later deprecated in favour of `xz` utility. * Since those formats are nearly the same, we can use a standard
|
* `lzma` utility which was later deprecated in favour of `xz` utility.
|
||||||
|
* Since those formats are nearly the same, we can use a standard
|
||||||
* "lzma alone" decoder from XZ Utils. */
|
* "lzma alone" decoder from XZ Utils. */
|
||||||
|
|
||||||
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
|
memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
|
||||||
@ -3415,24 +3355,31 @@ archive_read_support_format_zip_capabilities_seekable(struct archive_read * a)
|
|||||||
static int
|
static int
|
||||||
read_eocd(struct zip *zip, const char *p, int64_t current_offset)
|
read_eocd(struct zip *zip, const char *p, int64_t current_offset)
|
||||||
{
|
{
|
||||||
|
uint16_t disk_num;
|
||||||
|
uint32_t cd_size, cd_offset;
|
||||||
|
|
||||||
|
disk_num = archive_le16dec(p + 4);
|
||||||
|
cd_size = archive_le32dec(p + 12);
|
||||||
|
cd_offset = archive_le32dec(p + 16);
|
||||||
|
|
||||||
/* Sanity-check the EOCD we've found. */
|
/* Sanity-check the EOCD we've found. */
|
||||||
|
|
||||||
/* This must be the first volume. */
|
/* This must be the first volume. */
|
||||||
if (archive_le16dec(p + 4) != 0)
|
if (disk_num != 0)
|
||||||
return 0;
|
return 0;
|
||||||
/* Central directory must be on this volume. */
|
/* Central directory must be on this volume. */
|
||||||
if (archive_le16dec(p + 4) != archive_le16dec(p + 6))
|
if (disk_num != archive_le16dec(p + 6))
|
||||||
return 0;
|
return 0;
|
||||||
/* All central directory entries must be on this volume. */
|
/* All central directory entries must be on this volume. */
|
||||||
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
|
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
|
||||||
return 0;
|
return 0;
|
||||||
/* Central directory can't extend beyond start of EOCD record. */
|
/* Central directory can't extend beyond start of EOCD record. */
|
||||||
if (archive_le32dec(p + 16) + archive_le32dec(p + 12)
|
if (cd_offset + cd_size > current_offset)
|
||||||
> current_offset)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Save the central directory location for later use. */
|
/* Save the central directory location for later use. */
|
||||||
zip->central_directory_offset = archive_le32dec(p + 16);
|
zip->central_directory_offset = cd_offset;
|
||||||
|
zip->central_directory_offset_adjusted = current_offset - cd_size;
|
||||||
|
|
||||||
/* This is just a tiny bit higher than the maximum
|
/* This is just a tiny bit higher than the maximum
|
||||||
returned by the streaming Zip bidder. This ensures
|
returned by the streaming Zip bidder. This ensures
|
||||||
@ -3484,6 +3431,8 @@ read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
|
|||||||
|
|
||||||
/* Save the central directory offset for later use. */
|
/* Save the central directory offset for later use. */
|
||||||
zip->central_directory_offset = archive_le64dec(p + 48);
|
zip->central_directory_offset = archive_le64dec(p + 48);
|
||||||
|
/* TODO: Needs scanning backwards to find the eocd64 instead of assuming */
|
||||||
|
zip->central_directory_offset_adjusted = zip->central_directory_offset;
|
||||||
|
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
@ -3655,7 +3604,8 @@ slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
|
|||||||
* know the correction we need to apply to account for leading
|
* know the correction we need to apply to account for leading
|
||||||
* padding.
|
* padding.
|
||||||
*/
|
*/
|
||||||
if (__archive_read_seek(a, zip->central_directory_offset, SEEK_SET) < 0)
|
if (__archive_read_seek(a, zip->central_directory_offset_adjusted, SEEK_SET)
|
||||||
|
< 0)
|
||||||
return ARCHIVE_FATAL;
|
return ARCHIVE_FATAL;
|
||||||
|
|
||||||
found = 0;
|
found = 0;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "archive_platform.h"
|
#include "archive_platform.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:14Z kientzle $");
|
||||||
|
|
||||||
#ifdef HAVE_STDLIB_H
|
#ifdef HAVE_STDLIB_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -482,6 +482,8 @@ archive_write_client_close(struct archive_write_filter *f)
|
|||||||
ssize_t block_length;
|
ssize_t block_length;
|
||||||
ssize_t target_block_length;
|
ssize_t target_block_length;
|
||||||
ssize_t bytes_written;
|
ssize_t bytes_written;
|
||||||
|
size_t to_write;
|
||||||
|
char *p;
|
||||||
int ret = ARCHIVE_OK;
|
int ret = ARCHIVE_OK;
|
||||||
|
|
||||||
/* If there's pending data, pad and write the last block */
|
/* If there's pending data, pad and write the last block */
|
||||||
@ -504,9 +506,24 @@ archive_write_client_close(struct archive_write_filter *f)
|
|||||||
target_block_length - block_length);
|
target_block_length - block_length);
|
||||||
block_length = target_block_length;
|
block_length = target_block_length;
|
||||||
}
|
}
|
||||||
|
p = state->buffer;
|
||||||
|
to_write = block_length;
|
||||||
|
while (to_write > 0) {
|
||||||
bytes_written = (a->client_writer)(&a->archive,
|
bytes_written = (a->client_writer)(&a->archive,
|
||||||
a->client_data, state->buffer, block_length);
|
a->client_data, p, to_write);
|
||||||
ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
|
if (bytes_written <= 0) {
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((size_t)bytes_written > to_write) {
|
||||||
|
archive_set_error(&(a->archive),
|
||||||
|
-1, "write overrun");
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p += bytes_written;
|
||||||
|
to_write -= bytes_written;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (a->client_closer)
|
if (a->client_closer)
|
||||||
(*a->client_closer)(&a->archive, a->client_data);
|
(*a->client_closer)(&a->archive, a->client_data);
|
||||||
|
@ -360,7 +360,7 @@ static int la_mktemp(struct archive_write_disk *);
|
|||||||
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
static void fsobj_error(int *, struct archive_string *, int, const char *,
|
||||||
const char *);
|
const char *);
|
||||||
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
|
||||||
int);
|
int, int);
|
||||||
static int check_symlinks(struct archive_write_disk *);
|
static int check_symlinks(struct archive_write_disk *);
|
||||||
static int create_filesystem_object(struct archive_write_disk *);
|
static int create_filesystem_object(struct archive_write_disk *);
|
||||||
static struct fixup_entry *current_fixup(struct archive_write_disk *,
|
static struct fixup_entry *current_fixup(struct archive_write_disk *,
|
||||||
@ -2263,7 +2263,7 @@ create_filesystem_object(struct archive_write_disk *a)
|
|||||||
return (EPERM);
|
return (EPERM);
|
||||||
}
|
}
|
||||||
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
r = check_symlinks_fsobj(linkname_copy, &error_number,
|
||||||
&error_string, a->flags);
|
&error_string, a->flags, 1);
|
||||||
if (r != ARCHIVE_OK) {
|
if (r != ARCHIVE_OK) {
|
||||||
archive_set_error(&a->archive, error_number, "%s",
|
archive_set_error(&a->archive, error_number, "%s",
|
||||||
error_string.s);
|
error_string.s);
|
||||||
@ -2284,7 +2284,12 @@ create_filesystem_object(struct archive_write_disk *a)
|
|||||||
*/
|
*/
|
||||||
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
|
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
|
||||||
unlink(a->name);
|
unlink(a->name);
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
r = linkat(AT_FDCWD, linkname, AT_FDCWD, a->name,
|
||||||
|
0) ? errno : 0;
|
||||||
|
#else
|
||||||
r = link(linkname, a->name) ? errno : 0;
|
r = link(linkname, a->name) ? errno : 0;
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* New cpio and pax formats allow hardlink entries
|
* New cpio and pax formats allow hardlink entries
|
||||||
* to carry data, so we may have to open the file
|
* to carry data, so we may have to open the file
|
||||||
@ -2456,6 +2461,7 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
{
|
{
|
||||||
struct archive_write_disk *a = (struct archive_write_disk *)_a;
|
struct archive_write_disk *a = (struct archive_write_disk *)_a;
|
||||||
struct fixup_entry *next, *p;
|
struct fixup_entry *next, *p;
|
||||||
|
struct stat st;
|
||||||
int fd, ret;
|
int fd, ret;
|
||||||
|
|
||||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
|
archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
|
||||||
@ -2473,6 +2479,20 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
(TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
|
(TODO_TIMES | TODO_MODE_BASE | TODO_ACLS | TODO_FFLAGS)) {
|
||||||
fd = open(p->name,
|
fd = open(p->name,
|
||||||
O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
|
O_WRONLY | O_BINARY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
if (fd == -1) {
|
||||||
|
/* If we cannot lstat, skip entry */
|
||||||
|
if (lstat(p->name, &st) != 0)
|
||||||
|
goto skip_fixup_entry;
|
||||||
|
/*
|
||||||
|
* If we deal with a symbolic link, mark
|
||||||
|
* it in the fixup mode to ensure no
|
||||||
|
* modifications are made to its target.
|
||||||
|
*/
|
||||||
|
if (S_ISLNK(st.st_mode)) {
|
||||||
|
p->mode &= ~S_IFMT;
|
||||||
|
p->mode |= S_IFLNK;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p->fixup & TODO_TIMES) {
|
if (p->fixup & TODO_TIMES) {
|
||||||
set_times(a, fd, p->mode, p->name,
|
set_times(a, fd, p->mode, p->name,
|
||||||
@ -2487,7 +2507,12 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
fchmod(fd, p->mode);
|
fchmod(fd, p->mode);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_LCHMOD
|
||||||
|
lchmod(p->name, p->mode);
|
||||||
|
#else
|
||||||
|
if (!S_ISLNK(p->mode))
|
||||||
chmod(p->name, p->mode);
|
chmod(p->name, p->mode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (p->fixup & TODO_ACLS)
|
if (p->fixup & TODO_ACLS)
|
||||||
archive_write_disk_set_acls(&a->archive, fd,
|
archive_write_disk_set_acls(&a->archive, fd,
|
||||||
@ -2498,6 +2523,7 @@ _archive_write_disk_close(struct archive *_a)
|
|||||||
if (p->fixup & TODO_MAC_METADATA)
|
if (p->fixup & TODO_MAC_METADATA)
|
||||||
set_mac_metadata(a, p->name, p->mac_metadata,
|
set_mac_metadata(a, p->name, p->mac_metadata,
|
||||||
p->mac_metadata_size);
|
p->mac_metadata_size);
|
||||||
|
skip_fixup_entry:
|
||||||
next = p->next;
|
next = p->next;
|
||||||
archive_acl_clear(&p->acl);
|
archive_acl_clear(&p->acl);
|
||||||
free(p->mac_metadata);
|
free(p->mac_metadata);
|
||||||
@ -2638,6 +2664,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
|
|||||||
fe->next = a->fixup_list;
|
fe->next = a->fixup_list;
|
||||||
a->fixup_list = fe;
|
a->fixup_list = fe;
|
||||||
fe->fixup = 0;
|
fe->fixup = 0;
|
||||||
|
fe->mode = 0;
|
||||||
fe->name = strdup(pathname);
|
fe->name = strdup(pathname);
|
||||||
return (fe);
|
return (fe);
|
||||||
}
|
}
|
||||||
@ -2675,7 +2702,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
||||||
int flags)
|
int flags, int checking_linkname)
|
||||||
{
|
{
|
||||||
#if !defined(HAVE_LSTAT) && \
|
#if !defined(HAVE_LSTAT) && \
|
||||||
!(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
|
!(defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) && defined(HAVE_UNLINKAT))
|
||||||
@ -2684,6 +2711,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
|||||||
(void)error_number; /* UNUSED */
|
(void)error_number; /* UNUSED */
|
||||||
(void)error_string; /* UNUSED */
|
(void)error_string; /* UNUSED */
|
||||||
(void)flags; /* UNUSED */
|
(void)flags; /* UNUSED */
|
||||||
|
(void)checking_linkname; /* UNUSED */
|
||||||
return (ARCHIVE_OK);
|
return (ARCHIVE_OK);
|
||||||
#else
|
#else
|
||||||
int res = ARCHIVE_OK;
|
int res = ARCHIVE_OK;
|
||||||
@ -2805,6 +2833,28 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
|
|||||||
head = tail + 1;
|
head = tail + 1;
|
||||||
}
|
}
|
||||||
} else if (S_ISLNK(st.st_mode)) {
|
} else if (S_ISLNK(st.st_mode)) {
|
||||||
|
if (last && checking_linkname) {
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
/*
|
||||||
|
* Hardlinks to symlinks are safe to write
|
||||||
|
* if linkat() is supported as it does not
|
||||||
|
* follow symlinks.
|
||||||
|
*/
|
||||||
|
res = ARCHIVE_OK;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* We return ARCHIVE_FAILED here as we are
|
||||||
|
* not able to safely write hardlinks
|
||||||
|
* to symlinks.
|
||||||
|
*/
|
||||||
|
tail[0] = c;
|
||||||
|
fsobj_error(a_eno, a_estr, errno,
|
||||||
|
"Cannot write hardlink to symlink ",
|
||||||
|
path);
|
||||||
|
res = ARCHIVE_FAILED;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
} else
|
||||||
if (last) {
|
if (last) {
|
||||||
/*
|
/*
|
||||||
* Last element is symlink; remove it
|
* Last element is symlink; remove it
|
||||||
@ -2971,7 +3021,7 @@ check_symlinks(struct archive_write_disk *a)
|
|||||||
int rc;
|
int rc;
|
||||||
archive_string_init(&error_string);
|
archive_string_init(&error_string);
|
||||||
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
|
||||||
a->flags);
|
a->flags, 0);
|
||||||
if (rc != ARCHIVE_OK) {
|
if (rc != ARCHIVE_OK) {
|
||||||
archive_set_error(&a->archive, error_number, "%s",
|
archive_set_error(&a->archive, error_number, "%s",
|
||||||
error_string.s);
|
error_string.s);
|
||||||
@ -3899,7 +3949,8 @@ set_fflags_platform(struct archive_write_disk *a, int fd, const char *name,
|
|||||||
|
|
||||||
/* If we weren't given an fd, open it ourselves. */
|
/* If we weren't given an fd, open it ourselves. */
|
||||||
if (myfd < 0) {
|
if (myfd < 0) {
|
||||||
myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY | O_CLOEXEC);
|
myfd = open(name, O_RDONLY | O_NONBLOCK | O_BINARY |
|
||||||
|
O_CLOEXEC | O_NOFOLLOW);
|
||||||
__archive_ensure_cloexec_flag(myfd);
|
__archive_ensure_cloexec_flag(myfd);
|
||||||
}
|
}
|
||||||
if (myfd < 0)
|
if (myfd < 0)
|
||||||
|
@ -35,7 +35,10 @@
|
|||||||
.Nm archive_write_set_format_ar_svr4 ,
|
.Nm archive_write_set_format_ar_svr4 ,
|
||||||
.Nm archive_write_set_format_by_name ,
|
.Nm archive_write_set_format_by_name ,
|
||||||
.Nm archive_write_set_format_cpio ,
|
.Nm archive_write_set_format_cpio ,
|
||||||
|
.Nm archive_write_set_format_cpio_bin ,
|
||||||
.Nm archive_write_set_format_cpio_newc ,
|
.Nm archive_write_set_format_cpio_newc ,
|
||||||
|
.Nm archive_write_set_format_cpio_odc ,
|
||||||
|
.Nm archive_write_set_format_cpio_pwb ,
|
||||||
.Nm archive_write_set_format_filter_by_ext ,
|
.Nm archive_write_set_format_filter_by_ext ,
|
||||||
.Nm archive_write_set_format_filter_by_ext_def ,
|
.Nm archive_write_set_format_filter_by_ext_def ,
|
||||||
.Nm archive_write_set_format_gnutar ,
|
.Nm archive_write_set_format_gnutar ,
|
||||||
@ -73,8 +76,14 @@ Streaming Archive Library (libarchive, -larchive)
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn archive_write_set_format_cpio "struct archive *"
|
.Fn archive_write_set_format_cpio "struct archive *"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn archive_write_set_format_cpio_bin "struct archive *"
|
||||||
|
.Ft int
|
||||||
.Fn archive_write_set_format_cpio_newc "struct archive *"
|
.Fn archive_write_set_format_cpio_newc "struct archive *"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn archive_write_set_format_cpio_odc "struct archive *"
|
||||||
|
.Ft int
|
||||||
|
.Fn archive_write_set_format_cpio_pwb "struct archive *"
|
||||||
|
.Ft int
|
||||||
.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *filename"
|
.Fn archive_write_set_format_filter_by_ext "struct archive *" "const char *filename"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *filename" "const char *def_ext"
|
.Fn archive_write_set_format_filter_by_ext_def "struct archive *" "const char *filename" "const char *def_ext"
|
||||||
@ -119,17 +128,20 @@ to create a new archive with the same format as an existing archive.
|
|||||||
.It Fn archive_write_set_format_by_name
|
.It Fn archive_write_set_format_by_name
|
||||||
Sets the corresponding format based on the common name.
|
Sets the corresponding format based on the common name.
|
||||||
.It Xo
|
.It Xo
|
||||||
.Fn archive_write_set_format_filter_by_ext ,
|
.Fn archive_write_set_format_filter_by_ext
|
||||||
.Fn archive_write_set_format_filter_by_ext_def
|
.Fn archive_write_set_format_filter_by_ext_def
|
||||||
.Xc
|
.Xc
|
||||||
Sets both filters and format based on the output filename.
|
Sets both filters and format based on the output filename.
|
||||||
Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
|
Supported extensions: .7z, .zip, .jar, .cpio, .iso, .a, .ar, .tar, .tgz, .tar.gz, .tar.bz2, .tar.xz
|
||||||
.It Xo
|
.It Xo
|
||||||
.Fn archive_write_set_format_7zip
|
.Fn archive_write_set_format_7zip
|
||||||
.Fn archive_write_set_format_ar_bsd ,
|
.Fn archive_write_set_format_ar_bsd
|
||||||
.Fn archive_write_set_format_ar_svr4 ,
|
.Fn archive_write_set_format_ar_svr4
|
||||||
.Fn archive_write_set_format_cpio
|
.Fn archive_write_set_format_cpio
|
||||||
|
.Fn archive_write_set_format_cpio_bin
|
||||||
.Fn archive_write_set_format_cpio_newc
|
.Fn archive_write_set_format_cpio_newc
|
||||||
|
.Fn archive_write_set_format_cpio_odc
|
||||||
|
.Fn archive_write_set_format_cpio_pwb
|
||||||
.Fn archive_write_set_format_gnutar
|
.Fn archive_write_set_format_gnutar
|
||||||
.Fn archive_write_set_format_iso9660
|
.Fn archive_write_set_format_iso9660
|
||||||
.Fn archive_write_set_format_mtree
|
.Fn archive_write_set_format_mtree
|
||||||
|
@ -44,7 +44,9 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
|
|||||||
{
|
{
|
||||||
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
|
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
|
||||||
{ ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio },
|
{ ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio },
|
||||||
{ ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio },
|
{ ARCHIVE_FORMAT_CPIO_BIN_LE, archive_write_set_format_cpio_bin },
|
||||||
|
{ ARCHIVE_FORMAT_CPIO_PWB, archive_write_set_format_cpio_pwb },
|
||||||
|
{ ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio_odc },
|
||||||
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
|
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
|
||||||
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
|
{ ARCHIVE_FORMAT_ISO9660, archive_write_set_format_iso9660 },
|
||||||
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
|
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
|
||||||
|
@ -755,6 +755,10 @@ _7z_close(struct archive_write *a)
|
|||||||
*/
|
*/
|
||||||
#if HAVE_LZMA_H
|
#if HAVE_LZMA_H
|
||||||
header_compression = _7Z_LZMA1;
|
header_compression = _7Z_LZMA1;
|
||||||
|
if(zip->opt_compression == _7Z_LZMA2 ||
|
||||||
|
zip->opt_compression == _7Z_COPY)
|
||||||
|
header_compression = zip->opt_compression;
|
||||||
|
|
||||||
/* If the stored file is only one, do not encode the header.
|
/* If the stored file is only one, do not encode the header.
|
||||||
* This is the same way 7z command does. */
|
* This is the same way 7z command does. */
|
||||||
if (zip->total_number_entry == 1)
|
if (zip->total_number_entry == 1)
|
||||||
@ -762,7 +766,8 @@ _7z_close(struct archive_write *a)
|
|||||||
#else
|
#else
|
||||||
header_compression = _7Z_COPY;
|
header_compression = _7Z_COPY;
|
||||||
#endif
|
#endif
|
||||||
r = _7z_compression_init_encoder(a, header_compression, 6);
|
r = _7z_compression_init_encoder(a, header_compression,
|
||||||
|
zip->opt_compression_level);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return (r);
|
return (r);
|
||||||
zip->crc32flg = PRECODE_CRC32;
|
zip->crc32flg = PRECODE_CRC32;
|
||||||
|
@ -49,6 +49,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
|
|||||||
{ "arbsd", archive_write_set_format_ar_bsd },
|
{ "arbsd", archive_write_set_format_ar_bsd },
|
||||||
{ "argnu", archive_write_set_format_ar_svr4 },
|
{ "argnu", archive_write_set_format_ar_svr4 },
|
||||||
{ "arsvr4", archive_write_set_format_ar_svr4 },
|
{ "arsvr4", archive_write_set_format_ar_svr4 },
|
||||||
|
{ "bin", archive_write_set_format_cpio_bin },
|
||||||
{ "bsdtar", archive_write_set_format_pax_restricted },
|
{ "bsdtar", archive_write_set_format_pax_restricted },
|
||||||
{ "cd9660", archive_write_set_format_iso9660 },
|
{ "cd9660", archive_write_set_format_iso9660 },
|
||||||
{ "cpio", archive_write_set_format_cpio },
|
{ "cpio", archive_write_set_format_cpio },
|
||||||
@ -58,11 +59,12 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
|
|||||||
{ "mtree", archive_write_set_format_mtree },
|
{ "mtree", archive_write_set_format_mtree },
|
||||||
{ "mtree-classic", archive_write_set_format_mtree_classic },
|
{ "mtree-classic", archive_write_set_format_mtree_classic },
|
||||||
{ "newc", archive_write_set_format_cpio_newc },
|
{ "newc", archive_write_set_format_cpio_newc },
|
||||||
{ "odc", archive_write_set_format_cpio },
|
{ "odc", archive_write_set_format_cpio_odc },
|
||||||
{ "oldtar", archive_write_set_format_v7tar },
|
{ "oldtar", archive_write_set_format_v7tar },
|
||||||
{ "pax", archive_write_set_format_pax },
|
{ "pax", archive_write_set_format_pax },
|
||||||
{ "paxr", archive_write_set_format_pax_restricted },
|
{ "paxr", archive_write_set_format_pax_restricted },
|
||||||
{ "posix", archive_write_set_format_pax },
|
{ "posix", archive_write_set_format_pax },
|
||||||
|
{ "pwb", archive_write_set_format_cpio_pwb },
|
||||||
{ "raw", archive_write_set_format_raw },
|
{ "raw", archive_write_set_format_raw },
|
||||||
{ "rpax", archive_write_set_format_pax_restricted },
|
{ "rpax", archive_write_set_format_pax_restricted },
|
||||||
{ "shar", archive_write_set_format_shar },
|
{ "shar", archive_write_set_format_shar },
|
||||||
|
@ -1,500 +1,10 @@
|
|||||||
/*-
|
|
||||||
* Copyright (c) 2003-2007 Tim Kientzle
|
|
||||||
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
|
|
||||||
* 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_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifdef HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "archive.h"
|
#include "archive.h"
|
||||||
#include "archive_entry.h"
|
|
||||||
#include "archive_entry_locale.h"
|
|
||||||
#include "archive_private.h"
|
|
||||||
#include "archive_write_private.h"
|
|
||||||
#include "archive_write_set_format_private.h"
|
|
||||||
|
|
||||||
static ssize_t archive_write_cpio_data(struct archive_write *,
|
|
||||||
const void *buff, size_t s);
|
|
||||||
static int archive_write_cpio_close(struct archive_write *);
|
|
||||||
static int archive_write_cpio_free(struct archive_write *);
|
|
||||||
static int archive_write_cpio_finish_entry(struct archive_write *);
|
|
||||||
static int archive_write_cpio_header(struct archive_write *,
|
|
||||||
struct archive_entry *);
|
|
||||||
static int archive_write_cpio_options(struct archive_write *,
|
|
||||||
const char *, const char *);
|
|
||||||
static int format_octal(int64_t, void *, int);
|
|
||||||
static int64_t format_octal_recursive(int64_t, char *, int);
|
|
||||||
static int write_header(struct archive_write *, struct archive_entry *);
|
|
||||||
|
|
||||||
struct cpio {
|
|
||||||
uint64_t entry_bytes_remaining;
|
|
||||||
|
|
||||||
int64_t ino_next;
|
|
||||||
|
|
||||||
struct { int64_t old; int new;} *ino_list;
|
|
||||||
size_t ino_list_size;
|
|
||||||
size_t ino_list_next;
|
|
||||||
|
|
||||||
struct archive_string_conv *opt_sconv;
|
|
||||||
struct archive_string_conv *sconv_default;
|
|
||||||
int init_default_conversion;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define c_magic_offset 0
|
|
||||||
#define c_magic_size 6
|
|
||||||
#define c_dev_offset 6
|
|
||||||
#define c_dev_size 6
|
|
||||||
#define c_ino_offset 12
|
|
||||||
#define c_ino_size 6
|
|
||||||
#define c_mode_offset 18
|
|
||||||
#define c_mode_size 6
|
|
||||||
#define c_uid_offset 24
|
|
||||||
#define c_uid_size 6
|
|
||||||
#define c_gid_offset 30
|
|
||||||
#define c_gid_size 6
|
|
||||||
#define c_nlink_offset 36
|
|
||||||
#define c_nlink_size 6
|
|
||||||
#define c_rdev_offset 42
|
|
||||||
#define c_rdev_size 6
|
|
||||||
#define c_mtime_offset 48
|
|
||||||
#define c_mtime_size 11
|
|
||||||
#define c_namesize_offset 59
|
|
||||||
#define c_namesize_size 6
|
|
||||||
#define c_filesize_offset 65
|
|
||||||
#define c_filesize_size 11
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set output format to 'cpio' format.
|
* Set output format to the default 'cpio' format.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
archive_write_set_format_cpio(struct archive *_a)
|
archive_write_set_format_cpio(struct archive *_a)
|
||||||
{
|
{
|
||||||
struct archive_write *a = (struct archive_write *)_a;
|
return archive_write_set_format_cpio_odc(_a);
|
||||||
struct cpio *cpio;
|
|
||||||
|
|
||||||
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
|
||||||
ARCHIVE_STATE_NEW, "archive_write_set_format_cpio");
|
|
||||||
|
|
||||||
/* If someone else was already registered, unregister them. */
|
|
||||||
if (a->format_free != NULL)
|
|
||||||
(a->format_free)(a);
|
|
||||||
|
|
||||||
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
|
||||||
if (cpio == NULL) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
|
||||||
return (ARCHIVE_FATAL);
|
|
||||||
}
|
|
||||||
a->format_data = cpio;
|
|
||||||
a->format_name = "cpio";
|
|
||||||
a->format_options = archive_write_cpio_options;
|
|
||||||
a->format_write_header = archive_write_cpio_header;
|
|
||||||
a->format_write_data = archive_write_cpio_data;
|
|
||||||
a->format_finish_entry = archive_write_cpio_finish_entry;
|
|
||||||
a->format_close = archive_write_cpio_close;
|
|
||||||
a->format_free = archive_write_cpio_free;
|
|
||||||
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
|
|
||||||
a->archive.archive_format_name = "POSIX cpio";
|
|
||||||
return (ARCHIVE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_options(struct archive_write *a, const char *key,
|
|
||||||
const char *val)
|
|
||||||
{
|
|
||||||
struct cpio *cpio = (struct cpio *)a->format_data;
|
|
||||||
int ret = ARCHIVE_FAILED;
|
|
||||||
|
|
||||||
if (strcmp(key, "hdrcharset") == 0) {
|
|
||||||
if (val == NULL || val[0] == 0)
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
|
||||||
"%s: hdrcharset option needs a character-set name",
|
|
||||||
a->format_name);
|
|
||||||
else {
|
|
||||||
cpio->opt_sconv = archive_string_conversion_to_charset(
|
|
||||||
&a->archive, val, 0);
|
|
||||||
if (cpio->opt_sconv != NULL)
|
|
||||||
ret = ARCHIVE_OK;
|
|
||||||
else
|
|
||||||
ret = ARCHIVE_FATAL;
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: The "warn" return is just to inform the options
|
|
||||||
* supervisor that we didn't handle it. It will generate
|
|
||||||
* a suitable error if no one used this option. */
|
|
||||||
return (ARCHIVE_WARN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ino values are as long as 64 bits on some systems; cpio format
|
|
||||||
* only allows 18 bits and relies on the ino values to identify hardlinked
|
|
||||||
* files. So, we can't merely "hash" the ino numbers since collisions
|
|
||||||
* would corrupt the archive. Instead, we generate synthetic ino values
|
|
||||||
* to store in the archive and maintain a map of original ino values to
|
|
||||||
* synthetic ones so we can preserve hardlink information.
|
|
||||||
*
|
|
||||||
* TODO: Make this more efficient. It's not as bad as it looks (most
|
|
||||||
* files don't have any hardlinks and we don't do any work here for those),
|
|
||||||
* but it wouldn't be hard to do better.
|
|
||||||
*
|
|
||||||
* TODO: Work with dev/ino pairs here instead of just ino values.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
int64_t ino = archive_entry_ino64(entry);
|
|
||||||
int ino_new;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no index number was given, don't assign one. In
|
|
||||||
* particular, this handles the end-of-archive marker
|
|
||||||
* correctly by giving it a zero index value. (This is also
|
|
||||||
* why we start our synthetic index numbers with one below.)
|
|
||||||
*/
|
|
||||||
if (ino == 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
/* Don't store a mapping if we don't need to. */
|
|
||||||
if (archive_entry_nlink(entry) < 2) {
|
|
||||||
return (int)(++cpio->ino_next);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look up old ino; if we have it, this is a hardlink
|
|
||||||
* and we reuse the same value. */
|
|
||||||
for (i = 0; i < cpio->ino_list_next; ++i) {
|
|
||||||
if (cpio->ino_list[i].old == ino)
|
|
||||||
return (cpio->ino_list[i].new);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign a new index number. */
|
|
||||||
ino_new = (int)(++cpio->ino_next);
|
|
||||||
|
|
||||||
/* Ensure space for the new mapping. */
|
|
||||||
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
|
||||||
size_t newsize = cpio->ino_list_size < 512
|
|
||||||
? 512 : cpio->ino_list_size * 2;
|
|
||||||
void *newlist = realloc(cpio->ino_list,
|
|
||||||
sizeof(cpio->ino_list[0]) * newsize);
|
|
||||||
if (newlist == NULL)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
cpio->ino_list_size = newsize;
|
|
||||||
cpio->ino_list = newlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record and return the new value. */
|
|
||||||
cpio->ino_list[cpio->ino_list_next].old = ino;
|
|
||||||
cpio->ino_list[cpio->ino_list_next].new = ino_new;
|
|
||||||
++cpio->ino_list_next;
|
|
||||||
return (ino_new);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct archive_string_conv *
|
|
||||||
get_sconv(struct archive_write *a)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
struct archive_string_conv *sconv;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
sconv = cpio->opt_sconv;
|
|
||||||
if (sconv == NULL) {
|
|
||||||
if (!cpio->init_default_conversion) {
|
|
||||||
cpio->sconv_default =
|
|
||||||
archive_string_default_conversion_for_write(
|
|
||||||
&(a->archive));
|
|
||||||
cpio->init_default_conversion = 1;
|
|
||||||
}
|
|
||||||
sconv = cpio->sconv_default;
|
|
||||||
}
|
|
||||||
return (sconv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_header(struct archive_write *a, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
const char *path;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
|
|
||||||
archive_set_error(&a->archive, -1, "Filetype required");
|
|
||||||
return (ARCHIVE_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
|
|
||||||
&& errno == ENOMEM) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate memory for Pathname");
|
|
||||||
return (ARCHIVE_FATAL);
|
|
||||||
}
|
|
||||||
if (len == 0 || path == NULL || path[0] == '\0') {
|
|
||||||
archive_set_error(&a->archive, -1, "Pathname required");
|
|
||||||
return (ARCHIVE_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
|
|
||||||
archive_set_error(&a->archive, -1, "Size required");
|
|
||||||
return (ARCHIVE_FAILED);
|
|
||||||
}
|
|
||||||
return write_header(a, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
write_header(struct archive_write *a, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
const char *p, *path;
|
|
||||||
int pathlength, ret, ret_final;
|
|
||||||
int64_t ino;
|
|
||||||
char h[76];
|
|
||||||
struct archive_string_conv *sconv;
|
|
||||||
struct archive_entry *entry_main;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
ret_final = ARCHIVE_OK;
|
|
||||||
sconv = get_sconv(a);
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
||||||
/* Make sure the path separators in pathname, hardlink and symlink
|
|
||||||
* are all slash '/', not the Windows path separator '\'. */
|
|
||||||
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
|
||||||
if (entry_main == NULL) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate ustar data");
|
|
||||||
return(ARCHIVE_FATAL);
|
|
||||||
}
|
|
||||||
if (entry != entry_main)
|
|
||||||
entry = entry_main;
|
|
||||||
else
|
|
||||||
entry_main = NULL;
|
|
||||||
#else
|
|
||||||
entry_main = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
|
|
||||||
if (ret != 0) {
|
|
||||||
if (errno == ENOMEM) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate memory for Pathname");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
||||||
"Can't translate pathname '%s' to %s",
|
|
||||||
archive_entry_pathname(entry),
|
|
||||||
archive_string_conversion_charset_name(sconv));
|
|
||||||
ret_final = ARCHIVE_WARN;
|
|
||||||
}
|
|
||||||
/* Include trailing null. */
|
|
||||||
pathlength = (int)len + 1;
|
|
||||||
|
|
||||||
memset(h, 0, sizeof(h));
|
|
||||||
format_octal(070707, h + c_magic_offset, c_magic_size);
|
|
||||||
format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
|
|
||||||
|
|
||||||
ino = synthesize_ino_value(cpio, entry);
|
|
||||||
if (ino < 0) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"No memory for ino translation table");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
} else if (ino > 0777777) {
|
|
||||||
archive_set_error(&a->archive, ERANGE,
|
|
||||||
"Too many files for this cpio format");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
|
|
||||||
|
|
||||||
/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
|
|
||||||
format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
|
|
||||||
format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
|
|
||||||
format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
|
|
||||||
format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
|
|
||||||
if (archive_entry_filetype(entry) == AE_IFBLK
|
|
||||||
|| archive_entry_filetype(entry) == AE_IFCHR)
|
|
||||||
format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
|
|
||||||
else
|
|
||||||
format_octal(0, h + c_rdev_offset, c_rdev_size);
|
|
||||||
format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
|
|
||||||
format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
|
|
||||||
|
|
||||||
/* Non-regular files don't store bodies. */
|
|
||||||
if (archive_entry_filetype(entry) != AE_IFREG)
|
|
||||||
archive_entry_set_size(entry, 0);
|
|
||||||
|
|
||||||
/* Symlinks get the link written as the body of the entry. */
|
|
||||||
ret = archive_entry_symlink_l(entry, &p, &len, sconv);
|
|
||||||
if (ret != 0) {
|
|
||||||
if (errno == ENOMEM) {
|
|
||||||
archive_set_error(&a->archive, ENOMEM,
|
|
||||||
"Can't allocate memory for Linkname");
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
|
||||||
"Can't translate linkname '%s' to %s",
|
|
||||||
archive_entry_symlink(entry),
|
|
||||||
archive_string_conversion_charset_name(sconv));
|
|
||||||
ret_final = ARCHIVE_WARN;
|
|
||||||
}
|
|
||||||
if (len > 0 && p != NULL && *p != '\0')
|
|
||||||
ret = format_octal(strlen(p), h + c_filesize_offset,
|
|
||||||
c_filesize_size);
|
|
||||||
else
|
|
||||||
ret = format_octal(archive_entry_size(entry),
|
|
||||||
h + c_filesize_offset, c_filesize_size);
|
|
||||||
if (ret) {
|
|
||||||
archive_set_error(&a->archive, ERANGE,
|
|
||||||
"File is too large for cpio format.");
|
|
||||||
ret_final = ARCHIVE_FAILED;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = __archive_write_output(a, h, sizeof(h));
|
|
||||||
if (ret != ARCHIVE_OK) {
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = __archive_write_output(a, path, pathlength);
|
|
||||||
if (ret != ARCHIVE_OK) {
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpio->entry_bytes_remaining = archive_entry_size(entry);
|
|
||||||
|
|
||||||
/* Write the symlink now. */
|
|
||||||
if (p != NULL && *p != '\0') {
|
|
||||||
ret = __archive_write_output(a, p, strlen(p));
|
|
||||||
if (ret != ARCHIVE_OK) {
|
|
||||||
ret_final = ARCHIVE_FATAL;
|
|
||||||
goto exit_write_header;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exit_write_header:
|
|
||||||
archive_entry_free(entry_main);
|
|
||||||
return (ret_final);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
archive_write_cpio_data(struct archive_write *a, const void *buff, size_t s)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
if (s > cpio->entry_bytes_remaining)
|
|
||||||
s = (size_t)cpio->entry_bytes_remaining;
|
|
||||||
|
|
||||||
ret = __archive_write_output(a, buff, s);
|
|
||||||
cpio->entry_bytes_remaining -= s;
|
|
||||||
if (ret >= 0)
|
|
||||||
return (s);
|
|
||||||
else
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Format a number into the specified field.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
format_octal(int64_t v, void *p, int digits)
|
|
||||||
{
|
|
||||||
int64_t max;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
max = (((int64_t)1) << (digits * 3)) - 1;
|
|
||||||
if (v >= 0 && v <= max) {
|
|
||||||
format_octal_recursive(v, (char *)p, digits);
|
|
||||||
ret = 0;
|
|
||||||
} else {
|
|
||||||
format_octal_recursive(max, (char *)p, digits);
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int64_t
|
|
||||||
format_octal_recursive(int64_t v, char *p, int s)
|
|
||||||
{
|
|
||||||
if (s == 0)
|
|
||||||
return (v);
|
|
||||||
v = format_octal_recursive(v, p+1, s-1);
|
|
||||||
*p = '0' + ((char)v & 7);
|
|
||||||
return (v >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_close(struct archive_write *a)
|
|
||||||
{
|
|
||||||
int er;
|
|
||||||
struct archive_entry *trailer;
|
|
||||||
|
|
||||||
trailer = archive_entry_new2(NULL);
|
|
||||||
/* nlink = 1 here for GNU cpio compat. */
|
|
||||||
archive_entry_set_nlink(trailer, 1);
|
|
||||||
archive_entry_set_size(trailer, 0);
|
|
||||||
archive_entry_set_pathname(trailer, "TRAILER!!!");
|
|
||||||
er = write_header(a, trailer);
|
|
||||||
archive_entry_free(trailer);
|
|
||||||
return (er);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_free(struct archive_write *a)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
free(cpio->ino_list);
|
|
||||||
free(cpio);
|
|
||||||
a->format_data = NULL;
|
|
||||||
return (ARCHIVE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
archive_write_cpio_finish_entry(struct archive_write *a)
|
|
||||||
{
|
|
||||||
struct cpio *cpio;
|
|
||||||
|
|
||||||
cpio = (struct cpio *)a->format_data;
|
|
||||||
return (__archive_write_nulls(a,
|
|
||||||
(size_t)cpio->entry_bytes_remaining));
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,610 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003-2007 Tim Kientzle
|
||||||
|
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
|
||||||
|
* 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: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
|
||||||
|
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "archive.h"
|
||||||
|
#include "archive_entry.h"
|
||||||
|
#include "archive_entry_locale.h"
|
||||||
|
#include "archive_private.h"
|
||||||
|
#include "archive_write_private.h"
|
||||||
|
#include "archive_write_set_format_private.h"
|
||||||
|
|
||||||
|
static ssize_t archive_write_binary_data(struct archive_write *,
|
||||||
|
const void *buff, size_t s);
|
||||||
|
static int archive_write_binary_close(struct archive_write *);
|
||||||
|
static int archive_write_binary_free(struct archive_write *);
|
||||||
|
static int archive_write_binary_finish_entry(struct archive_write *);
|
||||||
|
static int archive_write_binary_header(struct archive_write *,
|
||||||
|
struct archive_entry *);
|
||||||
|
static int archive_write_binary_options(struct archive_write *,
|
||||||
|
const char *, const char *);
|
||||||
|
static int write_header(struct archive_write *, struct archive_entry *);
|
||||||
|
|
||||||
|
struct cpio {
|
||||||
|
uint64_t entry_bytes_remaining;
|
||||||
|
|
||||||
|
int64_t ino_next;
|
||||||
|
|
||||||
|
struct { int64_t old; int new;} *ino_list;
|
||||||
|
size_t ino_list_size;
|
||||||
|
size_t ino_list_next;
|
||||||
|
|
||||||
|
struct archive_string_conv *opt_sconv;
|
||||||
|
struct archive_string_conv *sconv_default;
|
||||||
|
int init_default_conversion;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This struct needs to be packed to get the header right */
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define PACKED(x) x __attribute__((packed))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||||
|
#else
|
||||||
|
#define PACKED(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HSIZE 26
|
||||||
|
|
||||||
|
PACKED(struct cpio_binary_header {
|
||||||
|
uint16_t h_magic;
|
||||||
|
uint16_t h_dev;
|
||||||
|
uint16_t h_ino;
|
||||||
|
uint16_t h_mode;
|
||||||
|
uint16_t h_uid;
|
||||||
|
uint16_t h_gid;
|
||||||
|
uint16_t h_nlink;
|
||||||
|
uint16_t h_majmin;
|
||||||
|
uint32_t h_mtime;
|
||||||
|
uint16_t h_namesize;
|
||||||
|
uint32_t h_filesize;
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Back in the day, the 7th Edition cpio.c had this, to
|
||||||
|
* adapt to, as the comment said, "VAX, Interdata, ...":
|
||||||
|
*
|
||||||
|
* union { long l; short s[2]; char c[4]; } U;
|
||||||
|
* #define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];}
|
||||||
|
* long mklong(v)
|
||||||
|
* short v[];
|
||||||
|
* {
|
||||||
|
* U.l = 1;
|
||||||
|
* if(U.c[0])
|
||||||
|
* U.s[0] = v[1], U.s[1] = v[0];
|
||||||
|
* else
|
||||||
|
* U.s[0] = v[0], U.s[1] = v[1];
|
||||||
|
* return U.l;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Of course, that assumes that all machines have little-endian shorts,
|
||||||
|
* and just adapts the others to the special endianness of the PDP-11.
|
||||||
|
*
|
||||||
|
* Now, we could do this:
|
||||||
|
*
|
||||||
|
* union { uint32_t l; uint16_t s[2]; uint8_t c[4]; } U;
|
||||||
|
* #define PUTI16(v,sv) {U.s[0]=1;if(U.c[0]) v=sv; else U.s[0]=sv,U.c[2]=U.c[1],U.c[3]=U.c[0],v=U.s[1];}
|
||||||
|
* #define PUTI32(v,lv) {char_t Ut;U.l=1;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,Ut=U.c[0],U.c[0]=U.c[1],U.c[1]=Ut,Ut=U.c[2],U.c[2]=U.c[3],U.c[3]=Ut,v[0]=U.s[0],v[1]=U.s[1];}
|
||||||
|
*
|
||||||
|
* ...but it feels a little better to do it like this:
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uint16_t swap16(uint16_t in) {
|
||||||
|
union {
|
||||||
|
uint16_t s[2];
|
||||||
|
uint8_t c[4];
|
||||||
|
} U;
|
||||||
|
U.s[0] = 1;
|
||||||
|
if (U.c[0])
|
||||||
|
return in;
|
||||||
|
else {
|
||||||
|
U.s[0] = in;
|
||||||
|
U.c[2] = U.c[1];
|
||||||
|
U.c[3] = U.c[0];
|
||||||
|
return U.s[1];
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t swap32(uint32_t in) {
|
||||||
|
union {
|
||||||
|
uint32_t l;
|
||||||
|
uint16_t s[2];
|
||||||
|
uint8_t c[4];
|
||||||
|
} U;
|
||||||
|
U.l = 1;
|
||||||
|
if (U.c[0]) { /* Little-endian */
|
||||||
|
uint16_t t;
|
||||||
|
U.l = in;
|
||||||
|
t = U.s[0];
|
||||||
|
U.s[0] = U.s[1];
|
||||||
|
U.s[1] = t;
|
||||||
|
} else if (U.c[3]) { /* Big-endian */
|
||||||
|
U.l = in;
|
||||||
|
U.s[0] = swap16(U.s[0]);
|
||||||
|
U.s[1] = swap16(U.s[1]);
|
||||||
|
} else { /* PDP-endian */
|
||||||
|
U.l = in;
|
||||||
|
}
|
||||||
|
return U.l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to the selected binary variant
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
archive_write_set_format_cpio_binary(struct archive *_a, int format)
|
||||||
|
{
|
||||||
|
struct archive_write *a = (struct archive_write *)_a;
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
if (sizeof(struct cpio_binary_header) != HSIZE) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"Binary cpio format not supported on this platform");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||||
|
ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_binary");
|
||||||
|
|
||||||
|
/* If someone else was already registered, unregister them. */
|
||||||
|
if (a->format_free != NULL)
|
||||||
|
(a->format_free)(a);
|
||||||
|
|
||||||
|
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
||||||
|
if (cpio == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
a->format_data = cpio;
|
||||||
|
a->format_name = "cpio";
|
||||||
|
a->format_options = archive_write_binary_options;
|
||||||
|
a->format_write_header = archive_write_binary_header;
|
||||||
|
a->format_write_data = archive_write_binary_data;
|
||||||
|
a->format_finish_entry = archive_write_binary_finish_entry;
|
||||||
|
a->format_close = archive_write_binary_close;
|
||||||
|
a->format_free = archive_write_binary_free;
|
||||||
|
a->archive.archive_format = format;
|
||||||
|
switch (format) {
|
||||||
|
case ARCHIVE_FORMAT_CPIO_PWB:
|
||||||
|
a->archive.archive_format_name = "PWB cpio";
|
||||||
|
break;
|
||||||
|
case ARCHIVE_FORMAT_CPIO_BIN_LE:
|
||||||
|
a->archive.archive_format_name = "7th Edition cpio";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
archive_set_error(&a->archive, EINVAL, "binary format must be 'pwb' or 'bin'");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to PWB (6th Edition) binary format
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
archive_write_set_format_cpio_pwb(struct archive *_a)
|
||||||
|
{
|
||||||
|
return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_PWB);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to 7th Edition binary format
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
archive_write_set_format_cpio_bin(struct archive *_a)
|
||||||
|
{
|
||||||
|
return archive_write_set_format_cpio_binary(_a, ARCHIVE_FORMAT_CPIO_BIN_LE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_options(struct archive_write *a, const char *key,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
struct cpio *cpio = (struct cpio *)a->format_data;
|
||||||
|
int ret = ARCHIVE_FAILED;
|
||||||
|
|
||||||
|
if (strcmp(key, "hdrcharset") == 0) {
|
||||||
|
if (val == NULL || val[0] == 0)
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||||
|
"%s: hdrcharset option needs a character-set name",
|
||||||
|
a->format_name);
|
||||||
|
else {
|
||||||
|
cpio->opt_sconv = archive_string_conversion_to_charset(
|
||||||
|
&a->archive, val, 0);
|
||||||
|
if (cpio->opt_sconv != NULL)
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
else
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: The "warn" return is just to inform the options
|
||||||
|
* supervisor that we didn't handle it. It will generate
|
||||||
|
* a suitable error if no one used this option. */
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ino values are as long as 64 bits on some systems; cpio format
|
||||||
|
* only allows 16 bits and relies on the ino values to identify hardlinked
|
||||||
|
* files. So, we can't merely "hash" the ino numbers since collisions
|
||||||
|
* would corrupt the archive. Instead, we generate synthetic ino values
|
||||||
|
* to store in the archive and maintain a map of original ino values to
|
||||||
|
* synthetic ones so we can preserve hardlink information.
|
||||||
|
*
|
||||||
|
* TODO: Make this more efficient. It's not as bad as it looks (most
|
||||||
|
* files don't have any hardlinks and we don't do any work here for those),
|
||||||
|
* but it wouldn't be hard to do better.
|
||||||
|
*
|
||||||
|
* TODO: Work with dev/ino pairs here instead of just ino values.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
int64_t ino = archive_entry_ino64(entry);
|
||||||
|
int ino_new;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no index number was given, don't assign one. In
|
||||||
|
* particular, this handles the end-of-archive marker
|
||||||
|
* correctly by giving it a zero index value. (This is also
|
||||||
|
* why we start our synthetic index numbers with one below.)
|
||||||
|
*/
|
||||||
|
if (ino == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Don't store a mapping if we don't need to. */
|
||||||
|
if (archive_entry_nlink(entry) < 2) {
|
||||||
|
return (int)(++cpio->ino_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up old ino; if we have it, this is a hardlink
|
||||||
|
* and we reuse the same value. */
|
||||||
|
for (i = 0; i < cpio->ino_list_next; ++i) {
|
||||||
|
if (cpio->ino_list[i].old == ino)
|
||||||
|
return (cpio->ino_list[i].new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign a new index number. */
|
||||||
|
ino_new = (int)(++cpio->ino_next);
|
||||||
|
|
||||||
|
/* Ensure space for the new mapping. */
|
||||||
|
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
||||||
|
size_t newsize = cpio->ino_list_size < 512
|
||||||
|
? 512 : cpio->ino_list_size * 2;
|
||||||
|
void *newlist = realloc(cpio->ino_list,
|
||||||
|
sizeof(cpio->ino_list[0]) * newsize);
|
||||||
|
if (newlist == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
cpio->ino_list_size = newsize;
|
||||||
|
cpio->ino_list = newlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record and return the new value. */
|
||||||
|
cpio->ino_list[cpio->ino_list_next].old = ino;
|
||||||
|
cpio->ino_list[cpio->ino_list_next].new = ino_new;
|
||||||
|
++cpio->ino_list_next;
|
||||||
|
return (ino_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct archive_string_conv *
|
||||||
|
get_sconv(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
sconv = cpio->opt_sconv;
|
||||||
|
if (sconv == NULL) {
|
||||||
|
if (!cpio->init_default_conversion) {
|
||||||
|
cpio->sconv_default =
|
||||||
|
archive_string_default_conversion_for_write(
|
||||||
|
&(a->archive));
|
||||||
|
cpio->init_default_conversion = 1;
|
||||||
|
}
|
||||||
|
sconv = cpio->sconv_default;
|
||||||
|
}
|
||||||
|
return (sconv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
|
||||||
|
archive_set_error(&a->archive, -1, "Filetype required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
|
||||||
|
&& errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (len == 0 || path == NULL || path[0] == '\0') {
|
||||||
|
archive_set_error(&a->archive, -1, "Pathname required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
|
||||||
|
archive_set_error(&a->archive, -1, "Size required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
return write_header(a, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
const char *p, *path;
|
||||||
|
int pathlength, ret, ret_final;
|
||||||
|
int64_t ino;
|
||||||
|
struct cpio_binary_header h;
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
struct archive_entry *entry_main;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
ret_final = ARCHIVE_OK;
|
||||||
|
sconv = get_sconv(a);
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
/* Make sure the path separators in pathname, hardlink and symlink
|
||||||
|
* are all slash '/', not the Windows path separator '\'. */
|
||||||
|
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||||
|
if (entry_main == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate ustar data");
|
||||||
|
return(ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (entry != entry_main)
|
||||||
|
entry = entry_main;
|
||||||
|
else
|
||||||
|
entry_main = NULL;
|
||||||
|
#else
|
||||||
|
entry_main = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate pathname '%s' to %s",
|
||||||
|
archive_entry_pathname(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
/* Include trailing null */
|
||||||
|
pathlength = (int)len + 1;
|
||||||
|
|
||||||
|
h.h_magic = swap16(070707);
|
||||||
|
h.h_dev = swap16(archive_entry_dev(entry));
|
||||||
|
|
||||||
|
ino = synthesize_ino_value(cpio, entry);
|
||||||
|
if (ino < 0) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"No memory for ino translation table");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
} else if (ino > 077777) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"Too many files for this cpio format");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
h.h_ino = swap16(ino);
|
||||||
|
|
||||||
|
h.h_mode = archive_entry_mode(entry);
|
||||||
|
if (((h.h_mode & AE_IFMT) == AE_IFSOCK) || ((h.h_mode & AE_IFMT) == AE_IFIFO)) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"sockets and fifos cannot be represented in the binary cpio formats");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
|
||||||
|
if ((h.h_mode & AE_IFMT) == AE_IFLNK) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"symbolic links cannot be represented in the PWB cpio format");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
/* we could turn off AE_IFREG here, but it does no harm, */
|
||||||
|
/* and allows v7 cpio to read the entry without confusion */
|
||||||
|
}
|
||||||
|
h.h_mode = swap16(h.h_mode);
|
||||||
|
|
||||||
|
h.h_uid = swap16(archive_entry_uid(entry));
|
||||||
|
h.h_gid = swap16(archive_entry_gid(entry));
|
||||||
|
h.h_nlink = swap16(archive_entry_nlink(entry));
|
||||||
|
|
||||||
|
if (archive_entry_filetype(entry) == AE_IFBLK
|
||||||
|
|| archive_entry_filetype(entry) == AE_IFCHR)
|
||||||
|
h.h_majmin = swap16(archive_entry_rdev(entry));
|
||||||
|
else
|
||||||
|
h.h_majmin = 0;
|
||||||
|
|
||||||
|
h.h_mtime = swap32(archive_entry_mtime(entry));
|
||||||
|
h.h_namesize = swap16(pathlength);
|
||||||
|
|
||||||
|
/* Non-regular files don't store bodies. */
|
||||||
|
if (archive_entry_filetype(entry) != AE_IFREG)
|
||||||
|
archive_entry_set_size(entry, 0);
|
||||||
|
|
||||||
|
/* Symlinks get the link written as the body of the entry. */
|
||||||
|
ret = archive_entry_symlink_l(entry, &p, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Linkname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate linkname '%s' to %s",
|
||||||
|
archive_entry_symlink(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 0 && p != NULL && *p != '\0') {
|
||||||
|
if (a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) {
|
||||||
|
archive_set_error(&a->archive, EINVAL,
|
||||||
|
"symlinks are not supported by UNIX V6 or by PWB cpio");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
h.h_filesize = swap32(strlen(p)); /* symlink */
|
||||||
|
} else {
|
||||||
|
if ((a->archive.archive_format == ARCHIVE_FORMAT_CPIO_PWB) &&
|
||||||
|
(archive_entry_size(entry) > 256*256*256-1)) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"File is too large for PWB binary cpio format.");
|
||||||
|
ret_final = ARCHIVE_FAILED;
|
||||||
|
goto exit_write_header;
|
||||||
|
} else if (archive_entry_size(entry) > INT32_MAX) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"File is too large for binary cpio format.");
|
||||||
|
ret_final = ARCHIVE_FAILED;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
h.h_filesize = swap32(archive_entry_size(entry)); /* file */
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, &h, HSIZE);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, path, pathlength);
|
||||||
|
if ((ret == ARCHIVE_OK) && ((pathlength % 2) != 0))
|
||||||
|
ret = __archive_write_nulls(a, 1);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpio->entry_bytes_remaining = archive_entry_size(entry);
|
||||||
|
if ((cpio->entry_bytes_remaining % 2) != 0)
|
||||||
|
cpio->entry_bytes_remaining++;
|
||||||
|
|
||||||
|
/* Write the symlink now. */
|
||||||
|
if (p != NULL && *p != '\0') {
|
||||||
|
ret = __archive_write_output(a, p, strlen(p));
|
||||||
|
if ((ret == ARCHIVE_OK) && ((strlen(p) % 2) != 0))
|
||||||
|
ret = __archive_write_nulls(a, 1);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_write_header:
|
||||||
|
archive_entry_free(entry_main);
|
||||||
|
return (ret_final);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
archive_write_binary_data(struct archive_write *a, const void *buff, size_t s)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
if (s > cpio->entry_bytes_remaining)
|
||||||
|
s = (size_t)cpio->entry_bytes_remaining;
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, buff, s);
|
||||||
|
cpio->entry_bytes_remaining -= s;
|
||||||
|
if (ret >= 0)
|
||||||
|
return (s);
|
||||||
|
else
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_close(struct archive_write *a)
|
||||||
|
{
|
||||||
|
int er;
|
||||||
|
struct archive_entry *trailer;
|
||||||
|
|
||||||
|
trailer = archive_entry_new2(NULL);
|
||||||
|
/* nlink = 1 here for GNU cpio compat. */
|
||||||
|
archive_entry_set_nlink(trailer, 1);
|
||||||
|
archive_entry_set_size(trailer, 0);
|
||||||
|
archive_entry_set_pathname(trailer, "TRAILER!!!");
|
||||||
|
er = write_header(a, trailer);
|
||||||
|
archive_entry_free(trailer);
|
||||||
|
return (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_free(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
free(cpio->ino_list);
|
||||||
|
free(cpio);
|
||||||
|
a->format_data = NULL;
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_binary_finish_entry(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
return (__archive_write_nulls(a,
|
||||||
|
(size_t)cpio->entry_bytes_remaining));
|
||||||
|
}
|
@ -0,0 +1,500 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003-2007 Tim Kientzle
|
||||||
|
* Copyright (c) 2011-2012 Michihiro NAKAJIMA
|
||||||
|
* 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: head/lib/libarchive/archive_write_set_format_cpio.c 201170 2009-12-29 06:34:23Z kientzle $");
|
||||||
|
|
||||||
|
#ifdef HAVE_ERRNO_H
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "archive.h"
|
||||||
|
#include "archive_entry.h"
|
||||||
|
#include "archive_entry_locale.h"
|
||||||
|
#include "archive_private.h"
|
||||||
|
#include "archive_write_private.h"
|
||||||
|
#include "archive_write_set_format_private.h"
|
||||||
|
|
||||||
|
static ssize_t archive_write_odc_data(struct archive_write *,
|
||||||
|
const void *buff, size_t s);
|
||||||
|
static int archive_write_odc_close(struct archive_write *);
|
||||||
|
static int archive_write_odc_free(struct archive_write *);
|
||||||
|
static int archive_write_odc_finish_entry(struct archive_write *);
|
||||||
|
static int archive_write_odc_header(struct archive_write *,
|
||||||
|
struct archive_entry *);
|
||||||
|
static int archive_write_odc_options(struct archive_write *,
|
||||||
|
const char *, const char *);
|
||||||
|
static int format_octal(int64_t, void *, int);
|
||||||
|
static int64_t format_octal_recursive(int64_t, char *, int);
|
||||||
|
static int write_header(struct archive_write *, struct archive_entry *);
|
||||||
|
|
||||||
|
struct cpio {
|
||||||
|
uint64_t entry_bytes_remaining;
|
||||||
|
|
||||||
|
int64_t ino_next;
|
||||||
|
|
||||||
|
struct { int64_t old; int new;} *ino_list;
|
||||||
|
size_t ino_list_size;
|
||||||
|
size_t ino_list_next;
|
||||||
|
|
||||||
|
struct archive_string_conv *opt_sconv;
|
||||||
|
struct archive_string_conv *sconv_default;
|
||||||
|
int init_default_conversion;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define c_magic_offset 0
|
||||||
|
#define c_magic_size 6
|
||||||
|
#define c_dev_offset 6
|
||||||
|
#define c_dev_size 6
|
||||||
|
#define c_ino_offset 12
|
||||||
|
#define c_ino_size 6
|
||||||
|
#define c_mode_offset 18
|
||||||
|
#define c_mode_size 6
|
||||||
|
#define c_uid_offset 24
|
||||||
|
#define c_uid_size 6
|
||||||
|
#define c_gid_offset 30
|
||||||
|
#define c_gid_size 6
|
||||||
|
#define c_nlink_offset 36
|
||||||
|
#define c_nlink_size 6
|
||||||
|
#define c_rdev_offset 42
|
||||||
|
#define c_rdev_size 6
|
||||||
|
#define c_mtime_offset 48
|
||||||
|
#define c_mtime_size 11
|
||||||
|
#define c_namesize_offset 59
|
||||||
|
#define c_namesize_size 6
|
||||||
|
#define c_filesize_offset 65
|
||||||
|
#define c_filesize_size 11
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set output format to 'cpio' format.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
archive_write_set_format_cpio_odc(struct archive *_a)
|
||||||
|
{
|
||||||
|
struct archive_write *a = (struct archive_write *)_a;
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
|
||||||
|
ARCHIVE_STATE_NEW, "archive_write_set_format_cpio_odc");
|
||||||
|
|
||||||
|
/* If someone else was already registered, unregister them. */
|
||||||
|
if (a->format_free != NULL)
|
||||||
|
(a->format_free)(a);
|
||||||
|
|
||||||
|
cpio = (struct cpio *)calloc(1, sizeof(*cpio));
|
||||||
|
if (cpio == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM, "Can't allocate cpio data");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
a->format_data = cpio;
|
||||||
|
a->format_name = "cpio";
|
||||||
|
a->format_options = archive_write_odc_options;
|
||||||
|
a->format_write_header = archive_write_odc_header;
|
||||||
|
a->format_write_data = archive_write_odc_data;
|
||||||
|
a->format_finish_entry = archive_write_odc_finish_entry;
|
||||||
|
a->format_close = archive_write_odc_close;
|
||||||
|
a->format_free = archive_write_odc_free;
|
||||||
|
a->archive.archive_format = ARCHIVE_FORMAT_CPIO_POSIX;
|
||||||
|
a->archive.archive_format_name = "POSIX cpio";
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_options(struct archive_write *a, const char *key,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
struct cpio *cpio = (struct cpio *)a->format_data;
|
||||||
|
int ret = ARCHIVE_FAILED;
|
||||||
|
|
||||||
|
if (strcmp(key, "hdrcharset") == 0) {
|
||||||
|
if (val == NULL || val[0] == 0)
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||||
|
"%s: hdrcharset option needs a character-set name",
|
||||||
|
a->format_name);
|
||||||
|
else {
|
||||||
|
cpio->opt_sconv = archive_string_conversion_to_charset(
|
||||||
|
&a->archive, val, 0);
|
||||||
|
if (cpio->opt_sconv != NULL)
|
||||||
|
ret = ARCHIVE_OK;
|
||||||
|
else
|
||||||
|
ret = ARCHIVE_FATAL;
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: The "warn" return is just to inform the options
|
||||||
|
* supervisor that we didn't handle it. It will generate
|
||||||
|
* a suitable error if no one used this option. */
|
||||||
|
return (ARCHIVE_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ino values are as long as 64 bits on some systems; cpio format
|
||||||
|
* only allows 18 bits and relies on the ino values to identify hardlinked
|
||||||
|
* files. So, we can't merely "hash" the ino numbers since collisions
|
||||||
|
* would corrupt the archive. Instead, we generate synthetic ino values
|
||||||
|
* to store in the archive and maintain a map of original ino values to
|
||||||
|
* synthetic ones so we can preserve hardlink information.
|
||||||
|
*
|
||||||
|
* TODO: Make this more efficient. It's not as bad as it looks (most
|
||||||
|
* files don't have any hardlinks and we don't do any work here for those),
|
||||||
|
* but it wouldn't be hard to do better.
|
||||||
|
*
|
||||||
|
* TODO: Work with dev/ino pairs here instead of just ino values.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
synthesize_ino_value(struct cpio *cpio, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
int64_t ino = archive_entry_ino64(entry);
|
||||||
|
int ino_new;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no index number was given, don't assign one. In
|
||||||
|
* particular, this handles the end-of-archive marker
|
||||||
|
* correctly by giving it a zero index value. (This is also
|
||||||
|
* why we start our synthetic index numbers with one below.)
|
||||||
|
*/
|
||||||
|
if (ino == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
/* Don't store a mapping if we don't need to. */
|
||||||
|
if (archive_entry_nlink(entry) < 2) {
|
||||||
|
return (int)(++cpio->ino_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up old ino; if we have it, this is a hardlink
|
||||||
|
* and we reuse the same value. */
|
||||||
|
for (i = 0; i < cpio->ino_list_next; ++i) {
|
||||||
|
if (cpio->ino_list[i].old == ino)
|
||||||
|
return (cpio->ino_list[i].new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assign a new index number. */
|
||||||
|
ino_new = (int)(++cpio->ino_next);
|
||||||
|
|
||||||
|
/* Ensure space for the new mapping. */
|
||||||
|
if (cpio->ino_list_size <= cpio->ino_list_next) {
|
||||||
|
size_t newsize = cpio->ino_list_size < 512
|
||||||
|
? 512 : cpio->ino_list_size * 2;
|
||||||
|
void *newlist = realloc(cpio->ino_list,
|
||||||
|
sizeof(cpio->ino_list[0]) * newsize);
|
||||||
|
if (newlist == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
cpio->ino_list_size = newsize;
|
||||||
|
cpio->ino_list = newlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record and return the new value. */
|
||||||
|
cpio->ino_list[cpio->ino_list_next].old = ino;
|
||||||
|
cpio->ino_list[cpio->ino_list_next].new = ino_new;
|
||||||
|
++cpio->ino_list_next;
|
||||||
|
return (ino_new);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct archive_string_conv *
|
||||||
|
get_sconv(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
sconv = cpio->opt_sconv;
|
||||||
|
if (sconv == NULL) {
|
||||||
|
if (!cpio->init_default_conversion) {
|
||||||
|
cpio->sconv_default =
|
||||||
|
archive_string_default_conversion_for_write(
|
||||||
|
&(a->archive));
|
||||||
|
cpio->init_default_conversion = 1;
|
||||||
|
}
|
||||||
|
sconv = cpio->sconv_default;
|
||||||
|
}
|
||||||
|
return (sconv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
const char *path;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (archive_entry_filetype(entry) == 0 && archive_entry_hardlink(entry) == NULL) {
|
||||||
|
archive_set_error(&a->archive, -1, "Filetype required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (archive_entry_pathname_l(entry, &path, &len, get_sconv(a)) != 0
|
||||||
|
&& errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
return (ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (len == 0 || path == NULL || path[0] == '\0') {
|
||||||
|
archive_set_error(&a->archive, -1, "Pathname required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0) {
|
||||||
|
archive_set_error(&a->archive, -1, "Size required");
|
||||||
|
return (ARCHIVE_FAILED);
|
||||||
|
}
|
||||||
|
return write_header(a, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
write_header(struct archive_write *a, struct archive_entry *entry)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
const char *p, *path;
|
||||||
|
int pathlength, ret, ret_final;
|
||||||
|
int64_t ino;
|
||||||
|
char h[76];
|
||||||
|
struct archive_string_conv *sconv;
|
||||||
|
struct archive_entry *entry_main;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
ret_final = ARCHIVE_OK;
|
||||||
|
sconv = get_sconv(a);
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
/* Make sure the path separators in pathname, hardlink and symlink
|
||||||
|
* are all slash '/', not the Windows path separator '\'. */
|
||||||
|
entry_main = __la_win_entry_in_posix_pathseparator(entry);
|
||||||
|
if (entry_main == NULL) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate ustar data");
|
||||||
|
return(ARCHIVE_FATAL);
|
||||||
|
}
|
||||||
|
if (entry != entry_main)
|
||||||
|
entry = entry_main;
|
||||||
|
else
|
||||||
|
entry_main = NULL;
|
||||||
|
#else
|
||||||
|
entry_main = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = archive_entry_pathname_l(entry, &path, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Pathname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate pathname '%s' to %s",
|
||||||
|
archive_entry_pathname(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
/* Include trailing null. */
|
||||||
|
pathlength = (int)len + 1;
|
||||||
|
|
||||||
|
memset(h, 0, sizeof(h));
|
||||||
|
format_octal(070707, h + c_magic_offset, c_magic_size);
|
||||||
|
format_octal(archive_entry_dev(entry), h + c_dev_offset, c_dev_size);
|
||||||
|
|
||||||
|
ino = synthesize_ino_value(cpio, entry);
|
||||||
|
if (ino < 0) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"No memory for ino translation table");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
} else if (ino > 0777777) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"Too many files for this cpio format");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
format_octal(ino & 0777777, h + c_ino_offset, c_ino_size);
|
||||||
|
|
||||||
|
/* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */
|
||||||
|
format_octal(archive_entry_mode(entry), h + c_mode_offset, c_mode_size);
|
||||||
|
format_octal(archive_entry_uid(entry), h + c_uid_offset, c_uid_size);
|
||||||
|
format_octal(archive_entry_gid(entry), h + c_gid_offset, c_gid_size);
|
||||||
|
format_octal(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size);
|
||||||
|
if (archive_entry_filetype(entry) == AE_IFBLK
|
||||||
|
|| archive_entry_filetype(entry) == AE_IFCHR)
|
||||||
|
format_octal(archive_entry_rdev(entry), h + c_rdev_offset, c_rdev_size);
|
||||||
|
else
|
||||||
|
format_octal(0, h + c_rdev_offset, c_rdev_size);
|
||||||
|
format_octal(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size);
|
||||||
|
format_octal(pathlength, h + c_namesize_offset, c_namesize_size);
|
||||||
|
|
||||||
|
/* Non-regular files don't store bodies. */
|
||||||
|
if (archive_entry_filetype(entry) != AE_IFREG)
|
||||||
|
archive_entry_set_size(entry, 0);
|
||||||
|
|
||||||
|
/* Symlinks get the link written as the body of the entry. */
|
||||||
|
ret = archive_entry_symlink_l(entry, &p, &len, sconv);
|
||||||
|
if (ret != 0) {
|
||||||
|
if (errno == ENOMEM) {
|
||||||
|
archive_set_error(&a->archive, ENOMEM,
|
||||||
|
"Can't allocate memory for Linkname");
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||||
|
"Can't translate linkname '%s' to %s",
|
||||||
|
archive_entry_symlink(entry),
|
||||||
|
archive_string_conversion_charset_name(sconv));
|
||||||
|
ret_final = ARCHIVE_WARN;
|
||||||
|
}
|
||||||
|
if (len > 0 && p != NULL && *p != '\0')
|
||||||
|
ret = format_octal(strlen(p), h + c_filesize_offset,
|
||||||
|
c_filesize_size);
|
||||||
|
else
|
||||||
|
ret = format_octal(archive_entry_size(entry),
|
||||||
|
h + c_filesize_offset, c_filesize_size);
|
||||||
|
if (ret) {
|
||||||
|
archive_set_error(&a->archive, ERANGE,
|
||||||
|
"File is too large for cpio format.");
|
||||||
|
ret_final = ARCHIVE_FAILED;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, h, sizeof(h));
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, path, pathlength);
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpio->entry_bytes_remaining = archive_entry_size(entry);
|
||||||
|
|
||||||
|
/* Write the symlink now. */
|
||||||
|
if (p != NULL && *p != '\0') {
|
||||||
|
ret = __archive_write_output(a, p, strlen(p));
|
||||||
|
if (ret != ARCHIVE_OK) {
|
||||||
|
ret_final = ARCHIVE_FATAL;
|
||||||
|
goto exit_write_header;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit_write_header:
|
||||||
|
archive_entry_free(entry_main);
|
||||||
|
return (ret_final);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
archive_write_odc_data(struct archive_write *a, const void *buff, size_t s)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
if (s > cpio->entry_bytes_remaining)
|
||||||
|
s = (size_t)cpio->entry_bytes_remaining;
|
||||||
|
|
||||||
|
ret = __archive_write_output(a, buff, s);
|
||||||
|
cpio->entry_bytes_remaining -= s;
|
||||||
|
if (ret >= 0)
|
||||||
|
return (s);
|
||||||
|
else
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a number into the specified field.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
format_octal(int64_t v, void *p, int digits)
|
||||||
|
{
|
||||||
|
int64_t max;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
max = (((int64_t)1) << (digits * 3)) - 1;
|
||||||
|
if (v >= 0 && v <= max) {
|
||||||
|
format_octal_recursive(v, (char *)p, digits);
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
format_octal_recursive(max, (char *)p, digits);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
format_octal_recursive(int64_t v, char *p, int s)
|
||||||
|
{
|
||||||
|
if (s == 0)
|
||||||
|
return (v);
|
||||||
|
v = format_octal_recursive(v, p+1, s-1);
|
||||||
|
*p = '0' + ((char)v & 7);
|
||||||
|
return (v >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_close(struct archive_write *a)
|
||||||
|
{
|
||||||
|
int er;
|
||||||
|
struct archive_entry *trailer;
|
||||||
|
|
||||||
|
trailer = archive_entry_new2(NULL);
|
||||||
|
/* nlink = 1 here for GNU cpio compat. */
|
||||||
|
archive_entry_set_nlink(trailer, 1);
|
||||||
|
archive_entry_set_size(trailer, 0);
|
||||||
|
archive_entry_set_pathname(trailer, "TRAILER!!!");
|
||||||
|
er = write_header(a, trailer);
|
||||||
|
archive_entry_free(trailer);
|
||||||
|
return (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_free(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
free(cpio->ino_list);
|
||||||
|
free(cpio);
|
||||||
|
a->format_data = NULL;
|
||||||
|
return (ARCHIVE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
archive_write_odc_finish_entry(struct archive_write *a)
|
||||||
|
{
|
||||||
|
struct cpio *cpio;
|
||||||
|
|
||||||
|
cpio = (struct cpio *)a->format_data;
|
||||||
|
return (__archive_write_nulls(a,
|
||||||
|
(size_t)cpio->entry_bytes_remaining));
|
||||||
|
}
|
@ -25,7 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "archive_platform.h"
|
#include "archive_platform.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_by_name.c 201168 2009-12-29 06:15:32Z kientzle $");
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -279,7 +279,7 @@ Values between 0 and 9 are supported.
|
|||||||
The interpretation of the compression level depends on the chosen
|
The interpretation of the compression level depends on the chosen
|
||||||
compression method.
|
compression method.
|
||||||
.El
|
.El
|
||||||
.It Format cpio
|
.It Format bin
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
.It Cm hdrcharset
|
.It Cm hdrcharset
|
||||||
The value is used as a character set name that will be
|
The value is used as a character set name that will be
|
||||||
@ -519,6 +519,18 @@ XXX needs explanation XXX
|
|||||||
The value is used as a character set name that will be
|
The value is used as a character set name that will be
|
||||||
used when translating file names.
|
used when translating file names.
|
||||||
.El
|
.El
|
||||||
|
.It Format odc
|
||||||
|
.Bl -tag -compact -width indent
|
||||||
|
.It Cm hdrcharset
|
||||||
|
The value is used as a character set name that will be
|
||||||
|
used when translating file names.
|
||||||
|
.El
|
||||||
|
.It Format pwb
|
||||||
|
.Bl -tag -compact -width indent
|
||||||
|
.It Cm hdrcharset
|
||||||
|
The value is used as a character set name that will be
|
||||||
|
used when translating file names.
|
||||||
|
.El
|
||||||
.It Format pax
|
.It Format pax
|
||||||
.Bl -tag -compact -width indent
|
.Bl -tag -compact -width indent
|
||||||
.It Cm hdrcharset
|
.It Cm hdrcharset
|
||||||
|
@ -56,40 +56,44 @@ The end of the archive is indicated by a special record with
|
|||||||
the pathname
|
the pathname
|
||||||
.Dq TRAILER!!! .
|
.Dq TRAILER!!! .
|
||||||
.Ss PWB format
|
.Ss PWB format
|
||||||
XXX Any documentation of the original PWB/UNIX 1.0 format? XXX
|
The PWB binary
|
||||||
.Ss Old Binary Format
|
|
||||||
The old binary
|
|
||||||
.Nm
|
.Nm
|
||||||
format stores numbers as 2-byte and 4-byte binary values.
|
format is the original format, when cpio was introduced as part of the
|
||||||
|
Programmer's Work Bench system, a variant of 6th Edition UNIX. It
|
||||||
|
stores numbers as 2-byte and 4-byte binary values.
|
||||||
Each entry begins with a header in the following format:
|
Each entry begins with a header in the following format:
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct header_old_cpio {
|
struct header_pwb_cpio {
|
||||||
unsigned short c_magic;
|
short h_magic;
|
||||||
unsigned short c_dev;
|
short h_dev;
|
||||||
unsigned short c_ino;
|
short h_ino;
|
||||||
unsigned short c_mode;
|
short h_mode;
|
||||||
unsigned short c_uid;
|
short h_uid;
|
||||||
unsigned short c_gid;
|
short h_gid;
|
||||||
unsigned short c_nlink;
|
short h_nlink;
|
||||||
unsigned short c_rdev;
|
short h_majmin;
|
||||||
unsigned short c_mtime[2];
|
long h_mtime;
|
||||||
unsigned short c_namesize;
|
short h_namesize;
|
||||||
unsigned short c_filesize[2];
|
long h_filesize;
|
||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Va unsigned short
|
.Va short
|
||||||
fields here are 16-bit integer values; the
|
fields here are 16-bit integer values, while the
|
||||||
.Va unsigned int
|
.Va long
|
||||||
fields are 32-bit integer values.
|
fields are 32 bit integers. Since PWB UNIX, like the 6th Edition UNIX
|
||||||
The fields are as follows
|
it was based on, only ran on PDP-11 computers, they
|
||||||
|
are in PDP-endian format, which has little-endian shorts, and
|
||||||
|
big-endian longs. That is, the long integer whose hexadecimal
|
||||||
|
representation is 0x12345678 would be stored in four successive bytes
|
||||||
|
as 0x34, 0x12, 0x78, 0x56.
|
||||||
|
The fields are as follows:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Va magic
|
.It Va h_magic
|
||||||
The integer value octal 070707.
|
The integer value octal 070707.
|
||||||
This value can be used to determine whether this archive is
|
.It Va h_dev , Va h_ino
|
||||||
written with little-endian or big-endian integers.
|
|
||||||
.It Va dev , Va ino
|
|
||||||
The device and inode numbers from the disk.
|
The device and inode numbers from the disk.
|
||||||
These are used by programs that read
|
These are used by programs that read
|
||||||
.Nm
|
.Nm
|
||||||
@ -97,9 +101,94 @@ archives to determine when two entries refer to the same file.
|
|||||||
Programs that synthesize
|
Programs that synthesize
|
||||||
.Nm
|
.Nm
|
||||||
archives should be careful to set these to distinct values for each entry.
|
archives should be careful to set these to distinct values for each entry.
|
||||||
.It Va mode
|
.It Va h_mode
|
||||||
The mode specifies both the regular permissions and the file type.
|
The mode specifies both the regular permissions and the file type, and
|
||||||
It consists of several bit fields as follows:
|
it also holds a couple of bits that are irrelevant to the cpio format,
|
||||||
|
because the field is actually a raw copy of the mode field in the inode
|
||||||
|
representing the file. These are the IALLOC flag, which shows that
|
||||||
|
the inode entry is in use, and the ILARG flag, which shows that the
|
||||||
|
file it represents is large enough to have indirect blocks pointers in
|
||||||
|
the inode.
|
||||||
|
The mode is decoded as follows:
|
||||||
|
.Pp
|
||||||
|
.Bl -tag -width "MMMMMMM" -compact
|
||||||
|
.It 0100000
|
||||||
|
IALLOC flag - irrelevant to cpio.
|
||||||
|
.It 0060000
|
||||||
|
This masks the file type bits.
|
||||||
|
.It 0040000
|
||||||
|
File type value for directories.
|
||||||
|
.It 0020000
|
||||||
|
File type value for character special devices.
|
||||||
|
.It 0060000
|
||||||
|
File type value for block special devices.
|
||||||
|
.It 0010000
|
||||||
|
ILARG flag - irrelevant to cpio.
|
||||||
|
.It 0004000
|
||||||
|
SUID bit.
|
||||||
|
.It 0002000
|
||||||
|
SGID bit.
|
||||||
|
.It 0001000
|
||||||
|
Sticky bit.
|
||||||
|
.It 0000777
|
||||||
|
The lower 9 bits specify read/write/execute permissions
|
||||||
|
for world, group, and user following standard POSIX conventions.
|
||||||
|
.El
|
||||||
|
.It Va h_uid , Va h_gid
|
||||||
|
The numeric user id and group id of the owner.
|
||||||
|
.It Va h_nlink
|
||||||
|
The number of links to this file.
|
||||||
|
Directories always have a value of at least two here.
|
||||||
|
Note that hardlinked files include file data with every copy in the archive.
|
||||||
|
.It Va h_majmin
|
||||||
|
For block special and character special entries,
|
||||||
|
this field contains the associated device number, with the major
|
||||||
|
number in the high byte, and the minor number in the low byte.
|
||||||
|
For all other entry types, it should be set to zero by writers
|
||||||
|
and ignored by readers.
|
||||||
|
.It Va h_mtime
|
||||||
|
Modification time of the file, indicated as the number
|
||||||
|
of seconds since the start of the epoch,
|
||||||
|
00:00:00 UTC January 1, 1970.
|
||||||
|
.It Va h_namesize
|
||||||
|
The number of bytes in the pathname that follows the header.
|
||||||
|
This count includes the trailing NUL byte.
|
||||||
|
.It Va h_filesize
|
||||||
|
The size of the file. Note that this archive format is limited to 16
|
||||||
|
megabyte file sizes, because PWB UNIX, like 6th Edition, only used
|
||||||
|
an unsigned 24 bit integer for the file size internally.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The pathname immediately follows the fixed header.
|
||||||
|
If
|
||||||
|
.Cm h_namesize
|
||||||
|
is odd, an additional NUL byte is added after the pathname.
|
||||||
|
The file data is then appended, again with an additional NUL
|
||||||
|
appended if needed to get the next header at an even offset.
|
||||||
|
.Pp
|
||||||
|
Hardlinked files are not given special treatment;
|
||||||
|
the full file contents are included with each copy of the
|
||||||
|
file.
|
||||||
|
.Ss New Binary Format
|
||||||
|
The new binary
|
||||||
|
.Nm
|
||||||
|
format showed up when cpio was adopted into late 7th Edition UNIX.
|
||||||
|
It is exactly like the PWB binary format, described above, except for
|
||||||
|
three changes:
|
||||||
|
.Pp
|
||||||
|
First, UNIX now ran on more than one hardware type, so the endianness
|
||||||
|
of 16 bit integers must be determined by observing the magic number at
|
||||||
|
the start of the header. The 32 bit integers are still always stored
|
||||||
|
with the most significant word first, though, so each of those two, in
|
||||||
|
the struct shown above, was stored as an array of two 16 bit integers,
|
||||||
|
in the traditional order. Those 16 bit integers, like all the others
|
||||||
|
in the struct, were accessed using a macro that byte swapped them if
|
||||||
|
necessary.
|
||||||
|
.Pp
|
||||||
|
Next, 7th Edition had more file types to store, and the IALLOC and ILARG
|
||||||
|
flag bits were re-purposed to accommodate these. The revised use of the
|
||||||
|
various bits is as follows:
|
||||||
|
.Pp
|
||||||
.Bl -tag -width "MMMMMMM" -compact
|
.Bl -tag -width "MMMMMMM" -compact
|
||||||
.It 0170000
|
.It 0170000
|
||||||
This masks the file type bits.
|
This masks the file type bits.
|
||||||
@ -124,51 +213,26 @@ SUID bit.
|
|||||||
SGID bit.
|
SGID bit.
|
||||||
.It 0001000
|
.It 0001000
|
||||||
Sticky bit.
|
Sticky bit.
|
||||||
On some systems, this modifies the behavior of executables and/or directories.
|
|
||||||
.It 0000777
|
.It 0000777
|
||||||
The lower 9 bits specify read/write/execute permissions
|
The lower 9 bits specify read/write/execute permissions
|
||||||
for world, group, and user following standard POSIX conventions.
|
for world, group, and user following standard POSIX conventions.
|
||||||
.El
|
.El
|
||||||
.It Va uid , Va gid
|
|
||||||
The numeric user id and group id of the owner.
|
|
||||||
.It Va nlink
|
|
||||||
The number of links to this file.
|
|
||||||
Directories always have a value of at least two here.
|
|
||||||
Note that hardlinked files include file data with every copy in the archive.
|
|
||||||
.It Va rdev
|
|
||||||
For block special and character special entries,
|
|
||||||
this field contains the associated device number.
|
|
||||||
For all other entry types, it should be set to zero by writers
|
|
||||||
and ignored by readers.
|
|
||||||
.It Va mtime
|
|
||||||
Modification time of the file, indicated as the number
|
|
||||||
of seconds since the start of the epoch,
|
|
||||||
00:00:00 UTC January 1, 1970.
|
|
||||||
The four-byte integer is stored with the most-significant 16 bits first
|
|
||||||
followed by the least-significant 16 bits.
|
|
||||||
Each of the two 16 bit values are stored in machine-native byte order.
|
|
||||||
.It Va namesize
|
|
||||||
The number of bytes in the pathname that follows the header.
|
|
||||||
This count includes the trailing NUL byte.
|
|
||||||
.It Va filesize
|
|
||||||
The size of the file.
|
|
||||||
Note that this archive format is limited to
|
|
||||||
four gigabyte file sizes.
|
|
||||||
See
|
|
||||||
.Va mtime
|
|
||||||
above for a description of the storage of four-byte integers.
|
|
||||||
.El
|
|
||||||
.Pp
|
.Pp
|
||||||
The pathname immediately follows the fixed header.
|
Finally, the file size field now represents a signed 32 bit integer in
|
||||||
If the
|
the underlying file system, so the maximum file size has increased to
|
||||||
.Cm namesize
|
2 gigabytes.
|
||||||
is odd, an additional NUL byte is added after the pathname.
|
|
||||||
The file data is then appended, padded with NUL
|
|
||||||
bytes to an even length.
|
|
||||||
.Pp
|
.Pp
|
||||||
Hardlinked files are not given special treatment;
|
Note that there is no obvious way to tell which of the two binary
|
||||||
the full file contents are included with each copy of the
|
formats an archive uses, other than to see which one makes more
|
||||||
file.
|
sense. The typical error scenario is that a PWB format archive
|
||||||
|
unpacked as if it were in the new format will create named sockets
|
||||||
|
instead of directories, and then fail to unpack files that should
|
||||||
|
go in those directories. Running
|
||||||
|
.Va bsdcpio -itv
|
||||||
|
on an unknown archive will make it obvious which it is: if it's
|
||||||
|
PWB format, directories will be listed with an 's' instead of
|
||||||
|
a 'd' as the first character of the mode string, and the larger
|
||||||
|
files will have a '?' in that position.
|
||||||
.Ss Portable ASCII Format
|
.Ss Portable ASCII Format
|
||||||
.St -susv2
|
.St -susv2
|
||||||
standardized an ASCII variant that is portable across all
|
standardized an ASCII variant that is portable across all
|
||||||
@ -180,6 +244,7 @@ format or as the
|
|||||||
format.
|
format.
|
||||||
It stores the same numeric fields as the old binary format, but
|
It stores the same numeric fields as the old binary format, but
|
||||||
represents them as 6-character or 11-character octal values.
|
represents them as 6-character or 11-character octal values.
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct cpio_odc_header {
|
struct cpio_odc_header {
|
||||||
char c_magic[6];
|
char c_magic[6];
|
||||||
@ -196,9 +261,9 @@ struct cpio_odc_header {
|
|||||||
};
|
};
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The fields are identical to those in the old binary format.
|
The fields are identical to those in the new binary format.
|
||||||
The name and file body follow the fixed header.
|
The name and file body follow the fixed header.
|
||||||
Unlike the old binary format, there is no additional padding
|
Unlike the binary formats, there is no additional padding
|
||||||
after the pathname or file contents.
|
after the pathname or file contents.
|
||||||
If the files being archived are themselves entirely ASCII, then
|
If the files being archived are themselves entirely ASCII, then
|
||||||
the resulting archive will be entirely ASCII, except for the
|
the resulting archive will be entirely ASCII, except for the
|
||||||
@ -207,6 +272,7 @@ NUL byte that terminates the name field.
|
|||||||
The "new" ASCII format uses 8-byte hexadecimal fields for
|
The "new" ASCII format uses 8-byte hexadecimal fields for
|
||||||
all numbers and separates device numbers into separate fields
|
all numbers and separates device numbers into separate fields
|
||||||
for major and minor numbers.
|
for major and minor numbers.
|
||||||
|
.Pp
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
struct cpio_newc_header {
|
struct cpio_newc_header {
|
||||||
char c_magic[6];
|
char c_magic[6];
|
||||||
@ -227,7 +293,7 @@ struct cpio_newc_header {
|
|||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
Except as specified below, the fields here match those specified
|
Except as specified below, the fields here match those specified
|
||||||
for the old binary format above.
|
for the new binary format above.
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Va magic
|
.It Va magic
|
||||||
The string
|
The string
|
||||||
@ -288,9 +354,9 @@ while working in AT&T's Unix Support Group.
|
|||||||
It appeared in 1977 as part of PWB/UNIX 1.0, the
|
It appeared in 1977 as part of PWB/UNIX 1.0, the
|
||||||
.Dq Programmer's Work Bench
|
.Dq Programmer's Work Bench
|
||||||
derived from
|
derived from
|
||||||
.At v6
|
.At 6th Edition UNIX
|
||||||
that was used internally at AT&T.
|
that was used internally at AT&T.
|
||||||
Both the old binary and old character formats were in use
|
Both the new binary and old character formats were in use
|
||||||
by 1980, according to the System III source released
|
by 1980, according to the System III source released
|
||||||
by SCO under their
|
by SCO under their
|
||||||
.Dq Ancient Unix
|
.Dq Ancient Unix
|
||||||
@ -304,9 +370,9 @@ The
|
|||||||
format is mis-named, as it uses a simple checksum and
|
format is mis-named, as it uses a simple checksum and
|
||||||
not a cyclic redundancy check.
|
not a cyclic redundancy check.
|
||||||
.Pp
|
.Pp
|
||||||
The old binary format is limited to 16 bits for user id,
|
The binary formats are limited to 16 bits for user id, group id,
|
||||||
group id, device, and inode numbers.
|
device, and inode numbers. They are limited to 16 megabyte and 2
|
||||||
It is limited to 4 gigabyte file sizes.
|
gigabyte file sizes for the older and newer variants, respectively.
|
||||||
.Pp
|
.Pp
|
||||||
The old ASCII format is limited to 18 bits for
|
The old ASCII format is limited to 18 bits for
|
||||||
the user id, group id, device, and inode numbers.
|
the user id, group id, device, and inode numbers.
|
||||||
|
@ -201,28 +201,27 @@ POSIX.1-2001 extended the ustar format to create the
|
|||||||
.Dq pax interchange
|
.Dq pax interchange
|
||||||
format.
|
format.
|
||||||
.Ss Cpio Formats
|
.Ss Cpio Formats
|
||||||
The libarchive library can read a number of common cpio variants and can write
|
The libarchive library can read and write a number of common cpio
|
||||||
.Dq odc
|
variants. A cpio archive stores each entry as a fixed-size header
|
||||||
and
|
followed by a variable-length filename and variable-length data.
|
||||||
.Dq newc
|
Unlike the tar format, the cpio format does only minimal padding of
|
||||||
format archives.
|
the header or file data. There are several cpio variants, which
|
||||||
A cpio archive stores each entry as a fixed-size header followed
|
differ primarily in how they store the initial header: some store the
|
||||||
by a variable-length filename and variable-length data.
|
values as octal or hexadecimal numbers in ASCII, others as binary
|
||||||
Unlike the tar format, the cpio format does only minimal padding
|
values of varying byte order and length.
|
||||||
of the header or file data.
|
|
||||||
There are several cpio variants, which differ primarily in
|
|
||||||
how they store the initial header: some store the values as
|
|
||||||
octal or hexadecimal numbers in ASCII, others as binary values of
|
|
||||||
varying byte order and length.
|
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Cm binary
|
.It Cm binary
|
||||||
The libarchive library transparently reads both big-endian and little-endian
|
The libarchive library transparently reads both big-endian and
|
||||||
variants of the original binary cpio format.
|
little-endian variants of the the two binary cpio formats; the
|
||||||
This format used 32-bit binary values for file size and mtime,
|
original one from PWB/UNIX, and the later, more widely used, variant.
|
||||||
and 16-bit binary values for the other fields.
|
This format used 32-bit binary values for file size and mtime, and
|
||||||
|
16-bit binary values for the other fields. The formats support only
|
||||||
|
the file types present in UNIX at the time of their creation. File
|
||||||
|
sizes are limited to 24 bits in the PWB format, because of the limits
|
||||||
|
of the file system, and to 31 bits in the newer binary format, where
|
||||||
|
signed 32 bit longs were used.
|
||||||
.It Cm odc
|
.It Cm odc
|
||||||
The libarchive library can both read and write this
|
This is the POSIX standardized format, which is officially known as the
|
||||||
POSIX-standard format, which is officially known as the
|
|
||||||
.Dq cpio interchange format
|
.Dq cpio interchange format
|
||||||
or the
|
or the
|
||||||
.Dq octet-oriented cpio archive format
|
.Dq octet-oriented cpio archive format
|
||||||
|
@ -105,7 +105,7 @@ POSIX
|
|||||||
.Dq pax interchange format
|
.Dq pax interchange format
|
||||||
archives,
|
archives,
|
||||||
.It
|
.It
|
||||||
POSIX octet-oriented cpio archives,
|
cpio archives,
|
||||||
.It
|
.It
|
||||||
Zip archive,
|
Zip archive,
|
||||||
.It
|
.It
|
||||||
|
@ -52,6 +52,10 @@ DEFINE_TEST(test_archive_pathmatch)
|
|||||||
assertEqualInt(0, archive_pathmatch("a/b/c", "a/b/", 0));
|
assertEqualInt(0, archive_pathmatch("a/b/c", "a/b/", 0));
|
||||||
assertEqualInt(0, archive_pathmatch("a/b/c", "a/b", 0));
|
assertEqualInt(0, archive_pathmatch("a/b/c", "a/b", 0));
|
||||||
|
|
||||||
|
/* Null string and non-empty pattern returns false. */
|
||||||
|
assertEqualInt(0, archive_pathmatch("a/b/c", NULL, 0));
|
||||||
|
assertEqualInt(0, archive_pathmatch_w(L"a/b/c", NULL, 0));
|
||||||
|
|
||||||
/* Empty pattern only matches empty string. */
|
/* Empty pattern only matches empty string. */
|
||||||
assertEqualInt(1, archive_pathmatch("","", 0));
|
assertEqualInt(1, archive_pathmatch("","", 0));
|
||||||
assertEqualInt(0, archive_pathmatch("","a", 0));
|
assertEqualInt(0, archive_pathmatch("","a", 0));
|
||||||
|
@ -141,7 +141,7 @@ compat_lzma(const char *name)
|
|||||||
|
|
||||||
DEFINE_TEST(test_compat_lzma)
|
DEFINE_TEST(test_compat_lzma)
|
||||||
{
|
{
|
||||||
/* This sample has been added junk datas to its tail. */
|
/* This sample has been added junk data to its tail. */
|
||||||
compat_lzma("test_compat_lzma_1.tlz");
|
compat_lzma("test_compat_lzma_1.tlz");
|
||||||
/* This sample has been made by lzma with option -e,
|
/* This sample has been made by lzma with option -e,
|
||||||
* the first byte of which is 0x5e.
|
* the first byte of which is 0x5e.
|
||||||
|
@ -528,7 +528,7 @@ test_basic(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Save current working directory. */
|
/* Save current working directory. */
|
||||||
#ifdef PATH_MAX
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
||||||
initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
||||||
#else
|
#else
|
||||||
initial_cwd = getcwd(NULL, 0);
|
initial_cwd = getcwd(NULL, 0);
|
||||||
@ -560,7 +560,7 @@ test_basic(void)
|
|||||||
failure(
|
failure(
|
||||||
"Current working directory does not return to the initial"
|
"Current working directory does not return to the initial"
|
||||||
"directory");
|
"directory");
|
||||||
#ifdef PATH_MAX
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
||||||
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
||||||
#else
|
#else
|
||||||
cwd = getcwd(NULL, 0);
|
cwd = getcwd(NULL, 0);
|
||||||
@ -1047,7 +1047,14 @@ test_restore_atime(void)
|
|||||||
size_t size;
|
size_t size;
|
||||||
int64_t offset;
|
int64_t offset;
|
||||||
int file_count;
|
int file_count;
|
||||||
|
const char *skip_test_restore_atime;
|
||||||
|
|
||||||
|
skip_test_restore_atime = getenv("SKIP_TEST_RESTORE_ATIME");
|
||||||
|
if (skip_test_restore_atime != NULL) {
|
||||||
|
skipping("Skipping restore atime tests due to "
|
||||||
|
"SKIP_TEST_RESTORE_ATIME environment variable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!atimeIsUpdated()) {
|
if (!atimeIsUpdated()) {
|
||||||
skipping("Can't test restoring atime on this filesystem");
|
skipping("Can't test restoring atime on this filesystem");
|
||||||
return;
|
return;
|
||||||
|
@ -998,3 +998,30 @@ DEFINE_TEST(test_read_format_zip_7z_lzma)
|
|||||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_TEST(test_read_format_zip_7z_deflate)
|
||||||
|
{
|
||||||
|
const char *refname = "test_read_format_zip_7z_deflate.zip";
|
||||||
|
struct archive_entry *ae;
|
||||||
|
struct archive *a;
|
||||||
|
|
||||||
|
assert((a = archive_read_new()) != NULL);
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
|
||||||
|
extract_reference_file(refname);
|
||||||
|
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK,
|
||||||
|
archive_read_open_filename(a, refname, 10240));
|
||||||
|
//read first symlink
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||||
|
assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
|
||||||
|
assertEqualString("libxkbcommon-x11.so.0.0.0",
|
||||||
|
archive_entry_symlink(ae));
|
||||||
|
//read second symlink
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||||
|
assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
|
||||||
|
assertEqualString("libxkbcommon-x11.so.0.0.0",
|
||||||
|
archive_entry_symlink(ae));
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a));
|
||||||
|
}
|
||||||
|
@ -0,0 +1,361 @@
|
|||||||
|
begin 644 test_read_format_zip_7z_deflate.zip
|
||||||
|
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
|
||||||
|
*RP```.H]````````
|
||||||
|
`
|
||||||
|
end
|
216
contrib/libarchive/libarchive/test/test_short_writes.c
Normal file
216
contrib/libarchive/libarchive/test/test_short_writes.c
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2021 Red Hat, Inc.
|
||||||
|
* 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 "test.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This test checks whether things work correctly when the archive_write_callback
|
||||||
|
* passed to archive_write_open() does a short write and only writes some of the
|
||||||
|
* data passed in. The way the test works is that two archives are constructed
|
||||||
|
* in parallel - one with short writes, one with full writes - and the results
|
||||||
|
* are compared to see if they are identical.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct checker {
|
||||||
|
struct archive *short_archive;
|
||||||
|
char *shortbuf;
|
||||||
|
size_t shortbuf_len;
|
||||||
|
|
||||||
|
struct archive *full_archive;
|
||||||
|
char *fullbuf;
|
||||||
|
size_t fullbuf_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
short_write_callback(struct archive *a, void *client_data, const void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
(void)a;
|
||||||
|
|
||||||
|
struct checker *checker = client_data;
|
||||||
|
size_t to_write = length < 100 ? length : 100;
|
||||||
|
size_t new_len = checker->shortbuf_len + to_write;
|
||||||
|
char *new_buf = realloc(checker->shortbuf, new_len);
|
||||||
|
assert(new_buf != NULL);
|
||||||
|
|
||||||
|
checker->shortbuf = new_buf;
|
||||||
|
memcpy(checker->shortbuf + checker->shortbuf_len, buffer, to_write);
|
||||||
|
checker->shortbuf_len = new_len;
|
||||||
|
|
||||||
|
return to_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
full_write_callback(struct archive *a, void *client_data, const void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
(void)a;
|
||||||
|
|
||||||
|
struct checker *checker = client_data;
|
||||||
|
size_t to_write = length;
|
||||||
|
size_t new_len = checker->fullbuf_len + to_write;
|
||||||
|
char *new_buf = realloc(checker->fullbuf, new_len);
|
||||||
|
assert(new_buf != NULL);
|
||||||
|
|
||||||
|
checker->fullbuf = new_buf;
|
||||||
|
memcpy(checker->fullbuf + checker->fullbuf_len, buffer, to_write);
|
||||||
|
checker->fullbuf_len = new_len;
|
||||||
|
|
||||||
|
return to_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct archive *
|
||||||
|
create_archive(struct checker *checker, archive_write_callback write_cb, int buffered)
|
||||||
|
{
|
||||||
|
struct archive *a;
|
||||||
|
|
||||||
|
assert((a = archive_write_new()) != NULL);
|
||||||
|
|
||||||
|
if (!buffered)
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK,
|
||||||
|
archive_write_set_bytes_per_block(a, 0));
|
||||||
|
|
||||||
|
/* With the default value of bytes_in_last_block, the writing code will
|
||||||
|
* pad out the final write to make it a full block. This causes problems
|
||||||
|
* for us because the size of the final write can be different depending
|
||||||
|
* on the size of previous writes, causing the "short" and "full" paths
|
||||||
|
* to get different amounts of padding. Setting it to 1 results in no
|
||||||
|
* padding other than that defined by the archive format. */
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK,
|
||||||
|
archive_write_set_bytes_in_last_block(a, 1));
|
||||||
|
|
||||||
|
/* We write a pax archive, but other formats would work fine too. */
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK,
|
||||||
|
archive_write_set_format_pax(a));
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK,
|
||||||
|
archive_write_add_filter_none(a));
|
||||||
|
|
||||||
|
assertEqualIntA(a, ARCHIVE_OK,
|
||||||
|
archive_write_open(a, checker, NULL, write_cb, NULL));
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct checker *
|
||||||
|
checker_new(int buffered)
|
||||||
|
{
|
||||||
|
struct checker *checker;
|
||||||
|
|
||||||
|
assert ((checker = calloc(1, sizeof *checker)) != NULL);
|
||||||
|
|
||||||
|
checker->short_archive = create_archive(checker, short_write_callback, buffered);
|
||||||
|
checker->full_archive = create_archive(checker, full_write_callback, buffered);
|
||||||
|
|
||||||
|
return checker;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
checker_add_file(struct checker *checker, const char *name, char *buffer, size_t len)
|
||||||
|
{
|
||||||
|
struct archive_entry *entry;
|
||||||
|
assert((entry = archive_entry_new()) != NULL);
|
||||||
|
|
||||||
|
archive_entry_set_pathname(entry, name);
|
||||||
|
archive_entry_set_mode(entry, AE_IFREG | 0755);
|
||||||
|
archive_entry_set_size(entry, len);
|
||||||
|
|
||||||
|
assertEqualIntA(checker->short_archive, ARCHIVE_OK,
|
||||||
|
archive_write_header(checker->short_archive, entry));
|
||||||
|
assertEqualIntA(checker->short_archive, len,
|
||||||
|
archive_write_data(checker->short_archive, buffer, len));
|
||||||
|
|
||||||
|
assertEqualIntA(checker->full_archive, ARCHIVE_OK,
|
||||||
|
archive_write_header(checker->full_archive, entry));
|
||||||
|
assertEqualIntA(checker->full_archive, len,
|
||||||
|
archive_write_data(checker->full_archive, buffer, len));
|
||||||
|
|
||||||
|
archive_entry_free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
checker_close(struct checker *checker)
|
||||||
|
{
|
||||||
|
assertEqualIntA(checker->short_archive, ARCHIVE_OK,
|
||||||
|
archive_write_close(checker->short_archive));
|
||||||
|
assertEqualIntA(checker->short_archive, ARCHIVE_OK,
|
||||||
|
archive_write_close(checker->full_archive));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
checker_check(struct checker *checker)
|
||||||
|
{
|
||||||
|
assertEqualInt(checker->shortbuf_len, checker->fullbuf_len);
|
||||||
|
assert(memcmp(checker->shortbuf, checker->fullbuf, checker->fullbuf_len) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
checker_free(struct checker *checker)
|
||||||
|
{
|
||||||
|
free(checker->shortbuf);
|
||||||
|
free(checker->fullbuf);
|
||||||
|
free(checker);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_TEST(test_short_writes)
|
||||||
|
{
|
||||||
|
struct checker *checker;
|
||||||
|
uint16_t test_data[16384];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 16384; i++)
|
||||||
|
test_data[i] = i;
|
||||||
|
|
||||||
|
|
||||||
|
/* Write a file smaller than the default buffer size (10 * 1024);
|
||||||
|
* this will be written out at close.
|
||||||
|
*/
|
||||||
|
checker = checker_new(1);
|
||||||
|
checker_add_file(checker, "a", (char *)test_data, 1024);
|
||||||
|
checker_close(checker);
|
||||||
|
assert(checker->shortbuf_len > 1024);
|
||||||
|
checker_check(checker);
|
||||||
|
checker_free(checker);
|
||||||
|
|
||||||
|
/* Write a file larger larger than twice default buffer size (10 * 1024);
|
||||||
|
* this both fills the buffer and writes it out, and also exercises
|
||||||
|
* the "write out full blocks directly" code path.
|
||||||
|
*/
|
||||||
|
checker = checker_new(1);
|
||||||
|
checker_add_file(checker, "a", (char *)test_data, 21 * 1024);
|
||||||
|
checker_close(checker);
|
||||||
|
assert(checker->shortbuf_len > 21 * 1024);
|
||||||
|
checker_check(checker);
|
||||||
|
checker_free(checker);
|
||||||
|
|
||||||
|
/* Test unbuffered writes - a different code path.
|
||||||
|
*/
|
||||||
|
checker = checker_new(0);
|
||||||
|
checker_add_file(checker, "a", (char *)test_data, 1024);
|
||||||
|
checker_close(checker);
|
||||||
|
assert(checker->shortbuf_len > 1024);
|
||||||
|
checker_check(checker);
|
||||||
|
checker_free(checker);
|
||||||
|
}
|
@ -577,7 +577,7 @@ DEFINE_TEST(test_sparse_basic)
|
|||||||
|
|
||||||
/* Check if the filesystem where CWD on can
|
/* Check if the filesystem where CWD on can
|
||||||
* report the number of the holes of a sparse file. */
|
* report the number of the holes of a sparse file. */
|
||||||
#ifdef PATH_MAX
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
||||||
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
||||||
#else
|
#else
|
||||||
cwd = getcwd(NULL, 0);
|
cwd = getcwd(NULL, 0);
|
||||||
@ -637,7 +637,7 @@ DEFINE_TEST(test_fully_sparse_files)
|
|||||||
|
|
||||||
/* Check if the filesystem where CWD on can
|
/* Check if the filesystem where CWD on can
|
||||||
* report the number of the holes of a sparse file. */
|
* report the number of the holes of a sparse file. */
|
||||||
#ifdef PATH_MAX
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
||||||
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
||||||
#else
|
#else
|
||||||
cwd = getcwd(NULL, 0);
|
cwd = getcwd(NULL, 0);
|
||||||
|
@ -67,7 +67,7 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
{
|
{
|
||||||
char *nl, *nlp;
|
char *nl, *nlp;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
int exisiting;
|
int existing;
|
||||||
|
|
||||||
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -85,15 +85,15 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
exisiting = 0;
|
existing = 0;
|
||||||
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
||||||
if (strcmp(nlp, xattrname) == 0) {
|
if (strcmp(nlp, xattrname) == 0) {
|
||||||
exisiting = 1;
|
existing = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(nl);
|
free(nl);
|
||||||
return (exisiting);
|
return (existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
81
contrib/libarchive/libarchive/test/test_write_disk_fixup.c
Normal file
81
contrib/libarchive/libarchive/test/test_write_disk_fixup.c
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2021 Martin Matuska
|
||||||
|
* 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 "test.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test fixup entries don't follow symlinks
|
||||||
|
*/
|
||||||
|
DEFINE_TEST(test_write_disk_fixup)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
skipping("Skipping test on Windows");
|
||||||
|
#else
|
||||||
|
struct archive *ad;
|
||||||
|
struct archive_entry *ae;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!canSymlink()) {
|
||||||
|
skipping("Symlinks not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write entries to disk. */
|
||||||
|
assert((ad = archive_write_disk_new()) != NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a file
|
||||||
|
*/
|
||||||
|
assertMakeFile("victim", 0600, "a");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a directory and a symlink with the same name
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Directory: dir */
|
||||||
|
assert((ae = archive_entry_new()) != NULL);
|
||||||
|
archive_entry_copy_pathname(ae, "dir");
|
||||||
|
archive_entry_set_mode(ae, AE_IFDIR | 0606);
|
||||||
|
assertEqualIntA(ad, 0, archive_write_header(ad, ae));
|
||||||
|
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||||
|
archive_entry_free(ae);
|
||||||
|
|
||||||
|
/* Symbolic Link: dir -> foo */
|
||||||
|
assert((ae = archive_entry_new()) != NULL);
|
||||||
|
archive_entry_copy_pathname(ae, "dir");
|
||||||
|
archive_entry_set_mode(ae, AE_IFLNK | 0777);
|
||||||
|
archive_entry_set_size(ae, 0);
|
||||||
|
archive_entry_copy_symlink(ae, "victim");
|
||||||
|
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
|
||||||
|
if (r >= ARCHIVE_WARN)
|
||||||
|
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||||
|
archive_entry_free(ae);
|
||||||
|
|
||||||
|
assertEqualInt(ARCHIVE_OK, archive_write_free(ad));
|
||||||
|
|
||||||
|
/* Test the entries on disk. */
|
||||||
|
assertIsSymlink("dir", "victim", 0);
|
||||||
|
assertFileMode("victim", 0600);
|
||||||
|
#endif
|
||||||
|
}
|
@ -49,6 +49,9 @@ DEFINE_TEST(test_write_disk_hardlink)
|
|||||||
static const char data[]="abcdefghijklmnopqrstuvwxyz";
|
static const char data[]="abcdefghijklmnopqrstuvwxyz";
|
||||||
struct archive *ad;
|
struct archive *ad;
|
||||||
struct archive_entry *ae;
|
struct archive_entry *ae;
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
int can_symlink;
|
||||||
|
#endif
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* Force the umask to something predictable. */
|
/* Force the umask to something predictable. */
|
||||||
@ -147,7 +150,7 @@ DEFINE_TEST(test_write_disk_hardlink)
|
|||||||
archive_entry_free(ae);
|
archive_entry_free(ae);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally, try a new-cpio-like approach, where the initial
|
* Third, try a new-cpio-like approach, where the initial
|
||||||
* regular file is empty and the hardlink has the data.
|
* regular file is empty and the hardlink has the data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -174,6 +177,41 @@ DEFINE_TEST(test_write_disk_hardlink)
|
|||||||
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||||
}
|
}
|
||||||
archive_entry_free(ae);
|
archive_entry_free(ae);
|
||||||
|
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
/* Finally, try creating a hard link to a dangling symlink */
|
||||||
|
can_symlink = canSymlink();
|
||||||
|
if (can_symlink) {
|
||||||
|
/* Symbolic link: link5a -> foo */
|
||||||
|
assert((ae = archive_entry_new()) != NULL);
|
||||||
|
archive_entry_copy_pathname(ae, "link5a");
|
||||||
|
archive_entry_set_mode(ae, AE_IFLNK | 0642);
|
||||||
|
archive_entry_unset_size(ae);
|
||||||
|
archive_entry_copy_symlink(ae, "foo");
|
||||||
|
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
|
||||||
|
if (r >= ARCHIVE_WARN) {
|
||||||
|
assertEqualInt(ARCHIVE_WARN,
|
||||||
|
archive_write_data(ad, data, sizeof(data)));
|
||||||
|
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||||
|
}
|
||||||
|
archive_entry_free(ae);
|
||||||
|
|
||||||
|
|
||||||
|
/* Link. Size of zero means this doesn't carry data. */
|
||||||
|
assert((ae = archive_entry_new()) != NULL);
|
||||||
|
archive_entry_copy_pathname(ae, "link5b");
|
||||||
|
archive_entry_set_mode(ae, S_IFREG | 0642);
|
||||||
|
archive_entry_set_size(ae, 0);
|
||||||
|
archive_entry_copy_hardlink(ae, "link5a");
|
||||||
|
assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
|
||||||
|
if (r >= ARCHIVE_WARN) {
|
||||||
|
assertEqualInt(ARCHIVE_WARN,
|
||||||
|
archive_write_data(ad, data, sizeof(data)));
|
||||||
|
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
|
||||||
|
}
|
||||||
|
archive_entry_free(ae);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
assertEqualInt(0, archive_write_free(ad));
|
assertEqualInt(0, archive_write_free(ad));
|
||||||
|
|
||||||
/* Test the entries on disk. */
|
/* Test the entries on disk. */
|
||||||
@ -211,5 +249,14 @@ DEFINE_TEST(test_write_disk_hardlink)
|
|||||||
assertFileNLinks("link4a", 2);
|
assertFileNLinks("link4a", 2);
|
||||||
assertFileSize("link4a", sizeof(data));
|
assertFileSize("link4a", sizeof(data));
|
||||||
assertIsHardlink("link4a", "link4b");
|
assertIsHardlink("link4a", "link4b");
|
||||||
|
|
||||||
|
#ifdef HAVE_LINKAT
|
||||||
|
if (can_symlink) {
|
||||||
|
/* Test #5 */
|
||||||
|
assertIsSymlink("link5a", "foo", 0);
|
||||||
|
assertFileNLinks("link5a", 2);
|
||||||
|
assertIsHardlink("link5a", "link5b");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
{
|
{
|
||||||
char *nl, *nlp;
|
char *nl, *nlp;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
int exisiting;
|
int existing;
|
||||||
|
|
||||||
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -55,15 +55,15 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
exisiting = 0;
|
existing = 0;
|
||||||
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
||||||
if (strcmp(nlp, xattrname) == 0) {
|
if (strcmp(nlp, xattrname) == 0) {
|
||||||
exisiting = 1;
|
existing = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(nl);
|
free(nl);
|
||||||
return (exisiting);
|
return (existing);
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
get_rsrc_footer(const char *filename, char *buff, size_t s)
|
get_rsrc_footer(const char *filename, char *buff, size_t s)
|
||||||
|
@ -67,7 +67,7 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
{
|
{
|
||||||
char *nl, *nlp;
|
char *nl, *nlp;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
int exisiting;
|
int existing;
|
||||||
|
|
||||||
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -85,15 +85,15 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
exisiting = 0;
|
existing = 0;
|
||||||
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
||||||
if (strcmp(nlp, xattrname) == 0) {
|
if (strcmp(nlp, xattrname) == 0) {
|
||||||
exisiting = 1;
|
existing = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(nl);
|
free(nl);
|
||||||
return (exisiting);
|
return (existing);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,7 +37,7 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
{
|
{
|
||||||
char *nl, *nlp;
|
char *nl, *nlp;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
int exisiting;
|
int existing;
|
||||||
|
|
||||||
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
@ -55,15 +55,15 @@ has_xattr(const char *filename, const char *xattrname)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
exisiting = 0;
|
existing = 0;
|
||||||
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
|
||||||
if (strcmp(nlp, xattrname) == 0) {
|
if (strcmp(nlp, xattrname) == 0) {
|
||||||
exisiting = 1;
|
existing = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(nl);
|
free(nl);
|
||||||
return (exisiting);
|
return (existing);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -273,18 +273,28 @@ test_big_entries(int (*set_format)(struct archive *), int64_t size, int expected
|
|||||||
|
|
||||||
DEFINE_TEST(test_write_format_cpio)
|
DEFINE_TEST(test_write_format_cpio)
|
||||||
{
|
{
|
||||||
|
int64_t size_16m = ((int64_t)1) << 24;
|
||||||
|
int64_t size_2g = ((int64_t)1) << 31;
|
||||||
int64_t size_4g = ((int64_t)1) << 32;
|
int64_t size_4g = ((int64_t)1) << 32;
|
||||||
int64_t size_8g = ((int64_t)1) << 33;
|
int64_t size_8g = ((int64_t)1) << 33;
|
||||||
|
|
||||||
test_format(archive_write_set_format_cpio);
|
test_format(archive_write_set_format_cpio_odc);
|
||||||
test_format(archive_write_set_format_cpio_newc);
|
test_format(archive_write_set_format_cpio_newc);
|
||||||
|
|
||||||
test_big_entries(archive_write_set_format_cpio,
|
test_big_entries(archive_write_set_format_cpio_odc,
|
||||||
size_8g - 1, ARCHIVE_OK);
|
size_8g - 1, ARCHIVE_OK);
|
||||||
test_big_entries(archive_write_set_format_cpio,
|
test_big_entries(archive_write_set_format_cpio_odc,
|
||||||
size_8g, ARCHIVE_FAILED);
|
size_8g, ARCHIVE_FAILED);
|
||||||
test_big_entries(archive_write_set_format_cpio_newc,
|
test_big_entries(archive_write_set_format_cpio_newc,
|
||||||
size_4g - 1, ARCHIVE_OK);
|
size_4g - 1, ARCHIVE_OK);
|
||||||
test_big_entries(archive_write_set_format_cpio_newc,
|
test_big_entries(archive_write_set_format_cpio_newc,
|
||||||
size_4g, ARCHIVE_FAILED);
|
size_4g, ARCHIVE_FAILED);
|
||||||
|
test_big_entries(archive_write_set_format_cpio_bin,
|
||||||
|
size_2g - 1, ARCHIVE_OK);
|
||||||
|
test_big_entries(archive_write_set_format_cpio_bin,
|
||||||
|
size_2g, ARCHIVE_FAILED);
|
||||||
|
test_big_entries(archive_write_set_format_cpio_pwb,
|
||||||
|
size_16m - 1, ARCHIVE_OK);
|
||||||
|
test_big_entries(archive_write_set_format_cpio_pwb,
|
||||||
|
size_16m, ARCHIVE_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ DEFINE_TEST(test_write_format_cpio_empty)
|
|||||||
|
|
||||||
/* Create a new archive in memory. */
|
/* Create a new archive in memory. */
|
||||||
assert((a = archive_write_new()) != NULL);
|
assert((a = archive_write_new()) != NULL);
|
||||||
assertA(0 == archive_write_set_format_cpio(a));
|
assertA(0 == archive_write_set_format_cpio_odc(a));
|
||||||
assertA(0 == archive_write_add_filter_none(a));
|
assertA(0 == archive_write_add_filter_none(a));
|
||||||
/* 1-byte block size ensures we see only the required bytes. */
|
/* 1-byte block size ensures we see only the required bytes. */
|
||||||
/* We're not testing the padding here. */
|
/* We're not testing the padding here. */
|
||||||
|
@ -54,7 +54,7 @@ DEFINE_TEST(test_write_format_cpio_odc)
|
|||||||
|
|
||||||
/* Create a new archive in memory. */
|
/* Create a new archive in memory. */
|
||||||
assert((a = archive_write_new()) != NULL);
|
assert((a = archive_write_new()) != NULL);
|
||||||
assertEqualIntA(a, 0, archive_write_set_format_cpio(a));
|
assertEqualIntA(a, 0, archive_write_set_format_cpio_odc(a));
|
||||||
assertEqualIntA(a, 0, archive_write_add_filter_none(a));
|
assertEqualIntA(a, 0, archive_write_add_filter_none(a));
|
||||||
assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));
|
assertEqualIntA(a, 0, archive_write_open_memory(a, buff, buffsize, &used));
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip_no_compression.c 201247 2009-12-30 05:59:21Z kientzle $");
|
||||||
|
|
||||||
/* File data */
|
/* File data */
|
||||||
static const char file_name[] = "file";
|
static const char file_name[] = "file";
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip_empty.c 201247 2009-12-30 05:59:21Z kientzle $");
|
||||||
|
|
||||||
DEFINE_TEST(test_write_format_zip_empty_zip64)
|
DEFINE_TEST(test_write_format_zip_empty_zip64)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detailed byte-for-byte verification of the format of a zip archive
|
* Detailed byte-for-byte verification of the format of a zip archive
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detailed byte-for-byte verification of the format of a zip archive
|
* Detailed byte-for-byte verification of the format of a zip archive
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_format_zip.c 201247 2009-12-30 05:59:21Z kientzle $");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These tests verify that our reader can read files
|
* These tests verify that our reader can read files
|
||||||
|
@ -150,7 +150,11 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
|
|||||||
#if GCC_VERSION >= 409
|
#if GCC_VERSION >= 409
|
||||||
__attribute__((__no_sanitize_undefined__))
|
__attribute__((__no_sanitize_undefined__))
|
||||||
#endif
|
#endif
|
||||||
static inline U32 A32(const void * x)
|
#if defined(_MSC_VER)
|
||||||
|
static __inline U32 A32(const void * x)
|
||||||
|
#else
|
||||||
|
static inline U32 A32(const void* x)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
return (((const U32_S *)(x))->v);
|
return (((const U32_S *)(x))->v);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ DEFINE_TEST(test_option_safe_writes)
|
|||||||
}
|
}
|
||||||
assertEqualInt(0, chdir(".."));
|
assertEqualInt(0, chdir(".."));
|
||||||
|
|
||||||
/* Extract created archive withe safe writes */
|
/* Extract created archive with safe writes */
|
||||||
assertEqualInt(0,
|
assertEqualInt(0,
|
||||||
systemf("%s -x -C out --safe-writes -f t.tar "
|
systemf("%s -x -C out --safe-writes -f t.tar "
|
||||||
">unpack.out 2>unpack.err", testprog));
|
">unpack.out 2>unpack.err", testprog));
|
||||||
|
@ -3680,7 +3680,7 @@ get_refdir(const char *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the current dir. */
|
/* Get the current dir. */
|
||||||
#ifdef PATH_MAX
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
||||||
pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
||||||
#else
|
#else
|
||||||
pwd = getcwd(NULL, 0);
|
pwd = getcwd(NULL, 0);
|
||||||
@ -3775,7 +3775,7 @@ main(int argc, char **argv)
|
|||||||
(void)argc; /* UNUSED */
|
(void)argc; /* UNUSED */
|
||||||
|
|
||||||
/* Get the current dir. */
|
/* Get the current dir. */
|
||||||
#ifdef PATH_MAX
|
#if defined(PATH_MAX) && !defined(__GLIBC__)
|
||||||
pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
|
||||||
#else
|
#else
|
||||||
pwd = getcwd(NULL, 0);
|
pwd = getcwd(NULL, 0);
|
||||||
|
@ -133,7 +133,9 @@ SRCS= archive_acl.c \
|
|||||||
archive_write_set_format_ar.c \
|
archive_write_set_format_ar.c \
|
||||||
archive_write_set_format_by_name.c \
|
archive_write_set_format_by_name.c \
|
||||||
archive_write_set_format_cpio.c \
|
archive_write_set_format_cpio.c \
|
||||||
|
archive_write_set_format_cpio_binary.c \
|
||||||
archive_write_set_format_cpio_newc.c \
|
archive_write_set_format_cpio_newc.c \
|
||||||
|
archive_write_set_format_cpio_odc.c \
|
||||||
archive_write_set_format_filter_by_ext.c \
|
archive_write_set_format_filter_by_ext.c \
|
||||||
archive_write_set_format_gnutar.c \
|
archive_write_set_format_gnutar.c \
|
||||||
archive_write_set_format_iso9660.c \
|
archive_write_set_format_iso9660.c \
|
||||||
|
@ -137,6 +137,7 @@
|
|||||||
#define HAVE_LIBZ 1
|
#define HAVE_LIBZ 1
|
||||||
#define HAVE_LIMITS_H 1
|
#define HAVE_LIMITS_H 1
|
||||||
#define HAVE_LINK 1
|
#define HAVE_LINK 1
|
||||||
|
#define HAVE_LINKAT 1
|
||||||
#define HAVE_LOCALE_H 1
|
#define HAVE_LOCALE_H 1
|
||||||
#define HAVE_LOCALTIME_R 1
|
#define HAVE_LOCALTIME_R 1
|
||||||
#define HAVE_LONG_LONG_INT 1
|
#define HAVE_LONG_LONG_INT 1
|
||||||
|
@ -214,6 +214,7 @@ TESTS_SRCS= \
|
|||||||
test_read_too_many_filters.c \
|
test_read_too_many_filters.c \
|
||||||
test_read_truncated.c \
|
test_read_truncated.c \
|
||||||
test_read_truncated_filter.c \
|
test_read_truncated_filter.c \
|
||||||
|
test_short_writes.c \
|
||||||
test_sparse_basic.c \
|
test_sparse_basic.c \
|
||||||
test_tar_filenames.c \
|
test_tar_filenames.c \
|
||||||
test_tar_large.c \
|
test_tar_large.c \
|
||||||
@ -223,6 +224,7 @@ TESTS_SRCS= \
|
|||||||
test_write_disk.c \
|
test_write_disk.c \
|
||||||
test_write_disk_appledouble.c \
|
test_write_disk_appledouble.c \
|
||||||
test_write_disk_failures.c \
|
test_write_disk_failures.c \
|
||||||
|
test_write_disk_fixup.c \
|
||||||
test_write_disk_hardlink.c \
|
test_write_disk_hardlink.c \
|
||||||
test_write_disk_hfs_compression.c \
|
test_write_disk_hfs_compression.c \
|
||||||
test_write_disk_lookup.c \
|
test_write_disk_lookup.c \
|
||||||
@ -582,6 +584,7 @@ ${PACKAGE}FILES+= test_read_format_ustar_filename_koi8r.tar.Z.uu
|
|||||||
${PACKAGE}FILES+= test_read_format_warc.warc.uu
|
${PACKAGE}FILES+= test_read_format_warc.warc.uu
|
||||||
${PACKAGE}FILES+= test_read_format_zip.zip.uu
|
${PACKAGE}FILES+= test_read_format_zip.zip.uu
|
||||||
${PACKAGE}FILES+= test_read_format_zip_7075_utf8_paths.zip.uu
|
${PACKAGE}FILES+= test_read_format_zip_7075_utf8_paths.zip.uu
|
||||||
|
${PACKAGE}FILES+= test_read_format_zip_7z_deflate.zip.uu
|
||||||
${PACKAGE}FILES+= test_read_format_zip_7z_lzma.zip.uu
|
${PACKAGE}FILES+= test_read_format_zip_7z_lzma.zip.uu
|
||||||
${PACKAGE}FILES+= test_read_format_zip_bz2_hang.zip.uu
|
${PACKAGE}FILES+= test_read_format_zip_bz2_hang.zip.uu
|
||||||
${PACKAGE}FILES+= test_read_format_zip_bzip2.zipx.uu
|
${PACKAGE}FILES+= test_read_format_zip_bzip2.zipx.uu
|
||||||
|
Loading…
Reference in New Issue
Block a user