diff options
author | kientzle <kientzle@FreeBSD.org> | 2006-09-05 05:59:46 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2006-09-05 05:59:46 +0000 |
commit | b70eb6239fc6c06b97d3bc78e4e84e977147c7b3 (patch) | |
tree | e9e5403d1ee6b34e31b33c6371840038b4f4874e | |
parent | 0eaa9fd1daf7600660f11f644e7adf331290e11d (diff) | |
download | FreeBSD-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/Makefile | 4 | ||||
-rw-r--r-- | lib/libarchive/archive.h.in | 13 | ||||
-rw-r--r-- | lib/libarchive/archive_private.h | 2 | ||||
-rw-r--r-- | lib/libarchive/archive_read.3 | 51 | ||||
-rw-r--r-- | lib/libarchive/archive_read.c | 31 | ||||
-rw-r--r-- | lib/libarchive/archive_read_extract.c | 5 | ||||
-rw-r--r-- | lib/libarchive/archive_read_open_file.c | 2 | ||||
-rw-r--r-- | lib/libarchive/archive_read_open_filename.c | 2 | ||||
-rw-r--r-- | lib/libarchive/archive_read_support_format_tar.c | 4 | ||||
-rw-r--r-- | lib/libarchive/archive_write.c | 54 |
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); } /* |