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:
parent
473ff747a3
commit
c12a9d810e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162028
@ -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
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
/*
|
||||
|
@ -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;
|
||||
/*
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user