diff options
Diffstat (limited to 'lib/libarchive/archive_read_private.h')
-rw-r--r-- | lib/libarchive/archive_read_private.h | 138 |
1 files changed, 96 insertions, 42 deletions
diff --git a/lib/libarchive/archive_read_private.h b/lib/libarchive/archive_read_private.h index 4353983..da0b83f 100644 --- a/lib/libarchive/archive_read_private.h +++ b/lib/libarchive/archive_read_private.h @@ -32,6 +32,75 @@ #include "archive_string.h" #include "archive_private.h" +struct archive_read; +struct archive_reader; +struct archive_read_source; + +/* + * A "reader" knows how to provide blocks. That can include something + * that reads blocks from disk or socket or a transformation layer + * that reads blocks from another source and transforms them. This + * includes decompression and decryption filters. + * + * How bidding works: + * * The bid manager reads the first block from the current source. + * * It shows that block to each registered bidder. + * * The winning bidder is initialized (with the block and information + * about the source) + * * The winning bidder becomes the new source and the process repeats + * This ends only when no reader provides a non-zero bid. + */ +struct archive_reader { + /* Configuration data for the reader. */ + void *data; + /* Bidder is handed the initial block from its source. */ + int (*bid)(struct archive_reader *, const void *buff, size_t); + /* Init() is given the archive, upstream source, and the initial + * block above. It returns a populated source structure. */ + struct archive_read_source *(*init)(struct archive_read *, + struct archive_reader *, struct archive_read_source *source, + const void *, size_t); + /* Release the reader and any configuration data it allocated. */ + int (*free)(struct archive_reader *); +}; + +/* + * A "source" is an instance of a reader. This structure is + * allocated and initialized by the init() method of a reader + * above. + */ +struct archive_read_source { + /* Essentially all sources will need these values, so + * just declare them here. */ + struct archive_reader *reader; /* Reader that I'm an instance of. */ + struct archive_read_source *upstream; /* Who I get blocks from. */ + struct archive_read *archive; /* associated archive. */ + /* Return next block. */ + ssize_t (*read)(struct archive_read_source *, const void **); + /* Skip forward this many bytes. */ + int64_t (*skip)(struct archive_read_source *self, int64_t request); + /* Close (recursively) and free(self). */ + int (*close)(struct archive_read_source *self); + /* My private data. */ + void *data; +}; + +/* + * The client source is almost the same as an internal source. + * + * TODO: Make archive_read_source and archive_read_client identical so + * that users of the library can easily register their own + * transformation filters. This will probably break the API/ABI and + * so should be deferred until libarchive 3.0. + */ +struct archive_read_client { + archive_open_callback *opener; + archive_read_callback *reader; + archive_skip_callback *skipper; + archive_close_callback *closer; + void *data; +}; + struct archive_read { struct archive archive; @@ -50,46 +119,30 @@ struct archive_read { off_t read_data_output_offset; size_t read_data_remaining; - /* Callbacks to open/read/write/close archive stream. */ - archive_open_callback *client_opener; - archive_read_callback *client_reader; - archive_skip_callback *client_skipper; - archive_close_callback *client_closer; - void *client_data; + /* Callbacks to open/read/write/close client archive stream. */ + struct archive_read_client client; + + /* Registered readers. */ + struct archive_reader readers[8]; + + /* Source */ + struct archive_read_source *source; /* File offset of beginning of most recently-read header. */ off_t header_position; - /* - * Decompressors have a very specific lifecycle: - * public setup function initializes a slot in this table - * 'config' holds minimal configuration data - * bid() examines a block of data and returns a bid [1] - * init() is called for successful bidder - * 'data' is initialized by init() - * read() returns a pointer to the next block of data - * consume() indicates how much data is used - * skip() ignores bytes of data - * finish() cleans up and frees 'data' and 'config' - * - * [1] General guideline: bid the number of bits that you actually - * test, e.g., 16 if you test a 2-byte magic value. - */ - struct decompressor_t { - void *config; - void *data; - int (*bid)(const void *buff, size_t); - int (*init)(struct archive_read *, - const void *buff, size_t); - int (*finish)(struct archive_read *); - ssize_t (*read_ahead)(struct archive_read *, - const void **, size_t); - ssize_t (*consume)(struct archive_read *, size_t); - off_t (*skip)(struct archive_read *, off_t); - } decompressors[4]; - - /* Pointer to current decompressor. */ - struct decompressor_t *decompressor; + + /* Used by reblocking logic. */ + char *buffer; + size_t buffer_size; + char *next; /* Current read location. */ + size_t avail; /* Bytes in my buffer. */ + const void *client_buff; /* Client buffer information. */ + size_t client_total; + const char *client_next; + size_t client_avail; + char end_of_file; + char fatal; /* * Format detection is mostly the same as compression @@ -124,12 +177,13 @@ int __archive_read_register_format(struct archive_read *a, int (*read_data_skip)(struct archive_read *), int (*cleanup)(struct archive_read *)); -struct decompressor_t - *__archive_read_register_compression(struct archive_read *a, - int (*bid)(const void *, size_t), - int (*init)(struct archive_read *, const void *, size_t)); +struct archive_reader + *__archive_read_get_reader(struct archive_read *a); const void - *__archive_read_ahead(struct archive_read *, size_t); - + *__archive_read_ahead(struct archive_read *, size_t, ssize_t *); +ssize_t + __archive_read_consume(struct archive_read *, size_t); +int64_t + __archive_read_skip(struct archive_read *, int64_t); #endif |