1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

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
This commit is contained in:
Tim Kientzle 2006-09-05 05:59:46 +00:00
parent 473ff747a3
commit c12a9d810e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162028
10 changed files with 127 additions and 41 deletions

View File

@ -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

View File

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

View File

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

View File

@ -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

View File

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

View File

@ -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 @@ archive_read_extract(struct archive *a, struct archive_entry *entry, int flags)
* 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);
}
/*

View File

@ -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;
/*

View File

@ -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;
/*

View File

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

View File

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