summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2006-09-05 05:59:46 +0000
committerkientzle <kientzle@FreeBSD.org>2006-09-05 05:59:46 +0000
commitb70eb6239fc6c06b97d3bc78e4e84e977147c7b3 (patch)
treee9e5403d1ee6b34e31b33c6371840038b4f4874e
parent0eaa9fd1daf7600660f11f644e7adf331290e11d (diff)
downloadFreeBSD-src-b70eb6239fc6c06b97d3bc78e4e84e977147c7b3.zip
FreeBSD-src-b70eb6239fc6c06b97d3bc78e4e84e977147c7b3.tar.gz
Some minor corrections:
* Expose functions for setting the "skip file" dev/ino information * Expose functions for setting/querying the block size on reads * Correctly propagate errors out of archive_read_close/archive_write_close * Update manpage with information about new functions
-rw-r--r--lib/libarchive/Makefile4
-rw-r--r--lib/libarchive/archive.h.in13
-rw-r--r--lib/libarchive/archive_private.h2
-rw-r--r--lib/libarchive/archive_read.351
-rw-r--r--lib/libarchive/archive_read.c31
-rw-r--r--lib/libarchive/archive_read_extract.c5
-rw-r--r--lib/libarchive/archive_read_open_file.c2
-rw-r--r--lib/libarchive/archive_read_open_filename.c2
-rw-r--r--lib/libarchive/archive_read_support_format_tar.c4
-rw-r--r--lib/libarchive/archive_write.c54
10 files changed, 127 insertions, 41 deletions
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 718ebea..df3612b 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -35,12 +35,14 @@ WARNS?= 6
INCS= archive.h archive_entry.h
# Build archive.h from archive.h.in by substituting version information.
+# Note: FreeBSD has inttypes.h, so enable that include in archive.h.in
archive.h: archive.h.in Makefile
cat ${.CURDIR}/archive.h.in | \
sed 's/@VERSION@/${VERSION}/g' | \
sed 's/@SHLIB_MAJOR@/${SHLIB_MAJOR}/g' | \
sed 's/@ARCHIVE_API_MAJOR@/${ARCHIVE_API_MAJOR}/g' | \
sed 's/@ARCHIVE_API_MINOR@/${ARCHIVE_API_MINOR}/g' | \
+ sed 's|@ARCHIVE_H_INCLUDE_INTTYPES_H@|#include <inttypes.h> /* For int64_t */|g' | \
cat > archive.h
# archive.h needs to be cleaned
@@ -152,10 +154,12 @@ MLINKS+= archive_read.3 archive_read_data_into_fd.3
MLINKS+= archive_read.3 archive_read_data_skip.3
MLINKS+= archive_read.3 archive_read_extract.3
MLINKS+= archive_read.3 archive_read_extract_set_progress_callback.3
+MLINKS+= archive_read.3 archive_read_extract_set_skip_file.3
MLINKS+= archive_read.3 archive_read_finish.3
MLINKS+= archive_read.3 archive_read_new.3
MLINKS+= archive_read.3 archive_read_next_header.3
MLINKS+= archive_read.3 archive_read_open.3
+MLINKS+= archive_read.3 archive_read_open2.3
MLINKS+= archive_read.3 archive_read_open_fd.3
MLINKS+= archive_read.3 archive_read_open_file.3
MLINKS+= archive_read.3 archive_read_set_bytes_per_block.3
diff --git a/lib/libarchive/archive.h.in b/lib/libarchive/archive.h.in
index 2ff9a3a..4603f44 100644
--- a/lib/libarchive/archive.h.in
+++ b/lib/libarchive/archive.h.in
@@ -36,7 +36,7 @@
*/
#include <sys/types.h> /* Linux requires this for off_t */
-#include <inttypes.h> /* For int64_t */
+@ARCHIVE_H_INCLUDE_INTTYPES_H@
#include <unistd.h> /* For ssize_t and size_t */
#ifdef __cplusplus
@@ -267,6 +267,11 @@ int archive_read_extract(struct archive *, struct archive_entry *,
void archive_read_extract_set_progress_callback(struct archive *,
void (*_progress_func)(void *), void *_user_data);
+/* Record the dev/ino of a file that will not be written. This is
+ * generally set to the dev/ino of the archive being read. */
+void archive_read_extract_set_skip_file(struct archive *,
+ dev_t, ino_t);
+
/* Close the file and release most resources. */
int archive_read_close(struct archive *);
/* Release all resources and destroy the object. */
@@ -291,9 +296,15 @@ void archive_read_finish(struct archive *);
struct archive *archive_write_new(void);
int archive_write_set_bytes_per_block(struct archive *,
int bytes_per_block);
+int archive_write_get_bytes_per_block(struct archive *);
/* XXX This is badly misnamed; suggestions appreciated. XXX */
int archive_write_set_bytes_in_last_block(struct archive *,
int bytes_in_last_block);
+int archive_write_get_bytes_in_last_block(struct archive *);
+
+/* The dev/ino of a file that won't be archived. This is used
+ * to avoid recursively adding an archive to itself. */
+int archive_write_set_skip_file(struct archive *, dev_t, ino_t);
int archive_write_set_compression_bzip2(struct archive *);
int archive_write_set_compression_gzip(struct archive *);
diff --git a/lib/libarchive/archive_private.h b/lib/libarchive/archive_private.h
index 419e0f7..9e02856 100644
--- a/lib/libarchive/archive_private.h
+++ b/lib/libarchive/archive_private.h
@@ -191,7 +191,7 @@ struct archive {
struct extract *extract;
void (*extract_progress)(void *);
void *extract_progress_user_data;
- void (*cleanup_archive_extract)(struct archive *);
+ int (*cleanup_archive_extract)(struct archive *);
int archive_error_number;
const char *error;
diff --git a/lib/libarchive/archive_read.3 b/lib/libarchive/archive_read.3
index 1575c7b..ec9ae3d 100644
--- a/lib/libarchive/archive_read.3
+++ b/lib/libarchive/archive_read.3
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2003-2005 Tim Kientzle
+.\" Copyright (c) 2003-2006 Tim Kientzle
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 8, 2005
+.Dd August 19, 2006
.Dt archive_read 3
.Os
.Sh NAME
@@ -41,6 +41,7 @@
.Nm archive_read_support_format_tar ,
.Nm archive_read_support_format_zip ,
.Nm archive_read_open ,
+.Nm archive_read_open2 ,
.Nm archive_read_open_fd ,
.Nm archive_read_open_file ,
.Nm archive_read_next_header ,
@@ -83,6 +84,8 @@
.Ft int
.Fn archive_read_open "struct archive *" "void *client_data" "archive_open_callback *" "archive_read_callback *" "archive_close_callback *"
.Ft int
+.Fn archive_read_open2 "struct archive *" "void *client_data" "archive_open_callback *" "archive_read_callback *" "archive_skip_callback *" "archive_close_callback *"
+.Ft int
.Fn archive_read_open_fd "struct archive *" "int fd" "size_t block_size"
.Ft int
.Fn archive_read_open_file "struct archive *" "const char *filename" "size_t block_size"
@@ -146,9 +149,14 @@ For convenience,
enables support for all available formats.
Note that there is no default.
.It Fn archive_read_open
+The same as
+.Fn archive_read_open2 ,
+except that the skip callback is assumed to be
+.Dv NULL .
+.It Fn archive_read_open2
Freeze the settings, open the archive, and prepare for reading entries.
This is the most generic version of this call, which accepts
-three callback functions.
+four callback functions.
Most clients will want to use
.Fn archive_read_open_file
or
@@ -156,26 +164,20 @@ or
instead.
The library invokes the client-provided functions to obtain
raw bytes from the archive.
-Note: The API permits a decompression method to fork and invoke the
-callbacks from another process.
-Although none of the current decompression methods use this technique,
-future decompression methods may utilize this technique.
-If the decompressor forks, it will ensure that the open and close
-callbacks are invoked within the same process as the read callback.
-In particular, clients should not attempt to use shared variables to
-communicate between the open/read/close callbacks and the mainline code.
.It Fn archive_read_open_fd
Like
.Fn archive_read_open ,
except that it accepts a file descriptor and block size rather than
-a trio of function pointers.
+a set of function pointers.
Note that the file descriptor will not be automatically closed at
end-of-archive.
+This function is safe for use with tape drives or other blocked devices.
.It Fn archive_read_open_file
Like
.Fn archive_read_open ,
except that it accepts a simple filename and a block size.
A NULL filename represents standard input.
+This function is safe for use with tape drives or other blocked devices.
.It Fn archive_read_next_header
Read the header for the next entry and return a pointer to
a
@@ -212,6 +214,12 @@ Note that the client is responsible for sizing the buffer appropriately.
A convenience function that repeatedly calls
.Fn archive_read_data_block
to copy the entire entry to the provided file descriptor.
+.It Fn archive_read_extract_set_skip_file
+This function records the device and inode numbers
+of a file that should not be restored.
+This is a convenience that prevents
+.Fn archive_read_extract
+from restoring a file over the archive itself.
.It Fn archive_read_extract
A convenience function that recreates the specified object on
disk and reads the entry data into that object.
@@ -298,6 +306,9 @@ The callback functions must match the following prototypes:
.Fn archive_read_callback "struct archive *" "void *client_data" "const void **buffer"
.It
.Ft typedef int
+.Fn archive_skip_callback "struct archive *" "void *client_data" "size_t request"
+.It
+.Ft typedef int
.Fn archive_open_callback "struct archive *" "void *client_data"
.It
.Ft typedef int
@@ -333,6 +344,22 @@ On error, the read callback should invoke
to register an error code and message and
return -1.
.Pp
+The skip callback is invoked when the
+library wants to ignore a block of data.
+The return value is the number of bytes actually
+skipped, which may differ from the request.
+If the callback cannot skip data, it should return
+zero.
+If the skip callback is not provided (the
+function pointer is
+.Dv NULL ),
+the library will invoke the read function
+instead and simply discard the result.
+A skip callback can provide significant
+performance gains when reading uncompressed
+archives from slow disk drives or other media
+that can skip quickly.
+.Pp
The close callback is invoked by archive_close when
the archive processing is complete.
The callback should return
diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c
index 46ccb59..f7f2204 100644
--- a/lib/libarchive/archive_read.c
+++ b/lib/libarchive/archive_read.c
@@ -88,19 +88,16 @@ archive_read_new(void)
}
/*
- * Set the block size.
+ * Record the do-not-extract-to file. This belongs in archive_read_extract.c.
*/
-/*
-int
-archive_read_set_bytes_per_block(struct archive *a, int bytes_per_block)
+void
+archive_read_extract_set_skip_file(struct archive *a, dev_t d, ino_t i)
{
- __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_set_bytes_per_block");
- if (bytes_per_block < 1)
- bytes_per_block = 1;
- a->bytes_per_block = bytes_per_block;
- return (0);
+ __archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_extract_set_skip_file");
+ a->skip_file_dev = d;
+ a->skip_file_ino = i;
}
-*/
+
/*
* Open the archive
@@ -504,19 +501,25 @@ archive_read_data_block(struct archive *a,
int
archive_read_close(struct archive *a)
{
+ int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
+
__archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_close");
a->state = ARCHIVE_STATE_CLOSED;
/* Call cleanup functions registered by optional components. */
if (a->cleanup_archive_extract != NULL)
- (a->cleanup_archive_extract)(a);
+ r = (a->cleanup_archive_extract)(a);
/* TODO: Finish the format processing. */
/* Close the input machinery. */
- if (a->compression_finish != NULL)
- (a->compression_finish)(a);
- return (ARCHIVE_OK);
+ if (a->compression_finish != NULL) {
+ r1 = (a->compression_finish)(a);
+ if (r1 < r)
+ r = r1;
+ }
+
+ return (r);
}
/*
diff --git a/lib/libarchive/archive_read_extract.c b/lib/libarchive/archive_read_extract.c
index aedd392..badf4eb 100644
--- a/lib/libarchive/archive_read_extract.c
+++ b/lib/libarchive/archive_read_extract.c
@@ -110,7 +110,7 @@ struct extract {
*/
#define SECURE_DIR_MODE 0700
-static void archive_extract_cleanup(struct archive *);
+static int archive_extract_cleanup(struct archive *);
static int extract_block_device(struct archive *,
struct archive_entry *, int);
static int extract_char_device(struct archive *,
@@ -318,7 +318,7 @@ cleanup:
* name from archive_read_finish) reduces static link pollution, since
* applications that don't use this API won't get this file linked in.
*/
-static void
+static int
archive_extract_cleanup(struct archive *a)
{
struct fixup_entry *next, *p;
@@ -353,6 +353,7 @@ archive_extract_cleanup(struct archive *a)
archive_string_free(&extract->create_parent_dir);
free(a->extract);
a->extract = NULL;
+ return (ARCHIVE_OK);
}
/*
diff --git a/lib/libarchive/archive_read_open_file.c b/lib/libarchive/archive_read_open_file.c
index efdd438..598e19d 100644
--- a/lib/libarchive/archive_read_open_file.c
+++ b/lib/libarchive/archive_read_open_file.c
@@ -137,7 +137,7 @@ file_skip(struct archive *a, void *client_data, size_t request)
{
struct read_file_data *mine = client_data;
off_t old_offset, new_offset;
-
+
/* Reduce request to the next smallest multiple of block_size */
request = (request / mine->block_size) * mine->block_size;
/*
diff --git a/lib/libarchive/archive_read_open_filename.c b/lib/libarchive/archive_read_open_filename.c
index efdd438..598e19d 100644
--- a/lib/libarchive/archive_read_open_filename.c
+++ b/lib/libarchive/archive_read_open_filename.c
@@ -137,7 +137,7 @@ file_skip(struct archive *a, void *client_data, size_t request)
{
struct read_file_data *mine = client_data;
off_t old_offset, new_offset;
-
+
/* Reduce request to the next smallest multiple of block_size */
request = (request / mine->block_size) * mine->block_size;
/*
diff --git a/lib/libarchive/archive_read_support_format_tar.c b/lib/libarchive/archive_read_support_format_tar.c
index cc0b5ed..083f7cc 100644
--- a/lib/libarchive/archive_read_support_format_tar.c
+++ b/lib/libarchive/archive_read_support_format_tar.c
@@ -533,8 +533,8 @@ archive_read_format_tar_skip(struct archive *a)
const void *b; /* dummy variables */
size_t s;
off_t o;
-
-
+
+
tar = *(a->pformat_data);
if (a->compression_skip == NULL) {
while (r == ARCHIVE_OK)
diff --git a/lib/libarchive/archive_write.c b/lib/libarchive/archive_write.c
index 3a999ca..446bb69 100644
--- a/lib/libarchive/archive_write.c
+++ b/lib/libarchive/archive_write.c
@@ -88,7 +88,6 @@ archive_write_new(void)
return (a);
}
-
/*
* Set the block size. Returns 0 if successful.
*/
@@ -100,6 +99,15 @@ archive_write_set_bytes_per_block(struct archive *a, int bytes_per_block)
return (ARCHIVE_OK);
}
+/*
+ * Get the current block size. -1 if it has never been set.
+ */
+int
+archive_write_get_bytes_per_block(struct archive *a)
+{
+ __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_get_bytes_per_block");
+ return (a->bytes_per_block);
+}
/*
* Set the size for the last block.
@@ -113,6 +121,30 @@ archive_write_set_bytes_in_last_block(struct archive *a, int bytes)
return (ARCHIVE_OK);
}
+/*
+ * Return the value set above. -1 indicates it has not been set.
+ */
+int
+archive_write_get_bytes_in_last_block(struct archive *a)
+{
+ __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_get_bytes_in_last_block");
+ return (a->bytes_in_last_block);
+}
+
+
+/*
+ * dev/ino of a file to be rejected. Used to prevent adding
+ * an archive to itself recursively.
+ */
+int
+archive_write_set_skip_file(struct archive *a, dev_t d, ino_t i)
+{
+ __archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_set_skip_file");
+ a->skip_file_dev = d;
+ a->skip_file_ino = i;
+ return (ARCHIVE_OK);
+}
+
/*
* Open the archive using the current settings.
@@ -149,22 +181,30 @@ archive_write_open(struct archive *a, void *client_data,
int
archive_write_close(struct archive *a)
{
+ int r = ARCHIVE_OK, r1 = ARCHIVE_OK;
+
__archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_ANY, "archive_write_close");
/* Finish the last entry. */
if (a->state & ARCHIVE_STATE_DATA)
- ((a->format_finish_entry)(a));
+ r = ((a->format_finish_entry)(a));
/* Finish off the archive. */
- if (a->format_finish != NULL)
- (a->format_finish)(a);
+ if (a->format_finish != NULL) {
+ r1 = (a->format_finish)(a);
+ if (r1 < r)
+ r = r1;
+ }
/* Finish the compression and close the stream. */
- if (a->compression_finish != NULL)
- (a->compression_finish)(a);
+ if (a->compression_finish != NULL) {
+ r1 = (a->compression_finish)(a);
+ if (r1 < r)
+ r = r1;
+ }
a->state = ARCHIVE_STATE_CLOSED;
- return (ARCHIVE_OK);
+ return (r);
}
/*
OpenPOWER on IntegriCloud