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:
Martin Matuska 2021-08-23 02:54:15 +02:00
commit ddce862ad8
69 changed files with 2408 additions and 813 deletions

View File

@ -1,3 +1,5 @@
Aug 22, 2021: libarchive 3.5.2 released
Dec 26, 2020: libarchive 3.5.1 released
Dec 01, 2020: libarchive 3.5.0 released

View File

@ -79,6 +79,7 @@ Currently, the library automatically detects and reads the following formats:
* POSIX octet-oriented cpio
* SVR4 ASCII cpio
* Binary cpio (big-endian or little-endian)
* PWB binary cpio
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
* 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)
@ -110,6 +111,8 @@ The library can create archives in any of the following formats:
* Old V7 tar format
* POSIX octet-oriented cpio
* SVR4 "newc" cpio
* Binary cpio (little-endian)
* PWB binary cpio
* shar archives
* ZIP archives (with uncompressed or "deflate" compressed entries)
* GNU and BSD 'ar' archives

View File

@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
* $FreeBSD: src/usr.bin/tar/bsdtar_platform.h,v 1.26 2008/12/06 07:37:14 kientzle Exp $
*/
/*

View File

@ -82,6 +82,13 @@ all operating modes.
.It Fl 0 , Fl Fl null
Read filenames separated by NUL characters instead of 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
(o mode only)
Append to the specified archive.

View File

@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
/*
* 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.
@ -62,6 +62,7 @@ static const struct option {
int equivalent; /* Equivalent short option. */
} cpio_longopts[] = {
{ "b64encode", 0, OPTION_B64ENCODE },
{ "binary", 0, '7' },
{ "create", 0, 'o' },
{ "dereference", 0, 'L' },
{ "dot", 0, 'V' },
@ -86,6 +87,7 @@ static const struct option {
{ "pass-through", 0, 'p' },
{ "preserve-modification-time", 0, 'm' },
{ "preserve-owner", 0, OPTION_PRESERVE_OWNER },
{ "pwb", 0, '6' },
{ "quiet", 0, OPTION_QUIET },
{ "unconditional", 0, 'u' },
{ "uuencode", 0, OPTION_UUENCODE },

View File

@ -192,6 +192,12 @@ main(int argc, char *argv[])
case '0': /* GNU convention: --null, -0 */
cpio->option_null = 1;
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 */
cpio->option_append = 1;
break;
@ -400,11 +406,12 @@ main(int argc, char *argv[])
switch (cpio->mode) {
case 'o':
/* TODO: Implement old binary format in libarchive,
use that here. */
if (cpio->format == NULL)
cpio->format = "odc"; /* Default format */
if (cpio->format == NULL) {
if (cpio->option_pwb)
cpio->format = "pwb";
else
cpio->format = "cpio";
}
mode_out(cpio);
break;
case 'i':
@ -462,7 +469,7 @@ static const char *long_help_msg =
" -v Verbose filenames -V one dot per file\n"
"Create: %p -o [options] < [list of files] > [archive]\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"
"Extract: %p -i [options] < [archive]\n";
@ -970,6 +977,8 @@ mode_in(struct cpio *cpio)
lafe_errc(1, 0, "Couldn't allocate archive object");
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (cpio->option_pwb)
archive_read_set_options(a, "pwb");
if (cpio->passphrase != NULL)
r = archive_read_add_passphrase(a, cpio->passphrase);
else
@ -1080,6 +1089,8 @@ mode_list(struct cpio *cpio)
lafe_errc(1, 0, "Couldn't allocate archive object");
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
if (cpio->option_pwb)
archive_read_set_options(a, "pwb");
if (cpio->passphrase != NULL)
r = archive_read_add_passphrase(a, cpio->passphrase);
else

View File

@ -62,6 +62,7 @@ struct cpio {
int option_list; /* -t */
char option_null; /* --null */
int option_numeric_uid_gid; /* -n */
int option_pwb; /* -6 */
int option_rename; /* -r */
char *destdir;
size_t destdir_len;

View File

@ -230,6 +230,8 @@ DEFINE_TEST(test_basic)
basic_cpio("copy_odc", "--format=odc", "", msg, msg);
basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
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";
basic_cpio("copy_ustar", "-H ustar", "", msg, msg);

View File

@ -36,7 +36,7 @@
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
*/
/* 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 <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.
*/
#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
__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_CRC (ARCHIVE_FORMAT_CPIO | 5)
#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_BASE (ARCHIVE_FORMAT_SHAR | 1)
#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_svr4(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_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_iso9660(struct archive *);
__LA_DECL int archive_write_set_format_mtree(struct archive *);

View File

@ -319,7 +319,7 @@ translate_acl(struct archive_read_disk *a,
static int
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 acl_type = 0;
@ -364,6 +364,13 @@ set_acl(struct archive *a, int fd, const char *name,
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);
if (acl == (acl_t)NULL) {
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
/* 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
{
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) {
if ((archive_acl_types(abstract_acl)
& 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");
if (ret != ARCHIVE_OK)
return (ret);
}
if ((archive_acl_types(abstract_acl)
& 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");
/* 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
else if ((archive_acl_types(abstract_acl) &
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");
}
#endif

View File

@ -30,7 +30,7 @@
#define ARCHIVE_ENTRY_H_INCLUDED
/* 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

View File

@ -384,6 +384,8 @@ __archive_pathmatch(const char *p, const char *s, int flags)
/* Empty pattern only matches the empty string. */
if (p == NULL || *p == '\0')
return (s == NULL || *s == '\0');
else if (s == NULL)
return (0);
/* Leading '^' anchors the start of the pattern. */
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. */
if (p == NULL || *p == L'\0')
return (s == NULL || *s == L'\0');
else if (s == NULL)
return (0);
/* Leading '^' anchors the start of the pattern. */
if (*p == L'^') {

View File

@ -46,6 +46,13 @@
#define __LA_DEAD
#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_READ_MAGIC (0xdeb0c5U)
#define ARCHIVE_WRITE_DISK_MAGIC (0xc001b0c5U)

View File

@ -173,7 +173,7 @@ arc4_init(void)
}
static inline void
arc4_addrandom(u_char *dat, int datlen)
arc4_addrandom(uint8_t *dat, int datlen)
{
int n;
uint8_t si;
@ -196,7 +196,7 @@ arc4_stir(void)
struct {
struct timeval tv;
pid_t pid;
u_char rnd[KEYSIZE];
uint8_t rnd[KEYSIZE];
} rdat;
if (!rs_initialized) {
@ -216,7 +216,7 @@ arc4_stir(void)
/* 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:
@ -258,7 +258,7 @@ arc4_getbyte(void)
static void
arc4random_buf(void *_buf, size_t n)
{
u_char *buf = (u_char *)_buf;
uint8_t *buf = (uint8_t *)_buf;
_ARC4_LOCK();
arc4_stir_if_needed();
while (n--) {

View File

@ -1522,8 +1522,40 @@ get_xfer_size(struct tree *t, int fd, const char *path)
}
#endif
#if defined(HAVE_STATFS) && defined(HAVE_FSTATFS) && defined(MNT_LOCAL) \
&& !defined(ST_LOCAL)
#if defined(HAVE_STATVFS)
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.
@ -1593,10 +1625,7 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
t->current_filesystem->xfer_align = sfs.f_bsize;
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;
set_statfs_transfer_size(t->current_filesystem, &sfs);
}
if (sfs.f_flags & MNT_LOCAL)
t->current_filesystem->remote = 0;
@ -1688,15 +1717,7 @@ setup_current_filesystem(struct archive_read_disk *a)
} else if (xr == 1) {
/* Usually come here unless NetBSD supports _PC_REC_XFER_ALIGN
* for pathconf() function. */
t->current_filesystem->xfer_align = svfs.f_frsize;
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
set_statvfs_transfer_size(t->current_filesystem, &svfs);
}
if (svfs.f_flag & ST_LOCAL)
t->current_filesystem->remote = 0;
@ -1803,15 +1824,9 @@ setup_current_filesystem(struct archive_read_disk *a)
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
#if defined(HAVE_STATVFS)
t->current_filesystem->xfer_align = svfs.f_frsize;
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;
set_statvfs_transfer_size(t->current_filesystem, &svfs);
#else
t->current_filesystem->xfer_align = sfs.f_frsize;
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;
set_statfs_transfer_size(t->current_filesystem, &sfs);
#endif
}
switch (sfs.f_type) {
@ -1918,10 +1933,7 @@ setup_current_filesystem(struct archive_read_disk *a)
return (ARCHIVE_FAILED);
} else if (xr == 1) {
/* pathconf(_PC_REX_*) operations are not supported. */
t->current_filesystem->xfer_align = svfs.f_frsize;
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;
set_statvfs_transfer_size(t->current_filesystem, &svfs);
}
#if defined(ST_NOATIME)

View File

@ -24,7 +24,7 @@
*/
#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
#include <sys/types.h>

View File

@ -188,9 +188,18 @@ used when translating file names.
.El
.It Format cpio
.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
The value is used as a character set name that will be
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
.It Format iso9660
.Bl -tag -compact -width indent

View File

@ -216,7 +216,7 @@ rpm_filter_read(struct archive_read_filter *self, const void **buff)
archive_set_error(
&self->archive->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Unrecoginized rpm header");
"Unrecognized rpm header");
return (ARCHIVE_FATAL);
}
rpm->state = ST_ARCHIVE;

View File

@ -248,7 +248,7 @@ bid_get_line(struct archive_read_filter *filter,
*ravail = *avail;
*b += 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);
if (len >= 0)
len += tested;

View File

@ -808,8 +808,12 @@ archive_read_format_7zip_read_data(struct archive_read *a,
if (zip->end_of_entry)
return (ARCHIVE_EOF);
bytes = read_stream(a, buff,
(size_t)zip->entry_bytes_remaining, 0);
const uint64_t max_read_size = 16 * 1024 * 1024; // Don't try to read more than 16 MB at a time
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)
return ((int)bytes);
if (bytes == 0) {
@ -1493,7 +1497,7 @@ decompress(struct archive_read *a, struct _7zip *zip,
zip->ppmd7_stat = -1;
archive_set_error(&a->archive,
ARCHIVE_ERRNO_MISC,
"Failed to initialize PPMd range decorder");
"Failed to initialize PPMd range decoder");
return (ARCHIVE_FAILED);
}
if (zip->ppstream.overconsumed) {
@ -3031,10 +3035,10 @@ extract_pack_stream(struct archive_read *a, size_t minimum)
"Truncated 7-Zip file body");
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;
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;
zip->folder_outbytes_remaining -= bytes_avail;
zip->uncompressed_buffer_bytes_remaining = bytes_avail;

View File

@ -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);
if (ds->pos_tbl == NULL)
return (ARCHIVE_FATAL);
lzx_huffman_free(&(ds->mt));
}
for (footer = 0; footer < 18; footer++)

View File

@ -185,6 +185,8 @@ struct cpio {
struct archive_string_conv *opt_sconv;
struct archive_string_conv *sconv_default;
int init_default_conversion;
int option_pwb;
};
static int64_t atol16(const char *, unsigned);
@ -343,6 +345,10 @@ archive_read_format_cpio_options(struct archive_read *a,
ret = ARCHIVE_FATAL;
}
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
@ -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_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);
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_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);
@ -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_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]);
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_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]);

View File

@ -408,7 +408,7 @@ next_line(struct archive_read *a,
*ravail = *avail;
*b += 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);
if (len >= 0)
len += tested;
@ -1074,7 +1074,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
continue;
/* Non-printable characters are not allowed */
for (s = p;s < p + len - 1; s++) {
if (!isprint(*s)) {
if (!isprint((unsigned char)*s)) {
r = ARCHIVE_FATAL;
break;
}
@ -2035,13 +2035,13 @@ mtree_atol(char **p, int base)
if (**p == '-') {
limit = INT64_MIN / base;
last_digit_limit = INT64_MIN % base;
last_digit_limit = -(INT64_MIN % base);
++(*p);
l = 0;
digit = parsedigit(**p);
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;
l = (l * base) - digit;
digit = parsedigit(*++(*p));

View File

@ -958,17 +958,17 @@ archive_read_format_rar_read_header(struct archive_read *a,
crc32_val = 0;
while (skip > 0) {
size_t to_read = skip;
ssize_t did_read;
if (to_read > 32 * 1024) {
if (to_read > 32 * 1024)
to_read = 32 * 1024;
}
if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
if ((h = __archive_read_ahead(a, to_read, NULL)) == NULL) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Bad RAR file");
return (ARCHIVE_FATAL);
}
p = h;
crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
__archive_read_consume(a, did_read);
skip -= did_read;
crc32_val = crc32(crc32_val, (const unsigned char *)p, to_read);
__archive_read_consume(a, to_read);
skip -= to_read;
}
if ((crc32_val & 0xffff) != crc32_expected) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,

View File

@ -4076,6 +4076,7 @@ int archive_read_support_format_rar5(struct archive *_a) {
if(ARCHIVE_OK != rar5_init(rar)) {
archive_set_error(&ar->archive, ENOMEM,
"Can't allocate rar5 filter buffer");
free(rar);
return ARCHIVE_FATAL;
}

View File

@ -1908,7 +1908,7 @@ pax_attribute(struct archive_read *a, struct tar *tar,
}
if (strcmp(key, "GNU.sparse.numbytes") == 0) {
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,
tar->sparse_offset, tar->sparse_numbytes)
!= ARCHIVE_OK)
@ -2645,14 +2645,14 @@ tar_atol_base_n(const char *p, size_t char_cnt, int base)
maxval = INT64_MIN;
limit = -(INT64_MIN / base);
last_digit_limit = INT64_MIN % base;
last_digit_limit = -(INT64_MIN % base);
}
l = 0;
if (char_cnt != 0) {
digit = *p - '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. */
}
l = (l * base) + digit;

View File

@ -142,6 +142,7 @@ struct zip {
/* Structural information about the archive. */
struct archive_string format_name;
int64_t central_directory_offset;
int64_t central_directory_offset_adjusted;
size_t central_directory_entries_total;
size_t central_directory_entries_on_this_disk;
int has_encrypted_entries;
@ -246,6 +247,17 @@ struct zip {
/* Many systems define min or MIN, but not all. */
#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
* 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
@ -899,81 +911,6 @@ process_extra(struct archive_read *a, struct archive_entry *entry,
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.
*/
@ -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;
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
size_t linkname_full_length = linkname_length;
if (zip->entry->compression != 0)
{
// symlink target string appeared to be compressed
int status = ARCHIVE_FATAL;
char *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;
}
const void *uncompressed_buffer;
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
case 14: /* ZIPx LZMA compression. */
/*(see zip file format specification, section 4.4.5)*/
status = zipx_lzma_uncompress_buffer(p,
linkname_length,
uncompressed_buffer,
(size_t)zip_entry->uncompressed_size);
zip->entry_bytes_remaining = zip_entry->compressed_size;
status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
&linkname_full_length, NULL);
break;
#endif
default: /* Unsupported compression. */
@ -1280,8 +1211,6 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
if (status == ARCHIVE_OK)
{
p = uncompressed_buffer;
linkname_full_length =
(size_t)zip_entry->uncompressed_size;
}
else
{
@ -1294,6 +1223,16 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
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;
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
* 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
* `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. */
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
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. */
/* This must be the first volume. */
if (archive_le16dec(p + 4) != 0)
if (disk_num != 0)
return 0;
/* 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;
/* All central directory entries must be on this volume. */
if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
return 0;
/* Central directory can't extend beyond start of EOCD record. */
if (archive_le32dec(p + 16) + archive_le32dec(p + 12)
> current_offset)
if (cd_offset + cd_size > current_offset)
return 0;
/* 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
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. */
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;
}
@ -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
* 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;
found = 0;

View File

@ -25,7 +25,7 @@
*/
#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
#include <stdlib.h>

View File

@ -482,6 +482,8 @@ archive_write_client_close(struct archive_write_filter *f)
ssize_t block_length;
ssize_t target_block_length;
ssize_t bytes_written;
size_t to_write;
char *p;
int ret = ARCHIVE_OK;
/* 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);
block_length = target_block_length;
}
bytes_written = (a->client_writer)(&a->archive,
a->client_data, state->buffer, block_length);
ret = bytes_written <= 0 ? ARCHIVE_FATAL : ARCHIVE_OK;
p = state->buffer;
to_write = block_length;
while (to_write > 0) {
bytes_written = (a->client_writer)(&a->archive,
a->client_data, p, to_write);
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)
(*a->client_closer)(&a->archive, a->client_data);

View File

@ -360,7 +360,7 @@ static int la_mktemp(struct archive_write_disk *);
static void fsobj_error(int *, struct archive_string *, int, const char *,
const char *);
static int check_symlinks_fsobj(char *, int *, struct archive_string *,
int);
int, int);
static int check_symlinks(struct archive_write_disk *);
static int create_filesystem_object(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);
}
r = check_symlinks_fsobj(linkname_copy, &error_number,
&error_string, a->flags);
&error_string, a->flags, 1);
if (r != ARCHIVE_OK) {
archive_set_error(&a->archive, error_number, "%s",
error_string.s);
@ -2284,7 +2284,12 @@ create_filesystem_object(struct archive_write_disk *a)
*/
if (a->flags & ARCHIVE_EXTRACT_SAFE_WRITES)
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;
#endif
/*
* New cpio and pax formats allow hardlink entries
* 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 fixup_entry *next, *p;
struct stat st;
int fd, ret;
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)) {
fd = open(p->name,
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) {
set_times(a, fd, p->mode, p->name,
@ -2487,7 +2507,12 @@ _archive_write_disk_close(struct archive *_a)
fchmod(fd, p->mode);
else
#endif
chmod(p->name, p->mode);
#ifdef HAVE_LCHMOD
lchmod(p->name, p->mode);
#else
if (!S_ISLNK(p->mode))
chmod(p->name, p->mode);
#endif
}
if (p->fixup & TODO_ACLS)
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)
set_mac_metadata(a, p->name, p->mac_metadata,
p->mac_metadata_size);
skip_fixup_entry:
next = p->next;
archive_acl_clear(&p->acl);
free(p->mac_metadata);
@ -2638,6 +2664,7 @@ new_fixup(struct archive_write_disk *a, const char *pathname)
fe->next = a->fixup_list;
a->fixup_list = fe;
fe->fixup = 0;
fe->mode = 0;
fe->name = strdup(pathname);
return (fe);
}
@ -2675,7 +2702,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
*/
static int
check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
int flags)
int flags, int checking_linkname)
{
#if !defined(HAVE_LSTAT) && \
!(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_string; /* UNUSED */
(void)flags; /* UNUSED */
(void)checking_linkname; /* UNUSED */
return (ARCHIVE_OK);
#else
int res = ARCHIVE_OK;
@ -2805,6 +2833,28 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
head = tail + 1;
}
} 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) {
/*
* Last element is symlink; remove it
@ -2971,7 +3021,7 @@ check_symlinks(struct archive_write_disk *a)
int rc;
archive_string_init(&error_string);
rc = check_symlinks_fsobj(a->name, &error_number, &error_string,
a->flags);
a->flags, 0);
if (rc != ARCHIVE_OK) {
archive_set_error(&a->archive, error_number, "%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 (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);
}
if (myfd < 0)

View File

@ -35,7 +35,10 @@
.Nm archive_write_set_format_ar_svr4 ,
.Nm archive_write_set_format_by_name ,
.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_odc ,
.Nm archive_write_set_format_cpio_pwb ,
.Nm archive_write_set_format_filter_by_ext ,
.Nm archive_write_set_format_filter_by_ext_def ,
.Nm archive_write_set_format_gnutar ,
@ -73,8 +76,14 @@ Streaming Archive Library (libarchive, -larchive)
.Ft int
.Fn archive_write_set_format_cpio "struct archive *"
.Ft int
.Fn archive_write_set_format_cpio_bin "struct archive *"
.Ft int
.Fn archive_write_set_format_cpio_newc "struct archive *"
.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"
.Ft int
.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
Sets the corresponding format based on the common name.
.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
.Xc
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
.It Xo
.Fn archive_write_set_format_7zip
.Fn archive_write_set_format_ar_bsd ,
.Fn archive_write_set_format_ar_svr4 ,
.Fn archive_write_set_format_ar_bsd
.Fn archive_write_set_format_ar_svr4
.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_odc
.Fn archive_write_set_format_cpio_pwb
.Fn archive_write_set_format_gnutar
.Fn archive_write_set_format_iso9660
.Fn archive_write_set_format_mtree

View File

@ -44,7 +44,9 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{
{ ARCHIVE_FORMAT_7ZIP, archive_write_set_format_7zip },
{ 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_ISO9660, archive_write_set_format_iso9660 },
{ ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },

View File

@ -755,6 +755,10 @@ _7z_close(struct archive_write *a)
*/
#if HAVE_LZMA_H
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.
* This is the same way 7z command does. */
if (zip->total_number_entry == 1)
@ -762,7 +766,8 @@ _7z_close(struct archive_write *a)
#else
header_compression = _7Z_COPY;
#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)
return (r);
zip->crc32flg = PRECODE_CRC32;

View File

@ -49,6 +49,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "arbsd", archive_write_set_format_ar_bsd },
{ "argnu", 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 },
{ "cd9660", archive_write_set_format_iso9660 },
{ "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-classic", archive_write_set_format_mtree_classic },
{ "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 },
{ "pax", archive_write_set_format_pax },
{ "paxr", archive_write_set_format_pax_restricted },
{ "posix", archive_write_set_format_pax },
{ "pwb", archive_write_set_format_cpio_pwb },
{ "raw", archive_write_set_format_raw },
{ "rpax", archive_write_set_format_pax_restricted },
{ "shar", archive_write_set_format_shar },

View File

@ -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_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
archive_write_set_format_cpio(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");
/* 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));
return archive_write_set_format_cpio_odc(_a);
}

View File

@ -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));
}

View File

@ -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));
}

View File

@ -25,7 +25,7 @@
*/
#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
#include <sys/types.h>

View File

@ -279,7 +279,7 @@ Values between 0 and 9 are supported.
The interpretation of the compression level depends on the chosen
compression method.
.El
.It Format cpio
.It Format bin
.Bl -tag -compact -width indent
.It Cm hdrcharset
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
used when translating file names.
.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
.Bl -tag -compact -width indent
.It Cm hdrcharset

View File

@ -56,40 +56,44 @@ The end of the archive is indicated by a special record with
the pathname
.Dq TRAILER!!! .
.Ss PWB format
XXX Any documentation of the original PWB/UNIX 1.0 format? XXX
.Ss Old Binary Format
The old binary
The PWB binary
.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:
.Pp
.Bd -literal -offset indent
struct header_old_cpio {
unsigned short c_magic;
unsigned short c_dev;
unsigned short c_ino;
unsigned short c_mode;
unsigned short c_uid;
unsigned short c_gid;
unsigned short c_nlink;
unsigned short c_rdev;
unsigned short c_mtime[2];
unsigned short c_namesize;
unsigned short c_filesize[2];
struct header_pwb_cpio {
short h_magic;
short h_dev;
short h_ino;
short h_mode;
short h_uid;
short h_gid;
short h_nlink;
short h_majmin;
long h_mtime;
short h_namesize;
long h_filesize;
};
.Ed
.Pp
The
.Va unsigned short
fields here are 16-bit integer values; the
.Va unsigned int
fields are 32-bit integer values.
The fields are as follows
.Va short
fields here are 16-bit integer values, while the
.Va long
fields are 32 bit integers. Since PWB UNIX, like the 6th Edition UNIX
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
.It Va magic
.It Va h_magic
The integer value octal 070707.
This value can be used to determine whether this archive is
written with little-endian or big-endian integers.
.It Va dev , Va ino
.It Va h_dev , Va h_ino
The device and inode numbers from the disk.
These are used by programs that read
.Nm
@ -97,9 +101,94 @@ archives to determine when two entries refer to the same file.
Programs that synthesize
.Nm
archives should be careful to set these to distinct values for each entry.
.It Va mode
The mode specifies both the regular permissions and the file type.
It consists of several bit fields as follows:
.It Va h_mode
The mode specifies both the regular permissions and the file type, and
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
.It 0170000
This masks the file type bits.
@ -124,51 +213,26 @@ SUID bit.
SGID bit.
.It 0001000
Sticky bit.
On some systems, this modifies the behavior of executables and/or directories.
.It 0000777
The lower 9 bits specify read/write/execute permissions
for world, group, and user following standard POSIX conventions.
.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
The pathname immediately follows the fixed header.
If the
.Cm namesize
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.
Finally, the file size field now represents a signed 32 bit integer in
the underlying file system, so the maximum file size has increased to
2 gigabytes.
.Pp
Hardlinked files are not given special treatment;
the full file contents are included with each copy of the
file.
Note that there is no obvious way to tell which of the two binary
formats an archive uses, other than to see which one makes more
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
.St -susv2
standardized an ASCII variant that is portable across all
@ -180,6 +244,7 @@ format or as the
format.
It stores the same numeric fields as the old binary format, but
represents them as 6-character or 11-character octal values.
.Pp
.Bd -literal -offset indent
struct cpio_odc_header {
char c_magic[6];
@ -196,9 +261,9 @@ struct cpio_odc_header {
};
.Ed
.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.
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.
If the files being archived are themselves entirely ASCII, then
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
all numbers and separates device numbers into separate fields
for major and minor numbers.
.Pp
.Bd -literal -offset indent
struct cpio_newc_header {
char c_magic[6];
@ -227,7 +293,7 @@ struct cpio_newc_header {
.Ed
.Pp
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
.It Va magic
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
.Dq Programmer's Work Bench
derived from
.At v6
.At 6th Edition UNIX
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 SCO under their
.Dq Ancient Unix
@ -304,9 +370,9 @@ The
format is mis-named, as it uses a simple checksum and
not a cyclic redundancy check.
.Pp
The old binary format is limited to 16 bits for user id,
group id, device, and inode numbers.
It is limited to 4 gigabyte file sizes.
The binary formats are limited to 16 bits for user id, group id,
device, and inode numbers. They are limited to 16 megabyte and 2
gigabyte file sizes for the older and newer variants, respectively.
.Pp
The old ASCII format is limited to 18 bits for
the user id, group id, device, and inode numbers.

View File

@ -201,28 +201,27 @@ POSIX.1-2001 extended the ustar format to create the
.Dq pax interchange
format.
.Ss Cpio Formats
The libarchive library can read a number of common cpio variants and can write
.Dq odc
and
.Dq newc
format archives.
A cpio archive stores each entry as a fixed-size header followed
by a variable-length filename and variable-length data.
Unlike the tar format, the cpio format does only minimal padding
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.
The libarchive library can read and write a number of common cpio
variants. A cpio archive stores each entry as a fixed-size header
followed by a variable-length filename and variable-length data.
Unlike the tar format, the cpio format does only minimal padding 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
.It Cm binary
The libarchive library transparently reads both big-endian and little-endian
variants of the original binary cpio format.
This format used 32-bit binary values for file size and mtime,
and 16-bit binary values for the other fields.
The libarchive library transparently reads both big-endian and
little-endian variants of the the two binary cpio formats; the
original one from PWB/UNIX, and the later, more widely used, variant.
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
The libarchive library can both read and write this
POSIX-standard format, which is officially known as the
This is the POSIX standardized format, which is officially known as the
.Dq cpio interchange format
or the
.Dq octet-oriented cpio archive format

View File

@ -105,7 +105,7 @@ POSIX
.Dq pax interchange format
archives,
.It
POSIX octet-oriented cpio archives,
cpio archives,
.It
Zip archive,
.It

View File

@ -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));
/* 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. */
assertEqualInt(1, archive_pathmatch("","", 0));
assertEqualInt(0, archive_pathmatch("","a", 0));

View File

@ -141,7 +141,7 @@ compat_lzma(const char *name)
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");
/* This sample has been made by lzma with option -e,
* the first byte of which is 0x5e.

View File

@ -528,7 +528,7 @@ test_basic(void)
*/
/* Save current working directory. */
#ifdef PATH_MAX
#if defined(PATH_MAX) && !defined(__GLIBC__)
initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
#else
initial_cwd = getcwd(NULL, 0);
@ -560,7 +560,7 @@ test_basic(void)
failure(
"Current working directory does not return to the initial"
"directory");
#ifdef PATH_MAX
#if defined(PATH_MAX) && !defined(__GLIBC__)
cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
#else
cwd = getcwd(NULL, 0);
@ -1047,7 +1047,14 @@ test_restore_atime(void)
size_t size;
int64_t offset;
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()) {
skipping("Can't test restoring atime on this filesystem");
return;

View File

@ -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_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));
}

View File

@ -0,0 +1,361 @@
begin 644 test_read_format_zip_7z_deflate.zip
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
*RP```.H]````````
`
end

View 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);
}

View File

@ -577,7 +577,7 @@ DEFINE_TEST(test_sparse_basic)
/* Check if the filesystem where CWD on can
* 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. */
#else
cwd = getcwd(NULL, 0);
@ -637,7 +637,7 @@ DEFINE_TEST(test_fully_sparse_files)
/* Check if the filesystem where CWD on can
* 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. */
#else
cwd = getcwd(NULL, 0);

View File

@ -67,7 +67,7 @@ has_xattr(const char *filename, const char *xattrname)
{
char *nl, *nlp;
ssize_t r;
int exisiting;
int existing;
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
if (r < 0)
@ -85,15 +85,15 @@ has_xattr(const char *filename, const char *xattrname)
return (0);
}
exisiting = 0;
existing = 0;
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
if (strcmp(nlp, xattrname) == 0) {
exisiting = 1;
existing = 1;
break;
}
}
free(nl);
return (exisiting);
return (existing);
}
#endif

View 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
}

View File

@ -49,6 +49,9 @@ DEFINE_TEST(test_write_disk_hardlink)
static const char data[]="abcdefghijklmnopqrstuvwxyz";
struct archive *ad;
struct archive_entry *ae;
#ifdef HAVE_LINKAT
int can_symlink;
#endif
int r;
/* Force the umask to something predictable. */
@ -147,7 +150,7 @@ DEFINE_TEST(test_write_disk_hardlink)
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.
*/
@ -174,6 +177,41 @@ DEFINE_TEST(test_write_disk_hardlink)
assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
}
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));
/* Test the entries on disk. */
@ -211,5 +249,14 @@ DEFINE_TEST(test_write_disk_hardlink)
assertFileNLinks("link4a", 2);
assertFileSize("link4a", sizeof(data));
assertIsHardlink("link4a", "link4b");
#ifdef HAVE_LINKAT
if (can_symlink) {
/* Test #5 */
assertIsSymlink("link5a", "foo", 0);
assertFileNLinks("link5a", 2);
assertIsHardlink("link5a", "link5b");
}
#endif
#endif
}

View File

@ -37,7 +37,7 @@ has_xattr(const char *filename, const char *xattrname)
{
char *nl, *nlp;
ssize_t r;
int exisiting;
int existing;
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
if (r < 0)
@ -55,15 +55,15 @@ has_xattr(const char *filename, const char *xattrname)
return (0);
}
exisiting = 0;
existing = 0;
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
if (strcmp(nlp, xattrname) == 0) {
exisiting = 1;
existing = 1;
break;
}
}
free(nl);
return (exisiting);
return (existing);
}
static int
get_rsrc_footer(const char *filename, char *buff, size_t s)

View File

@ -67,7 +67,7 @@ has_xattr(const char *filename, const char *xattrname)
{
char *nl, *nlp;
ssize_t r;
int exisiting;
int existing;
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
if (r < 0)
@ -85,15 +85,15 @@ has_xattr(const char *filename, const char *xattrname)
return (0);
}
exisiting = 0;
existing = 0;
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
if (strcmp(nlp, xattrname) == 0) {
exisiting = 1;
existing = 1;
break;
}
}
free(nl);
return (exisiting);
return (existing);
}
#endif

View File

@ -37,7 +37,7 @@ has_xattr(const char *filename, const char *xattrname)
{
char *nl, *nlp;
ssize_t r;
int exisiting;
int existing;
r = listxattr(filename, NULL, 0, XATTR_SHOWCOMPRESSION);
if (r < 0)
@ -55,15 +55,15 @@ has_xattr(const char *filename, const char *xattrname)
return (0);
}
exisiting = 0;
existing = 0;
for (nlp = nl; nlp < nl + r; nlp += strlen(nlp) + 1) {
if (strcmp(nlp, xattrname) == 0) {
exisiting = 1;
existing = 1;
break;
}
}
free(nl);
return (exisiting);
return (existing);
}
#endif

View File

@ -273,18 +273,28 @@ test_big_entries(int (*set_format)(struct archive *), int64_t size, int expected
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_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_big_entries(archive_write_set_format_cpio,
test_big_entries(archive_write_set_format_cpio_odc,
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);
test_big_entries(archive_write_set_format_cpio_newc,
size_4g - 1, ARCHIVE_OK);
test_big_entries(archive_write_set_format_cpio_newc,
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);
}

View File

@ -52,7 +52,7 @@ DEFINE_TEST(test_write_format_cpio_empty)
/* Create a new archive in memory. */
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));
/* 1-byte block size ensures we see only the required bytes. */
/* We're not testing the padding here. */

View File

@ -54,7 +54,7 @@ DEFINE_TEST(test_write_format_cpio_odc)
/* Create a new archive in memory. */
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_open_memory(a, buff, buffsize, &used));

View File

@ -28,7 +28,7 @@
*/
#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 */
static const char file_name[] = "file";

View File

@ -28,7 +28,7 @@
*/
#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)
{

View File

@ -29,7 +29,7 @@
*/
#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

View File

@ -29,7 +29,7 @@
*/
#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

View File

@ -29,7 +29,7 @@
*/
#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

View File

@ -150,7 +150,11 @@ typedef struct _U32_S { U32 v; } _PACKED U32_S;
#if GCC_VERSION >= 409
__attribute__((__no_sanitize_undefined__))
#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);
}

View File

@ -58,7 +58,7 @@ DEFINE_TEST(test_option_safe_writes)
}
assertEqualInt(0, chdir(".."));
/* Extract created archive withe safe writes */
/* Extract created archive with safe writes */
assertEqualInt(0,
systemf("%s -x -C out --safe-writes -f t.tar "
">unpack.out 2>unpack.err", testprog));

View File

@ -3680,7 +3680,7 @@ get_refdir(const char *d)
}
/* Get the current dir. */
#ifdef PATH_MAX
#if defined(PATH_MAX) && !defined(__GLIBC__)
pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
#else
pwd = getcwd(NULL, 0);
@ -3775,7 +3775,7 @@ main(int argc, char **argv)
(void)argc; /* UNUSED */
/* Get the current dir. */
#ifdef PATH_MAX
#if defined(PATH_MAX) && !defined(__GLIBC__)
pwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
#else
pwd = getcwd(NULL, 0);

View File

@ -133,7 +133,9 @@ SRCS= archive_acl.c \
archive_write_set_format_ar.c \
archive_write_set_format_by_name.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_odc.c \
archive_write_set_format_filter_by_ext.c \
archive_write_set_format_gnutar.c \
archive_write_set_format_iso9660.c \

View File

@ -137,6 +137,7 @@
#define HAVE_LIBZ 1
#define HAVE_LIMITS_H 1
#define HAVE_LINK 1
#define HAVE_LINKAT 1
#define HAVE_LOCALE_H 1
#define HAVE_LOCALTIME_R 1
#define HAVE_LONG_LONG_INT 1

View File

@ -214,6 +214,7 @@ TESTS_SRCS= \
test_read_too_many_filters.c \
test_read_truncated.c \
test_read_truncated_filter.c \
test_short_writes.c \
test_sparse_basic.c \
test_tar_filenames.c \
test_tar_large.c \
@ -223,6 +224,7 @@ TESTS_SRCS= \
test_write_disk.c \
test_write_disk_appledouble.c \
test_write_disk_failures.c \
test_write_disk_fixup.c \
test_write_disk_hardlink.c \
test_write_disk_hfs_compression.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_zip.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_bz2_hang.zip.uu
${PACKAGE}FILES+= test_read_format_zip_bzip2.zipx.uu