blob: 405a4c55b9edb8eeeb1e677fcf2101b5cc105edf [file] [log] [blame]
API Plans
=========
Encryption
----------
* struct zip *zip_open_encrypted(const char *path, int flags, const char *password, int *errorp);
* int zip_set_encryption(struct zip *archive, zip_uint64_t idx, zip_uint16_t method, const char *password);
* void zip_set_archive_encryption(struct zip *archive, zip_uint16_t method, const char *password);
Prefixes
--------
For example for adding extractors for self-extracting zip archives.
* zip_set_archive_prefix(struct zip *za, const zip_uint8_t *data, zip_uint64_t length);
* const zip_uint8_t *zip_get_archive_prefix(struct zip *za, zip_uint64_t *lengthp);
Progress Callback
-----------------
Register callback; will be called from zip_close() after each file has been processed.
typedef void (*zip_progress_callback_t)(double);
void zip_register_progress_callback(zip_t *, zip_progress_callback_t);
API Issues
==========
! D zip_get_archive_comment has int *lenp argument. Cleaner would be zip_uint32_t *.
rename and fix. which other functions for naming consistency?
! D rename remaining zip_XXX_{file,archive}_* to zip_{file,archive}_XXX_*?
* compression/crypt implementations: how to set error code on failure
* compression/crypt error messages a la ZIP_ER_ZLIB (no detailed info passing)
* check arguments for every entry point into libzip
Features
========
* function to copy file from one archive to another
* set O_CLOEXEC flag after fopen and mkstemp
* Windows specific I/O source (to be written by a Windows expert)
* I/O methods
* support streaming output (creating new archive to e.g. stdout)
* add functions to:
. read/set ASCII file flag? (wiz: more general options?)
* zip_commit (to finish changes without closing archive)
* add custom compression function support
* zip_fseek
* zip_source_zip: allow rewinding
* zipcmp: add option for file content comparison
* zipcmp: compare bit flags if paranoid
* zipcmp: compare external attributes/opsys if paranoid
* zipcmp: compare last_mod if paranoid (or with separate flag?)
* consistency
. for stored files, test compressed = uncompressed
. data descriptor
. local headers come before central dir
- support for old compression methods?????
Bugs
====
* support InfoZIP encryption header extension
* embed stripped down old zlib for torrentzip
! ensure that nentries is small enough not to cause overflow (size_t for entry, uint64 for CD on disk)
* Xcode 32bit build uses 64bit config.h
* fix OpenSUSE i686 regression failures
* fix open_filename_duplicate_consistency.test to fail
* split zip archive torrentzip state from user requested torrentzip state
* check for limits imposed by format (central dir size, file size, extra fields, ...)
* _zip_u2d_time: handle localtime(3) failure
* POSIX: zip_open: check whether file can be created and fail if not
* fix inconsistent usage of valid flags (not checked in many places)
* cdr == NULL -> ER_NOENT vs. idx > cdir->nentry -> ER_INVAL inconsistent (still there?)
* torrentzip broken on NetBSD/amd64 6.99
* torrentzip: check behaviour of files with empty name (size 0; file size > 0)
Cleanup
=======
* move compat refs from zipint.h to own file, and include that in zipint.h and src
* get rid of zip_get_{compression,encryption}_implementation
* use zip_*int*_t internally
* clean up lint(1) warnings?
Test Case Issues
================
* add test case for ZIP_CM_DEFAULT -> stored (edge cases)
* add test case to change values for newly added files (name, compression method, comment, mtime, . . .)
* replace Text::Diff with own implementation
* use zipcmp -p?
* zip_open file less than EOCDLEN bytes long
* test calls against old API
* run regression tests also from CMake framework
* rename file to dir/ and vice versa (fails)
* fix comment test to be newline insensitive
* check if http://bugs.python.org/issue20078 provides ideas for new tests
* (add, replace)
add to empty zip
add to existing zip
add w/ existing file name [E]
replace ok
replace w/ illegal index [E]
replace w/ deleted name [E]
unchange added/replaced file
* (close)
copy zip file
open copy
rename, delete, replace, add w/ new name, add w/ deleted name
close
zipcmp copy expected
remove copy
* (error_get)
* (error_get_sys_type)
* (error_to_str)
* (extra_fields)
* (file_error_get)
* (file_strerror)
* (replace)
* (source_buffer)
* (source_file)
* (source_filep)
* (source_free)
* (source_function)
* (source_zip)
* (strerror)
* (unchange)
* (unchange_all)
* open(ZIP_RDONLY)
* I/O abstraction layer
zip_open_from_source
* read two zip entries interleaved
I/O Methods
===========
One major headache for libzip portability (especially to Windows) is
I/O, i.e. reading and writing from the file system. Also, there
have been requests to open zip archives from a memory buffer. To
address these issues, we'll introduce an I/O abstraction layer.
We'll reuse zip_source, since it already provides support for
the reading part, adding high level abstraction of the additional
operations needed. This way, newly written zip_sources can be used
both for adding files into an archive as well as for accessing archives
themselves.
Specifically, we'll add these commands:
ZIP_SOURCE_BEGIN_WRITE
Prepare for writing. The written data will replace all
original data. The file position is reset to 0. (On POSIX
systems, this will create a temporary file and open it for
writing.)
ZIP_SOURCE_WRITE
Write bytes of data, a la fwrite(3) (does not need to know
anything about the zip archive structure).
ZIP_SOURCE_COMMIT_WRITE
Used after all data has been written successfully. (On
POSIX systems, this will replace the original file with
the temporary file, adapting permissions etc.)
ZIP_SOURCE_REMOVE
Zip archive is empty. Is responsible for removing file, if
appropriate.
ZIP_SOURCE_ROLLBACK_WRITE
Used to reset the zip archive to the previous state (e.g.
because writing failed) to restore original data if possible;
return an error otherwise. (On POSIX systems, this will
delete the temporary file.)
ZIP_SOURCE_SEEK
Set position for next read or write, a la fseek(3).
ZIP_SOURCE_TELL
Report current position, a la ftell(3).
ZIP_SOURCE_SUPPORTS
Query which commands are supported for this stream. If a
file cannot be written to, this will report ZIP_SOURCE_BEGIN_WRITE
as not supported, even if the source type would support
write. (This is used in zip_open to set global flags like
ZIP_AFL_RDONLY.)
We'll provide a zip_open variant that takes a zip_source argument
used for reading/writing archives. Using an enhanced version of
zip_source_buffer, this can be used to read zip archives from memory.
zip_open itself will create a source from the file using a
port-specific default implementation (POSIX vs. Windows vs. ...).
Once the details are finalized, we'll ask for volunteers for writing
a Windows specific implementation.
zip_source_XXX -> [I]
[I] -> OPEN -> [R]
[R] -> (SEEK|TELL|READ|STAT)* -> [R]
[R] -> CLOSE -> [I]
[I] -> BEGIN_WRITE -> [W]
[W] -> (SEEK|TELL|WRITE)* -> [W]
[W] -> (COMMIT_WRITE|ROLLBACK_WRITE) -> [I]
[IR] -> REMOVE -> [X]
[I] -> STAT -> [I]
(no state change in case of error)
always:
* -> ERROR -> \1
* -> SUPPORTS -> \1
* -> FREE
[-,-]
[R,-]
[-,W]
[R,W]
zip_source_XXX -> [-,-]
[-,y] -> OPEN -> [R,y]
[R,y] -> (SEEK|TELL|READ|STAT)* -> [R,y]
[R,y] -> CLOSE -> [-,y]
[x,-] -> BEGIN_WRITE -> [x,W]
[x,W] -> (SEEK_WRITE|TELL_WRITE|WRITE)* -> [x,W]
[x,W] -> (COMMIT_WRITE|ROLLBACK_WRITE) -> [x,-]
[x,y] -> REMOVE -> [-,-]
[x,y] -> STAT -> [x,y]
[x,y] -> ERROR -> [x,y]
[x,y] -> SUPPORTS -> [x,y]
[x,y] -> FREE
- document: zip_source_write: length can't be > ZIP_INT64_MAX
- document: ZIP_SOURCE_CLOSE implementation can't return error
- check for INT_MAX, UINT_MAX
plan for merge:
after merge:
- direct reference to source and from upper layer are equivalent: only close/free if all are gone.
- only allow multiple upper layers for sources that support seek
- cache supported state in struct zip_source and check in _zip_source_call before calling
D re-implement fix for OS X sandboxing (zip_archive_set_tempdir).
- find out FSEEK_MAX/FTELL_MAX and use it
- adapt man pages
- document ZIP_RDONLY
- keep error codes in man pages in sync
- document ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), NULL : (type *)(data))
- document new functions
** zip_error_t *zip_get_error(zip_t *);
** int zip_error_code_zip(const zip_error_t *);
** int zip_error_code_system(const zip_error_t *);
** void zip_error_fini(zip_error_t *);
** void zip_error_init(zip_error_t *);
** void zip_error_set(zip_error_t *, int, int);
** const char *zip_error_strerror(zip_error_t *);
** int zip_error_system_type(const zip_error_t *);
** zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t);
** zip_error_t *zip_file_get_error(zip_file_t *);
** zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *);
** zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *);
** int zip_source_close(zip_source_t *);
** zip_error_t *zip_source_error(zip_source_t *src);
** zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
** zip_source_t *zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *);
** zip_source_t *zip_source_function_create(zip_source_callback, void *, zip_error_t *);
** int zip_source_is_deleted(zip_source_t *);
** void zip_source_keep(zip_source_t *);
** zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...);
** int zip_source_open(zip_source_t *);
** zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t);
** int zip_source_stat(zip_source_t *, zip_stat_t *);
- document deprecations
** int zip_error_get_sys_type(int); /* use zip_error_system_type */
** void zip_error_get(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
** void zip_file_error_get(zip_file_t *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */