+Aug 04, 2009: libarchive 2.7.1 released
+
+Jul 20, 2009: Suppress bogus warning about unxz
+Jul 19, 2009: Support Cygwin 1.7
+Jun 11, 2009: Support lzma/xz files compressed with larger buffer sizes.
+May 24, 2009: Handle gzip files signed with OpenBSD "gzsig" program.
+May 07, 2009: Avoid false failures when reading from pipe.
+
Apr 16, 2009: libarchive 2.7.0 released
Apr 10, 2009: libarchive 2.6.992a released
+++ /dev/null
-CMakeLists.txt
-INSTALL
-Makefile.am
-Makefile.in
-PROJECTS
-aclocal.m4
-build/autoconf/
-build/autogen.sh
-build/cmake/
-build/release.sh
-build/windows/
-config.h.in
-configure
-configure.ac
-contrib/
-cpio/CMakeLists.txt
-cpio/config_freebsd.h
-cpio/cpio_cygwin.c
-cpio/cpio_cygwin.h
-cpio/cpio_windows.c
-cpio/cpio_windows.h
-cpio/test/
-doc/
-examples/
-libarchive/CMakeLists.txt
-libarchive/archive_windows.c
-libarchive/archive_windows.h
-libarchive/config_freebsd.h
-libarchive/config_windows.h
-libarchive/filter_fork_windows.c
-libarchive/test/
-tar/CMakeLists.txt
-tar/bsdtar_cygwin.c
-tar/bsdtar_cygwin.h
-tar/bsdtar_windows.c
-tar/bsdtar_windows.h
-tar/config_freebsd.h
-tar/test/
/*
* Short options for cpio. Please keep this sorted.
*/
-static const char *short_options = "0AaBC:F:O:cdE:f:H:hijLlmnopR:rtuvW:yZz";
+static const char *short_options = "0AaBC:F:O:cdE:f:H:hI:ijLlmnopR:rtuvW:yZz";
/*
* Long options for cpio. Please keep this sorted.
if (cpio->option_numeric_uid_gid) {
/* Format numeric uid/gid for display. */
- snprintf(uids, sizeof(uids), "%jd",
- (intmax_t)archive_entry_uid(entry));
+ snprintf(uids, sizeof(uids), "%d",
+ (int)archive_entry_uid(entry));
uname = uids;
- snprintf(gids, sizeof(gids), "%jd",
- (intmax_t)archive_entry_gid(entry));
+ snprintf(gids, sizeof(gids), "%d",
+ (int)archive_entry_gid(entry));
gname = gids;
} else {
/* Use uname if it's present, else lookup name from uid. */
* (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
* #endif
*/
-#define ARCHIVE_VERSION_NUMBER 2007000
+#define ARCHIVE_VERSION_NUMBER 2007001
__LA_DECL int archive_version_number(void);
/*
* Textual name/version of the library, useful for version displays.
*/
-#define ARCHIVE_VERSION_STRING "libarchive 2.7.0"
+#define ARCHIVE_VERSION_STRING "libarchive 2.7.1"
__LA_DECL const char * archive_version_string(void);
#if ARCHIVE_VERSION_NUMBER < 3000000
const char *compression_name;
/* Position in UNCOMPRESSED data stream. */
- off_t file_position;
+ int64_t file_position;
/* Position in COMPRESSED data stream. */
- off_t raw_position;
+ int64_t raw_position;
int archive_error_number;
const char *error;
struct archive_read *a;
struct archive_format_descriptor *format;
char key[64], val[64];
+ char *valp;
size_t i;
int len, r;
while ((len = __archive_parse_options(s, format->name,
sizeof(key), key, sizeof(val), val)) > 0) {
- if (val[0] == '\0')
- r = format->options(a, key, NULL);
- else
- r = format->options(a, key, val);
+ valp = val[0] == '\0' ? NULL : val;
+ a->format = format;
+ r = format->options(a, key, valp);
+ a->format = NULL;
if (r == ARCHIVE_FATAL)
return (r);
s += len;
static int64_t
client_skip_proxy(struct archive_read_filter *self, int64_t request)
{
- int64_t r;
+ int64_t ask, get, total;
+ /* Limit our maximum seek request to 1GB on platforms
+ * with 32-bit off_t (such as Windows). */
+ int64_t skip_limit = ((int64_t)1) << (sizeof(off_t) * 8 - 2);
+
if (self->archive->client.skipper == NULL)
return (0);
- r = (self->archive->client.skipper)(&self->archive->archive,
- self->data, request);
- self->archive->archive.raw_position += r;
- return (r);
+ total = 0;
+ for (;;) {
+ ask = request;
+ if (ask > skip_limit)
+ ask = skip_limit;
+ get = (self->archive->client.skipper)(&self->archive->archive,
+ self->data, ask);
+ if (get == 0)
+ return (total);
+ request -= get;
+ self->archive->archive.raw_position += get;
+ total += get;
+ }
}
static int
int64_t
__archive_read_filter_skip(struct archive_read_filter *filter, int64_t request)
{
- off_t bytes_skipped, total_bytes_skipped = 0;
+ int64_t bytes_skipped, total_bytes_skipped = 0;
size_t min;
if (filter->fatal)
total_bytes_skipped += bytes_skipped;
}
if (filter->client_avail > 0) {
- min = minimum(request, (off_t)filter->client_avail);
+ min = minimum(request, (int64_t)filter->client_avail);
bytes_skipped = __archive_read_consume(filter->archive, min);
request -= bytes_skipped;
total_bytes_skipped += bytes_skipped;
int initial_fd = fd;
int r, r1;
+ archive_clear_error(_a);
path = archive_entry_sourcepath(entry);
if (path == NULL)
path = archive_entry_pathname(entry);
void *b;
int fd;
- if (filename == NULL || filename[0] == '\0')
- return (archive_read_open_fd(a, 0, block_size));
-
- fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0) {
- archive_set_error(a, errno, "Failed to open '%s'", filename);
- return (ARCHIVE_FATAL);
+ if (filename == NULL || filename[0] == '\0') {
+ /* We used to invoke archive_read_open_fd(a,0,block_size)
+ * here, but that doesn't (and shouldn't) handle the
+ * end-of-file flush when reading stdout from a pipe.
+ * Basically, read_open_fd() is intended for folks who
+ * are willing to handle such details themselves. This
+ * API is intended to be a little smarter for folks who
+ * want easy handling of the common case.
+ */
+ filename = ""; /* Normalize NULL to "" */
+ fd = 0;
+ } else {
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ archive_set_error(a, errno,
+ "Failed to open '%s'", filename);
+ return (ARCHIVE_FATAL);
+ }
}
if (fstat(fd, &st) != 0) {
archive_set_error(a, errno, "Can't stat '%s'", filename);
return (ARCHIVE_FATAL);
}
- mine = (struct read_file_data *)malloc(sizeof(*mine) + strlen(filename));
+ mine = (struct read_file_data *)calloc(1,
+ sizeof(*mine) + strlen(filename));
b = malloc(block_size);
if (mine == NULL || b == NULL) {
archive_set_error(a, ENOMEM, "No memory");
if (S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
/*
- * Skip is a performance optimization for anything
- * that supports lseek(). Generally, that only
- * includes regular files and possibly raw disk
- * devices, but there's no good portable way to detect
- * raw disks.
+ * Enabling skip here is a performance optimization
+ * for anything that supports lseek(). On FreeBSD
+ * (and probably many other systems), only regular
+ * files and raw disk devices support lseek() (on
+ * other input types, lseek() returns success but
+ * doesn't actually change the file pointer, which
+ * just completely screws up the position-tracking
+ * logic). In addition, I've yet to find a portable
+ * way to determine if a device is a raw disk device.
+ * So I don't see a way to do much better than to only
+ * enable this optimization for regular files.
*/
mine->can_skip = 1;
- } else
- mine->can_skip = 0;
+ }
return (archive_read_open2(a, mine,
NULL, file_read, file_skip, file_close));
}
*buff = mine->buffer;
bytes_read = read(mine->fd, mine->buffer, mine->block_size);
if (bytes_read < 0) {
- archive_set_error(a, errno, "Error reading '%s'",
- mine->filename);
+ if (mine->filename[0] == '\0')
+ archive_set_error(a, errno, "Error reading stdin");
+ else
+ archive_set_error(a, errno, "Error reading '%s'",
+ mine->filename);
}
return (bytes_read);
}
* likely caused by a programmer error (too large request)
* or a corrupted archive file.
*/
- archive_set_error(a, errno, "Error seeking in '%s'",
- mine->filename);
+ if (mine->filename[0] == '\0')
+ /*
+ * Should never get here, since lseek() on stdin ought
+ * to return an ESPIPE error.
+ */
+ archive_set_error(a, errno, "Error seeking in stdin");
+ else
+ archive_set_error(a, errno, "Error seeking in '%s'",
+ mine->filename);
return (-1);
}
return (new_offset - old_offset);
mine->block_size);
} while (bytesRead > 0);
}
- close(mine->fd);
+ /* If a named file was opened, then it needs to be closed. */
+ if (mine->filename[0] != '\0')
+ close(mine->fd);
}
free(mine->buffer);
free(mine);
* "as much as possible." Clients who need specific
* compression should enable those individually so they can
* verify the level of support. */
+ /* Clear any warning messages set by the above functions. */
+ archive_clear_error(a);
return (ARCHIVE_OK);
}
if (p == NULL)
return (0);
len += ((int)p[len + 1] << 8) | (int)p[len];
+ len += 2;
}
/* Null-terminated optional filename. */
*/
if (self->code == ARCHIVE_COMPRESSION_XZ)
ret = lzma_stream_decoder(&(state->stream),
- (1U << 23) + (1U << 21),/* memlimit */
+ (1U << 30),/* memlimit */
LZMA_CONCATENATED);
else
ret = lzma_alone_decoder(&(state->stream),
- (1U << 23) + (1U << 21));/* memlimit */
+ (1U << 30));/* memlimit */
if (ret == LZMA_OK)
return (ARCHIVE_OK);
if (bytes_read == 0)
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Truncated input file");
- if (buff == NULL)
+ if (*buff == NULL)
return (ARCHIVE_FATAL);
if (bytes_read > iso9660->entry_bytes_remaining)
bytes_read = iso9660->entry_bytes_remaining;
if (mtree->buff == NULL) {
archive_set_error(&a->archive, ENOMEM,
"Can't allocate memory");
+ return (ARCHIVE_FATAL);
}
- return (ARCHIVE_FATAL);
}
*buff = mtree->buff;
wchar_t *pax_entry;
size_t pax_entry_length;
int header_recursion_depth;
- off_t entry_bytes_remaining;
- off_t entry_offset;
- off_t entry_padding;
- off_t realsize;
+ int64_t entry_bytes_remaining;
+ int64_t entry_offset;
+ int64_t entry_padding;
+ int64_t realsize;
struct sparse_block *sparse_list;
struct sparse_block *sparse_last;
int64_t sparse_offset;
static int
archive_read_format_tar_skip(struct archive_read *a)
{
- off_t bytes_skipped;
+ int64_t bytes_skipped;
struct tar* tar;
tar = (struct tar *)(a->format->data);
* re-using the ones off the disk. That way, the 18-bit c_ino
* field only limits the number of files in the archive.
*/
- if (archive_entry_ino(entry) > 0777777) {
- archive_set_error(&a->archive, ERANGE, "large inode number truncated");
+ if ((int)archive_entry_ino(entry) > 0777777) {
+ archive_set_error(&a->archive, ERANGE,
+ "large inode number truncated");
ret = ARCHIVE_WARN;
}