### Install Configuration Files Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Installs the generated configuration and version files to the specified destination directory. ```cmake install( FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" DESTINATION "${CONFIG_INSTALL_DIR}" ) ``` -------------------------------- ### Ruby FFI Binding Example Source: https://github.com/kuba--/zip/blob/master/README.md Example of using the zip library in Ruby with the FFI gem. First, install the gem, then bind the library functions in your module. ```shell $ gem install ffi ``` ```ruby require 'ffi' module Zip extend FFI::Library ffi_lib "./libzip.#{::FFI::Platform::LIBSUFFIX}" attach_function :zip_open, [:string, :int, :char], :pointer attach_function :zip_close, [:pointer], :void attach_function :zip_entry_open, [:pointer, :string], :int attach_function :zip_entry_close, [:pointer], :void attach_function :zip_entry_write, [:pointer, :string, :int], :int end ptr = Zip.zip_open("/tmp/ruby.zip", 6, "w" ) status = Zip.zip_entry_open(ptr, "test") content = "test content" status = Zip.zip_entry_write(ptr, content, content.size()) Zip.zip_entry_close(ptr) Zip.zip_close(ptr) ``` -------------------------------- ### Install Header Files Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Installs the public header files for the zip library to the include directory. ```cmake install(FILES ${PROJECT_SOURCE_DIR}/src/zip.h DESTINATION ${INCLUDE_INSTALL_DIR}/zip) ``` -------------------------------- ### Go Binding Example Source: https://github.com/kuba--/zip/blob/master/README.md Example of using the zip library in Go via cgo. Requires the kuba--/c-go-zip third-party binding. ```go package main /* #cgo CFLAGS: -I../src #cgo LDFLAGS: -L. -lzip #include */ import "C" import "unsafe" func main() { path := C.CString("/tmp/go.zip") zip := C.zip_open(path, 6, 'w') entryname := C.CString("test") C.zip_entry_open(zip, entryname) content := "test content" buf := unsafe.Pointer(C.CString(content)) bufsize := C.size_t(len(content)) C.zip_entry_write(zip, buf, bufsize) C.zip_entry_close(zip) C.zip_close(zip) } ``` -------------------------------- ### Python CFFI Binding Example Source: https://github.com/kuba--/zip/blob/master/README.md Example of using the zip library in Python with the cffi package. Install cffi, then bind the library functions. ```shell $ pip install cffi ``` ```python import ctypes.util from cffi import FFI ffi = FFI() ffi.cdef(""" struct zip_t *zip_open(const char *zipname, int level, char mode); void zip_close(struct zip_t *zip); int zip_entry_open(struct zip_t *zip, const char *entryname); int zip_entry_close(struct zip_t *zip); int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize); """ ) Zip = ffi.dlopen(ctypes.util.find_library("zip")) ptr = Zip.zip_open("/tmp/python.zip", 6, 'w') status = Zip.zip_entry_open(ptr, "test") content = "test content" status = Zip.zip_entry_write(ptr, content, len(content)) Zip.zip_entry_close(ptr) Zip.zip_close(ptr) ``` -------------------------------- ### Install Build Tools Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Installs the zipcli and unzipcli executables to the bin directory if ZIP_BUILD_TOOLS is enabled. ```cmake install(TARGETS zipcli unzipcli RUNTIME DESTINATION bin) ``` -------------------------------- ### Set Installation Directories Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Defines installation directories for CMake configuration files and include headers. ```cmake set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") set(INCLUDE_INSTALL_DIR "include") ``` -------------------------------- ### Include Directories Configuration Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Sets up include directories for the zip library, making the 'src' directory available during build and the 'include' directory during installation. ```cmake target_include_directories(${PROJECT_NAME} PUBLIC $ $ ) ``` -------------------------------- ### Ring Zip Library Example Source: https://github.com/kuba--/zip/blob/master/README.md Example of using the zip library in Ring with the RingZip extension. This code demonstrates creating a zip file, adding entries, and writing content. ```ring load "ziplib.ring" new Zip { setFileName("myfile.zip") open("w") newEntry() { open("test.c") writefile("test.c") close() } close() } ``` -------------------------------- ### Install Project Targets Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Installs the main project targets (executables, libraries) to their respective runtime and library destinations. It also associates them with the export set. ```cmake install(TARGETS ${PROJECT_NAME} EXPORT ${TARGETS_EXPORT_NAME} RUNTIME DESTINATION bin ARCHIVE DESTINATION lib LIBRARY DESTINATION lib INCLUDES DESTINATION ${INCLUDE_INSTALL_DIR} ) ``` -------------------------------- ### Rust FFI Binding Example Source: https://github.com/kuba--/zip/blob/master/README.md Example of using the zip library in Rust via FFI. This code defines the necessary structs and external functions to interact with the C library. ```rust extern crate libc; use std::ffi::CString; #[repr(C)] pub struct Zip { _private: [u8; 0], } #[link(name = "zip")] extern "C" { fn zip_open(path: *const libc::c_char, level: libc::c_int, mode: libc::c_char) -> *mut Zip; fn zip_close(zip: *mut Zip) -> libc::c_void; fn zip_entry_open(zip: *mut Zip, entryname: *const libc::c_char) -> libc::c_int; fn zip_entry_close(zip: *mut Zip) -> libc::c_int; fn zip_entry_write( zip: *mut Zip, buf: *const libc::c_void, bufsize: libc::size_t, ) -> libc::c_int; } fn main() { let path = CString::new("/tmp/rust.zip").unwrap(); let mode: libc::c_char = 'w' as libc::c_char; let entryname = CString::new("test.txt").unwrap(); let content = "test content\0"; unsafe { let zip: *mut Zip = zip_open(path.as_ptr(), 5, mode); { zip_entry_open(zip, entryname.as_ptr()); { let buf = content.as_ptr() as *const libc::c_void; let bufsize = content.len() as libc::size_t; zip_entry_write(zip, buf, bufsize); } zip_entry_close(zip); } zip_close(zip); } } ``` -------------------------------- ### Install Fuzzing Targets Source: https://github.com/kuba--/zip/blob/master/fuzz/CMakeLists.txt Installs the fuzzing executables to the directory specified by the OUT environment variable. Issues a warning if OUT is not defined, preventing installation. ```cmake if (DEFINED ENV{OUT}) install(TARGETS fuzz_entry DESTINATION $ENV{OUT}) install(TARGETS fuzz_stream DESTINATION $ENV{OUT}) else () message(WARNING "Cannot install if $OUT is not defined!") endif () ``` -------------------------------- ### Create Zip Archive in D Source: https://github.com/kuba--/zip/blob/master/README.md This D code example illustrates creating a zip archive and writing data to an entry. It requires linking the zip library. ```shell $ dmd -L-lzip main.d ``` ```d extern(C) void* zip_open(const(char)* zipname, int level, char mode); extern(C) void zip_close(void* zip); extern(C) int zip_entry_open(void* zip, const(char)* entryname); extern(C) int zip_entry_close(void* zip); extern(C) int zip_entry_write(void* zip, const(void)* buf, size_t bufsize); void main() { void* zip = zip_open("/tmp/d.zip", 6, 'w'); scope(exit) zip_close(zip); zip_entry_open(zip, "test"); scope(exit) zip_entry_close(zip); string content = "test content"; zip_entry_write(zip, content.ptr, content.length); } ``` -------------------------------- ### Project and Module Setup Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Sets the minimum CMake version, project name, languages, and module path. It also enables verbose Makefiles for detailed build output. ```cmake cmake_minimum_required(VERSION 3.14) project(zip LANGUAGES C VERSION "0.3.14") set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) set(CMAKE_VERBOSE_MAKEFILE ON) ``` -------------------------------- ### Configure Package Configuration File Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Configures the main package configuration file from a template. The INSTALL_DESTINATION specifies where the file will be installed. ```cmake # Use variables: # * TARGETS_EXPORT_NAME # * PROJECT_NAME configure_package_config_file( "cmake/Config.cmake.in" "${PROJECT_CONFIG}" INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" ) ``` -------------------------------- ### Never FFI Binding Example Source: https://github.com/kuba--/zip/blob/master/README.md Example of using the zip library in Never with FFI. This code demonstrates opening a zip file, writing content to entries, and closing the zip archive. ```never extern "libzip.so" func zip_open(zipname: string, level: int, mode: char) -> c_ptr extern "libzip.so" func zip_close(zip: c_ptr) -> void extern "libzip.so" func zip_entry_open(zip: c_ptr, entryname: string) -> int extern "libzip.so" func zip_entry_close(zip: c_ptr) -> int extern "libzip.so" func zip_entry_write(zip: c_ptr, buf: string, bufsize: int) -> int extern "libzip.so" func zip_entry_fwrite(zip: c_ptr, filename: string) -> int func main() -> int { let content = "Test content" let zip = zip_open("/tmp/never.zip", 6, 'w'); zip_entry_open(zip, "test.file"); zip_entry_fwrite(zip, "/tmp/test.txt"); zip_entry_close(zip); zip_entry_open(zip, "test.content"); zip_entry_write(zip, content, length(content)); zip_entry_close(zip); zip_close(zip); 0 } ``` -------------------------------- ### Fuzzing Setup Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Configures fuzzing by adding a subdirectory if ZIP_BUILD_FUZZ is enabled and LIB_FUZZING_ENGINE environment variable is defined. Exits with an error if LIB_FUZZING_ENGINE is not set. ```cmake if (ZIP_BUILD_FUZZ) if (NOT DEFINED ENV{LIB_FUZZING_ENGINE}) message(FATAL_ERROR "LIB_FUZZING_ENGINE is not defined") endif() add_subdirectory(fuzz) endif() ``` -------------------------------- ### Install Exported Targets Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Installs the exported targets for the project, specifying a namespace and destination directory. This is crucial for package management. ```cmake install( EXPORT "${TARGETS_EXPORT_NAME}" NAMESPACE "${NAMESPACE}" DESTINATION "${CONFIG_INSTALL_DIR}" ) ``` -------------------------------- ### Apply clang-format to Source Files Source: https://github.com/kuba--/zip/blob/master/CONTRIBUTING.md Run this script to apply the LLVM style of clang-format to all C and H source files. Ensure you have clang-format installed and that the files are tracked by Git. ```sh for file in $(git ls-files | \ grep -E '\\.(c|h)$' | \ grep -v -- '#') do clang-format -i $file --style=LLVM done ``` -------------------------------- ### Example Usage of zip_extract Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/archive-operations.md Demonstrates how to use the zip_extract function with a custom callback to count extracted entries. The callback returns 0 to continue extraction or a negative value to abort. ```c static int on_extract(const char *filename, void *arg) { int *count = (int *)arg; printf("Extracted: %s\n", filename); (*count)++; return 0; // Continue } int main() { int extracted = 0; int result = zip_extract("archive.zip", "/tmp/output", on_extract, &extracted); if (result == 0) { printf("Successfully extracted %d entries\n", extracted); } else { printf("Extraction failed with error code: %d\n", result); } return 0; } ``` -------------------------------- ### ZIP64 Control Example Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Use 'w' - 64 (character value 55) to force standard ZIP format, ensuring compatibility with older ZIP readers. This is useful when the output file needs to be readable by all ZIP software. ```c // Force standard ZIP format (not ZIP64) struct zip_t *zip = zip_open("archive.zip", 6, 'w' - 64); // Now 'w' - 64 evaluates to char(55) // For compatibility with older ZIP readers // This ensures the output file can be read by all ZIP software ``` -------------------------------- ### Configure ZIP Library with Compiler Flags Source: https://github.com/kuba--/zip/blob/master/README.md Alternatively, use compiler flags to disable features. This example shows disabling deflate support. ```shell cc -DZIP_ENABLE_DEFLATE=0 -c zip.c ``` -------------------------------- ### Add Uninstall Target Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Configures and adds a custom 'uninstall' target to allow users to remove installed files. This uses a separate CMake script for uninstallation logic. ```cmake # uninstall target (https://gitlab.kitware.com/cmake/community/wikis/FAQ#can-i-do-make-uninstall-with-cmake) if(NOT TARGET uninstall) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake/cmake_uninstall.cmake) endif() ``` -------------------------------- ### Get CRC-32 Checksum of ZIP Entry Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the CRC-32 checksum for the current entry. This is useful for verifying data integrity. ```c unsigned int zip_entry_crc32(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "document.txt"); unsigned int crc = zip_entry_crc32(zip); printf("CRC-32: 0x%08X\n", crc); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Using Shared Library on Linux/Unix Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Compile and link your application with the shared zip library on Linux/Unix systems. Ensure include paths, library paths, and runtime library paths are correctly set. ```bash gcc -I/path/to/zip/src myapp.c -o myapp -L/path/to/build -lzip export LD_LIBRARY_PATH=/path/to/build:$LD_LIBRARY_PATH ./myapp ``` -------------------------------- ### Get Compressed Size of ZIP Entry Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the compressed size of the current entry in bytes. Useful for calculating compression ratios. ```c unsigned long long zip_entry_comp_size(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "file.bin"); unsigned long long compressed = zip_entry_comp_size(zip); unsigned long long uncompressed = zip_entry_size(zip); double ratio = (double)compressed / uncompressed * 100.0; printf("Compression ratio: %.2f%%\n", ratio); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Create Zip Archive from Files Source: https://github.com/kuba--/zip/blob/master/_autodocs/README.md Use this pattern to create a new zip archive and add multiple files to it. Ensure entries are opened and closed for each file added. ```c struct zip_t *zip = zip_open("output.zip", 6, 'w'); zip_entry_open(zip, "file1.txt"); zip_entry_fwrite(zip, "file1.txt"); zip_entry_close(zip); zip_entry_open(zip, "file2.dat"); zip_entry_fwrite(zip, "file2.dat"); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Build and Link Fuzzing Entry Target Source: https://github.com/kuba--/zip/blob/master/fuzz/CMakeLists.txt Creates an executable for the fuzzing entry point and links it with the project's library and the fuzzing engine. Assumes OSSFuzz environment variables are set. ```cmake add_executable(fuzz_entry fuzz_entry.c) target_link_libraries(fuzz_entry PRIVATE ${PROJECT_NAME} $ENV{LIB_FUZZING_ENGINE}) ``` -------------------------------- ### Using Shared Library on Windows (MSVC) Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Compile and link your application with the shared zip library on Windows using MSVC. Ensure the correct include and library paths are specified. ```batch cl /I.\src myapp.c /link .\build\zip.lib .\myapp.exe ``` -------------------------------- ### Get Uncompressed Entry Size (zip_entry_uncomp_size) Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the uncompressed size of the current ZIP entry. Useful for comparing uncompressed and compressed sizes. ```c unsigned long long zip_entry_uncomp_size(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "file.txt"); unsigned long long uncompressed = zip_entry_uncomp_size(zip); unsigned long long compressed = zip_entry_comp_size(zip); printf("Uncompressed: %llu, Compressed: %llu\n", uncompressed, compressed); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Get Uncompressed Entry Size (zip_entry_size) Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the uncompressed size of the current ZIP entry. This function is an alias for zip_entry_uncomp_size and returns 0 for directory entries. ```c unsigned long long zip_entry_size(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "largefile.bin"); unsigned long long size = zip_entry_size(zip); printf("Uncompressed size: %llu bytes\n", size); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Reading from an offset with a pre-allocated buffer Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-io.md Demonstrates how to read a specific number of bytes from a ZIP entry at a given offset into a pre-allocated buffer using `zip_entry_noallocreadwithoffset`. Ensure the buffer is large enough for the intended read size. ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); if (zip_entry_open(zip, "largefile.dat") == 0) { unsigned char buf[1024]; size_t offset = 512; size_t to_read = sizeof(buf); ssize_t nread = zip_entry_noallocreadwithoffset(zip, offset, to_read, buf); if (nread > 0) { printf("Read %zd bytes from offset %zu\n", nread, offset); } else if (nread < 0) { printf("Error: %zd\n", nread); } zip_entry_close(zip); } zip_close(zip); ``` -------------------------------- ### Compile on Linux/Unix Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Compile the library on Linux or Unix-like systems using GCC. This command creates an object file and then archives it into a static library. ```bash gcc -c -o zip.o src/zip.c -I src/ ar rcs libzip.a zip.o ``` -------------------------------- ### Get ZIP Entry Header Offset Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Use this function to retrieve the offset of the local header for the current entry. Ensure the ZIP archive and entry are opened before calling. ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "file.txt"); unsigned long long header_offset = zip_entry_header_offset(zip); printf("Local header offset: %llu\n", header_offset); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Open and Close a ZIP Archive Source: https://github.com/kuba--/zip/blob/master/_autodocs/types.md Demonstrates how to open a ZIP archive file in write mode and subsequently close it. Ensure proper error checking after opening. ```c struct zip_t *zip = zip_open("archive.zip", 6, 'w'); if (zip != NULL) { // Use the archive... zip_close(zip); } else { fprintf(stderr, "Failed to open archive\n"); } ``` -------------------------------- ### Create New Zip Archive Source: https://github.com/kuba--/zip/blob/master/README.md Opens a new zip archive with default compression. Use this to create a zip file from scratch. ```c struct zip_t *zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); { zip_entry_open(zip, "foo-1.txt"); { const char *buf = "Some data here...\0"; zip_entry_write(zip, buf, strlen(buf)); } zip_entry_close(zip); zip_entry_open(zip, "foo-2.txt"); { // merge 3 files into one entry and compress them on-the-fly. zip_entry_fwrite(zip, "foo-2.1.txt"); zip_entry_fwrite(zip, "foo-2.2.txt"); zip_entry_fwrite(zip, "foo-2.3.txt"); } zip_entry_close(zip); } zip_close(zip); ``` -------------------------------- ### Project Options Configuration Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Defines various build options for the zip project, including sanitizers, static PIC, documentation generation, fuzz targets, tools, and feature flags like inflate, deflate, symlink support, and stdio usage. ```cmake option(CMAKE_ENABLE_SANITIZERS "Enable zip sanitizers" OFF) option(ZIP_STATIC_PIC "Build static zip with PIC" ON) option(ZIP_BUILD_DOCS "Generate API documentation with Doxygen" OFF) option(ZIP_BUILD_FUZZ "Build fuzz targets" OFF) option(ZIP_BUILD_TOOLS "Build command-line tools (zipcli, unzipcli)" OFF) option(ZIP_ENABLE_INFLATE "Enable decompression / extraction support" ON) option(ZIP_ENABLE_DEFLATE "Enable compression / archive creation support" ON) option(ZIP_HAVE_SYMLINK "Enable symlink support during extraction" ON) option(MINIZ_NO_STDIO "Disable stdio usage in miniz" OFF) ``` -------------------------------- ### Get Central Directory Offset of ZIP Entry Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the byte offset of the current entry within the ZIP archive's central directory. This can be used for low-level archive manipulation. ```c unsigned long long zip_entry_dir_offset(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "file.txt"); unsigned long long offset = zip_entry_dir_offset(zip); printf("Central directory offset: %llu\n", offset); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Create Zip Archive in Pascal Source: https://github.com/kuba--/zip/blob/master/README.md This Pascal code demonstrates creating a zip archive and adding an entry. It uses ctypes and requires linking the zip library. ```pascal program main; {$linklib c} {$linklib zip} uses ctypes; function zip_open(zipname:Pchar; level:longint; mode:char):pointer;cdecl;external; procedure zip_close(zip:pointer);cdecl;external; function zip_entry_open(zip:pointer; entryname:Pchar):longint;cdecl;external; function zip_entry_close(zip:pointer):longint;cdecl;external; function zip_entry_write(zip:pointer; buf:pointer; bufsize:csize_t):longint;cdecl;external; const content: Pchar = 'test content'; var zip : pointer; begin zip := zip_open('/tmp/pascal.zip', 6, 'w'); zip_entry_open(zip, 'test'); zip_entry_write(zip, content, strlen(content)); zip_entry_close(zip); zip_close(zip); end. ``` -------------------------------- ### Get Human-Readable Error Message Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/utility-functions.md Converts a numeric error code into a human-readable string. Useful for debugging and user feedback when an operation fails. Returns NULL for unknown error codes. ```c const char *zip_strerror(int errnum); ``` -------------------------------- ### Get Total ZIP Entries Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/archive-operations.md Use `zip_entries_total` to retrieve the total number of entries within a ZIP archive. This count includes both files and directories. It can be used in conjunction with `zip_entry_openbyindex` for iterating through all entries. ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); ssize_t count = zip_entries_total(zip); if (count > 0) { printf("Archive contains %zd entries\n", count); for (size_t i = 0; i < count; ++i) { if (zip_entry_openbyindex(zip, i) == 0) { printf(" - %s\n", zip_entry_name(zip)); zip_entry_close(zip); } } } zip_close(zip); ``` -------------------------------- ### Configure ZIP Library with CMake Source: https://github.com/kuba--/zip/blob/master/README.md Use these CMake flags to customize the build. Disable features like deflate or inflate to reduce binary size. Symlink support is platform-dependent by default. ```shell cmake .. -DZIP_ENABLE_DEFLATE=OFF ``` ```shell cmake .. -DZIP_ENABLE_INFLATE=OFF ``` ```shell cmake .. -DZIP_HAVE_SYMLINK=OFF ``` -------------------------------- ### Entry Read with Size Checking Source: https://github.com/kuba--/zip/blob/master/_autodocs/errors.md This pattern demonstrates reading an entire entry into a pre-allocated buffer after checking its size. It includes checks for memory allocation and read errors. ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); if (zip == NULL) { fprintf(stderr, "Cannot open archive\n"); return EXIT_FAILURE; } if (zip_entry_open(zip, "largefile.bin") != 0) { fprintf(stderr, "Entry not found\n"); zip_close(zip); return EXIT_FAILURE; } unsigned long long size = zip_entry_size(zip); unsigned char *buf = malloc(size); if (buf == NULL) { fprintf(stderr, "Out of memory: cannot allocate %llu bytes\n", size); zip_entry_close(zip); zip_close(zip); return EXIT_FAILURE; } ssize_t nread = zip_entry_noallocread(zip, buf, size); if (nread < 0) { fprintf(stderr, "Read failed with code: %zd\n", nread); free(buf); zip_entry_close(zip); zip_close(zip); return EXIT_FAILURE; } printf("Successfully read %zd bytes\n", nread); free(buf); zip_entry_close(zip); zip_close(zip); return EXIT_SUCCESS; ``` -------------------------------- ### Open ZIP Stream with Error Reporting Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/stream-operations.md Use `zip_stream_openwitherror` to open a ZIP archive from a memory stream and get detailed error information. Ensure to check the return value and the `errnum` parameter for failure analysis. ```c int err; struct zip_t *zip = zip_stream_openwitherror(NULL, 0, 6, 'w', &err); if (zip == NULL) { fprintf(stderr, "Error: %s\n", zip_strerror(err)); return; } zip_stream_close(zip); ``` -------------------------------- ### Get ZIP Entry Index Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the numeric index of the currently open entry in a ZIP archive. The index is a non-negative value on success or a negative error code on failure. Ensure an entry is open before calling this function. ```c ssize_t zip_entry_index(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); zip_entry_open(zip, "file.txt"); ssize_t idx = zip_entry_index(zip); if (idx >= 0) { printf("Entry index: %zd\n", idx); } zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Compile on Windows (MinGW) Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Compile the library on Windows using MinGW. This process is similar to Linux/Unix but uses a MinGW-specific GCC compiler and archiver. ```bash x86_64-w64-mingw32-gcc -c -o zip.o src/zip.c -I src/ x86_64-w64-mingw32-ar rcs libzip.a zip.o ``` -------------------------------- ### Get ZIP Entry Name Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Retrieves the name of the currently open entry in a ZIP archive. The name is returned as stored in the archive, using forward slashes and without drive letters. This function is valid only while an entry is open. ```c const char *zip_entry_name(struct zip_t *zip); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); if (zip_entry_openbyindex(zip, 0) == 0) { const char *name = zip_entry_name(zip); if (name != NULL) { printf("First entry: %s\n", name); } zip_entry_close(zip); } zip_close(zip); ``` -------------------------------- ### Creating Archives Source: https://github.com/kuba--/zip/blob/master/_autodocs/INDEX.txt Illustrates the sequence of functions used to create a new ZIP archive. ```APIDOC ## Creating Archives ### Description This section outlines the typical function calls for creating a new ZIP archive. ### Functions - `zip_open()` with mode 'w' - `zip_stream_open()` with mode 'w' - `zip_entry_open()` - `zip_entry_write()` - `zip_entry_fwrite()` - `zip_entry_close()` - `zip_close()` or `zip_stream_close()` ``` -------------------------------- ### zip_entry_noallocreadwithoffset Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-io.md Reads a specified number of bytes from a ZIP entry, starting at a given offset, into a provided buffer. The read operation is clamped to the remaining bytes in the entry and does not allocate memory internally. It's suitable for reading specific chunks of data from large entries. ```APIDOC ## zip_entry_noallocreadwithoffset ### Description Extracts part of the current entry starting at an offset. ### Method Signature ```c ssize_t zip_entry_noallocreadwithoffset(struct zip_t *zip, size_t offset, size_t size, void *buf); ``` ### Parameters #### Parameters - **zip** (struct zip_t *) - Yes - Pointer to ZIP archive handler - **offset** (size_t) - Yes - Byte offset within the entry to start reading - **size** (size_t) - Yes - Maximum number of bytes to read - **buf** (void *) - Yes - Pointer to pre-allocated output buffer ### Return Type `ssize_t` — Number of bytes actually written to buffer, or negative error code on failure. Value is clamped to bytes remaining after offset. ### Availability Available when `ZIP_ENABLE_INFLATE` is 1 (enabled by default). ### Notes - Reads up to `size` bytes starting at `offset` into caller-owned buffer - The actual read count is clamped to remaining bytes; safe to pass size larger than remaining data - Returns error only if offset is past the end of the entry or on decompression failure - Each call iterates from the start of the entry (not resumable) ### Example ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); if (zip_entry_open(zip, "largefile.dat") == 0) { unsigned char buf[1024]; size_t offset = 512; size_t to_read = sizeof(buf); ssize_t nread = zip_entry_noallocreadwithoffset(zip, offset, to_read, buf); if (nread > 0) { printf("Read %zd bytes from offset %zu\n", nread, offset); } else if (nread < 0) { printf("Error: %zd\n", nread); } zip_entry_close(zip); } zip_close(zip); ``` ``` -------------------------------- ### Get ZIP Header Offset Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/archive-management.md Retrieves the byte offset of the ZIP header within a stream. This is particularly useful for ZIP archives embedded in other files. The function returns 0 on success and a negative error code on failure. The offset is written to the provided `uint64_t` pointer. ```c int zip_offset(struct zip_t *zip, uint64_t *offset); ``` ```c uint64_t header_offset; struct zip_t *zip = zip_open("archive.zip", 0, 'r'); if (zip_offset(zip, &header_offset) == 0) { printf("ZIP header offset: %llu\n", header_offset); } else { printf("Error getting offset\n"); } zip_close(zip); ``` -------------------------------- ### Create Password-Protected Zip Archive Source: https://github.com/kuba--/zip/blob/master/README.md Creates a new zip archive with traditional PKWARE encryption. A password must be provided to protect the archive. ```c struct zip_t *zip = zip_open_with_password("secret.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w', "password"); { zip_entry_open(zip, "secret-1.txt"); { const char *buf = "Classified data...\0"; zip_entry_write(zip, buf, strlen(buf)); } zip_entry_close(zip); } zip_close(zip); ``` -------------------------------- ### Open ZIP Entry for Reading or Writing Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-operations.md Opens or creates an entry in the ZIP archive. Use in write or append mode to add a new entry, or in read mode to open an existing one. Entry names are case-insensitive on Windows and case-sensitive on Unix by default. Must be followed by `zip_entry_close()`. ```c int zip_entry_open(struct zip_t *zip, const char *entryname); ``` ```c struct zip_t *zip = zip_open("archive.zip", 6, 'w'); if (zip_entry_open(zip, "document.txt") == 0) { zip_entry_write(zip, "Hello", 5); zip_entry_close(zip); } zip_close(zip); ``` -------------------------------- ### Open ZIP Archive with Password Protection Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/archive-management.md Use `zip_open_with_password` to create or open a ZIP archive with Traditional PKWARE Encryption. Provide a password for encryption during write mode or decryption during read mode. A NULL password disables encryption. ```c // Create password-protected archive struct zip_t *zip = zip_open_with_password("secret.zip", 6, 'w', "mypassword"); if (zip == NULL) { fprintf(stderr, "Failed to create encrypted archive\n"); return; } zip_entry_open(zip, "secret.txt"); zip_entry_write(zip, "classified", 10); zip_entry_close(zip); zip_close(zip); // Later: read password-protected archive zip = zip_open_with_password("secret.zip", 0, 'r', "mypassword"); if (zip == NULL) { fprintf(stderr, "Failed to open encrypted archive\n"); return; } // Extract entries... zip_close(zip); ``` -------------------------------- ### Write Package Version File Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Generates a basic package version file using CMakePackageConfigHelpers. Ensure the 'CMakePackageConfigHelpers' module is included. ```cmake include(CMakePackageConfigHelpers) # Note: PROJECT_VERSION is used as a VERSION write_basic_package_version_file( "${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion ) ``` -------------------------------- ### Create Zip Archive in Odin Source: https://github.com/kuba--/zip/blob/master/README.md This Odin code demonstrates creating a zip archive with an entry. It relies on a third-party binding for zip functionality. ```odin package main foreign import lib "system:zip" import "core:c" foreign lib { zip_open :: proc(zipname : cstring, level : c.int, mode : c.char) -> rawptr --- zip_close :: proc(zip : rawptr) --- zip_entry_open :: proc(zip : rawptr, entryname : cstring) -> c.int --- zip_entry_close :: proc(zip : rawptr) -> c.int --- zip_entry_write :: proc(zip : rawptr, buf : rawptr, bufsize : c.size_t) -> c.int --- } main :: proc() { zip_file := zip_open("odin.zip", 6, 'w') defer zip_close(zip_file) zip_entry_open(zip_file, "test") defer zip_entry_close(zip_file) content := "test content"; zip_entry_write(zip_file, &content, len(content)) } ``` -------------------------------- ### Production Server Configuration Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Use this CMake profile for production servers requiring full features, including deflate compression, inflate, and symlink support. Builds shared libraries. ```bash cmake \ -DZIP_ENABLE_DEFLATE=ON \ -DZIP_ENABLE_INFLATE=ON \ -DZIP_HAVE_SYMLINK=ON \ -DBUILD_SHARED_LIBS=true \ .. ``` -------------------------------- ### Set C Standard Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Sets the C standard to C90. ```cmake set(CMAKE_C_STANDARD 90) ``` -------------------------------- ### Shared Library Build Configuration Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Compile the zip library as a dynamic/shared library using CMake. This enables platform-specific definitions and export declarations for shared object usage. ```bash mkdir build cd build cmake -DBUILD_SHARED_LIBS=true .. cmake --build . ``` -------------------------------- ### Create Zip Archive in Nim Source: https://github.com/kuba--/zip/blob/master/README.md This Nim code snippet shows how to create a zip file and add content. It requires linking the zip library during compilation. ```shell $ nim c --passL:-lzip main.nim ``` ```nim proc zip_open(zipname: cstring, level: cint, mode: char): pointer {.importc.} proc zip_close(zip: pointer) {.importc.} proc zip_entry_open(zip: pointer, entryname: cstring): cint {.importc.} proc zip_entry_close(zip: pointer): cint {.importc.} proc zip_entry_write(zip: pointer, buf: pointer, bufsize: csize_t): cint {.importc.} when isMainModule: var zip = zip_open("/tmp/nim.zip", 6, 'w') discard zip_entry_open(zip, "test") let content: cstring = "test content"; discard zip_entry_write(zip, content, csize_t(len(content))) discard zip_entry_close(zip) zip_close(zip) ``` -------------------------------- ### Build zipcli and unzipcli Executables Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Builds zipcli and unzipcli command-line tools if ZIP_BUILD_TOOLS is enabled. Links them against the project library and sets C standard to C99. ```cmake add_executable(zipcli cmd/zipcli.c) target_link_libraries(zipcli ${PROJECT_NAME}) set_target_properties(zipcli PROPERTIES C_STANDARD 99) add_executable(unzipcli cmd/unzipcli.c) target_link_libraries(unzipcli ${PROJECT_NAME}) set_target_properties(unzipcli PROPERTIES C_STANDARD 99) ``` -------------------------------- ### Create Zip Archive in Zig Source: https://github.com/kuba--/zip/blob/master/README.md Use this snippet to create a zip archive and add entries using Zig. Ensure the zip library is linked during compilation. ```shell $ zig build-exe main.zig -lc -lzip ``` ```zig const c = @cImport({ @cInclude("zip.h"); }); pub fn main() void { var zip = c.zip_open("/tmp/zig.zip", 6, 'w'); defer c.zip_close(zip); _ = c.zip_entry_open(zip, "test"); defer _ = c.zip_entry_close(zip); const content = "test content"; _ = c.zip_entry_write(zip, content, content.len); } ``` -------------------------------- ### Minimal Create-Only Build Configuration Source: https://github.com/kuba--/zip/blob/master/_autodocs/configuration.md Configure CMake to disable INFLATE decompression and read/extract functions for create-only applications. This can reduce binary size by 40-50%. ```bash cmake -DZIP_ENABLE_INFLATE=OFF .. make ``` -------------------------------- ### Password-Protected Zip Archive Operations Source: https://github.com/kuba--/zip/blob/master/_autodocs/README.md Demonstrates creating a password-protected zip archive and subsequently reading from it using the correct password. Ensure the password is provided for both operations. ```c // Create with password struct zip_t *zip = zip_open_with_password("secret.zip", 6, 'w', "password123"); zip_entry_open(zip, "secret.txt"); zip_entry_write(zip, "classified", 10); zip_entry_close(zip); zip_close(zip); // Read with password zip = zip_open_with_password("secret.zip", 0, 'r', "password123"); zip_entry_open(zip, "secret.txt"); void *buf = NULL; size_t size = 0; zip_entry_read(zip, &buf, &size); printf("Secret: %.*s\n", (int)size, (char *)buf); free(buf); zip_entry_close(zip); zip_close(zip); ``` -------------------------------- ### Extract ZIP Entry to File Source: https://github.com/kuba--/zip/blob/master/_autodocs/api-reference/entry-io.md Use `zip_entry_fread` to decompress and write an entire ZIP entry directly to a specified file. This is efficient for large files as it avoids loading the content into memory. The output file will be created or truncated. ```c int zip_entry_fread(struct zip_t *zip, const char *filename); ``` ```c struct zip_t *zip = zip_open("archive.zip", 0, 'r'); if (zip_entry_open(zip, "document.pdf") == 0) { if (zip_entry_fread(zip, "/tmp/extracted_document.pdf") == 0) { printf("Successfully extracted document.pdf\n"); } else { printf("Error extracting document\n"); } zip_entry_close(zip); } zip_close(zip); ``` -------------------------------- ### Add Documentation Target Source: https://github.com/kuba--/zip/blob/master/CMakeLists.txt Conditionally adds a 'doc' target to generate API documentation using Doxygen if ZIP_BUILD_DOCS is enabled. Requires Doxygen to be found. ```cmake if(ZIP_BUILD_DOCS) find_package(Doxygen REQUIRED) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM) endif() ``` -------------------------------- ### Password-Protected Archive in Memory (Stream API) Source: https://github.com/kuba--/zip/blob/master/README.md Creates a password-protected zip archive in memory using the stream API and then reads it back. Both operations require the correct password. ```c char *outbuf = NULL; size_t outbufsize = 0; struct zip_t *zip = zip_stream_open_with_password(NULL, 0, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w', "password"); { zip_entry_open(zip, "secret-1.txt"); { const char *buf = "Classified data...\0"; zip_entry_write(zip, buf, strlen(buf)); } zip_entry_close(zip); zip_stream_copy(zip, (void **)&outbuf, &outbufsize); } zip_stream_close(zip); /* read it back */ void *readbuf = NULL; size_t readsize = 0; zip = zip_stream_open_with_password(outbuf, outbufsize, 0, 'r', "password"); { zip_entry_open(zip, "secret-1.txt"); { zip_entry_read(zip, &readbuf, &readsize); } zip_entry_close(zip); } zip_stream_close(zip); free(readbuf); free(outbuf); ```