mirror of
https://github.com/veracrypt/VeraCrypt
synced 2024-09-19 20:36:18 +02:00
Update Libzip to latest 1.9.2 (#1071)
* Libzip 1.9.2 Updated Libzip to latest version 1.9.2 and changed version number in the config.h from 1.7.3 to 1.9.2. Not sure if anything else needs to be tweaked :) * Modified Libzip to work with Visual studio * Update README.md Update libzip copyright. * Added the missing files. I've added the missing files zipconf.h and config.h, I've missed those sorry for that!
This commit is contained in:
parent
b872702309
commit
1fc4168b81
@ -219,7 +219,7 @@ Copyright (c) 1998-2000 Paul Le Roux. All rights reserved.
|
||||
Copyright (c) 1998-2008 Brian Gladman, Worcester, UK. All rights reserved.
|
||||
Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler.
|
||||
Copyright (c) 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
|
||||
Copyright (c) 1999-2017 Dieter Baron and Thomas Klausner.
|
||||
Copyright (c) 1999-2020 Dieter Baron and Thomas Klausner.
|
||||
Copyright (c) 2013, Alexey Degtyarev. All rights reserved.
|
||||
Copyright (c) 1999-2016 Jack Lloyd. All rights reserved.
|
||||
Copyright (c) 2013-2019 Stephan Mueller <smueller@chronox.de>
|
||||
|
@ -1,6 +1,6 @@
|
||||
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,3 +1,35 @@
|
||||
1.9.2 [2022-06-28]
|
||||
|
||||
* Fix version number in header file.
|
||||
|
||||
1.9.1 [2022-06-28]
|
||||
===================
|
||||
|
||||
* Fix `zip_file_is_seekable()`.
|
||||
|
||||
1.9.0 [2022-06-13]
|
||||
==================
|
||||
|
||||
* Add `zip_file_is_seekable()`.
|
||||
* Improve compatibility with WinAES.
|
||||
* Fix encoding handling in `zip_name_locate()`.
|
||||
* Add option to `zipcmp` to output summary of changes.
|
||||
* Various bug fixes and documentation improvements.
|
||||
|
||||
1.8.0 [2021-06-18]
|
||||
==================
|
||||
|
||||
* Add support for zstd (Zstandard) compression.
|
||||
* Add support for lzma (ID 14) compression.
|
||||
* Add `zip_source_window_create()`.
|
||||
* Add `zip_source_zip_create()` variant to `zip_source_zip()`.
|
||||
* Allow method specific `comp_flags` in `zip_set_file_compression()`.
|
||||
* Allow `zip_source_tell()` on sources that don't support seeking and `zip_ftell()` on compressed data.
|
||||
* Provide more details for consistency check errors.
|
||||
* Improve output of `zipcmp`.
|
||||
* In `zipcmp`, don’t ignore empty directories when comparing directory listing.
|
||||
* Treat empty string as no password given in `zip_file_set_encryption()`, `zip_fopen_encrypted()`, and `zip_set_default_password()`.
|
||||
|
||||
1.7.3 [2020-07-15]
|
||||
==================
|
||||
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
/*
|
||||
compat.h -- compatibility defines.
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -41,27 +41,26 @@
|
||||
/* to have *_MAX definitions for all types when compiling with g++ */
|
||||
#define __STDC_LIMIT_MACROS
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef ZIP_EXTERN
|
||||
#ifndef ZIP_STATIC
|
||||
#if defined(_WIN32) && defined(ZIP_DLL) && !defined(ZIP_STATIC)
|
||||
#ifdef BUILDING_LIBZIP
|
||||
#define ZIP_EXTERN __declspec(dllexport)
|
||||
#else
|
||||
#define ZIP_EXTERN
|
||||
#define ZIP_EXTERN __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* for dup(), close(), etc. */
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDBOOL_H
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#ifndef __cplusplus
|
||||
#elif !defined(__BOOL_DEFINED)
|
||||
typedef char bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
@ -85,9 +84,6 @@ typedef char bool;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(HAVE__CHMOD)
|
||||
#define chmod _chmod
|
||||
#endif
|
||||
#if defined(HAVE__CLOSE)
|
||||
#define close _close
|
||||
#endif
|
||||
@ -101,7 +97,7 @@ typedef char bool;
|
||||
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
|
||||
#define fileno _fileno
|
||||
#endif
|
||||
#if defined(HAVE__SNPRINTF)
|
||||
#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#if defined(HAVE__STRDUP)
|
||||
|
@ -5,68 +5,72 @@
|
||||
#endif
|
||||
/* BEGIN DEFINES */
|
||||
/* #undef HAVE___PROGNAME */
|
||||
#define HAVE__CHMOD
|
||||
#define HAVE__CLOSE
|
||||
#define HAVE__DUP
|
||||
#define HAVE__FDOPEN
|
||||
#define HAVE__FILENO
|
||||
#define HAVE__OPEN
|
||||
#define HAVE__SETMODE
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define HAVE__SNPRINTF
|
||||
#else
|
||||
/* #undef HAVE__SNPRINTF */
|
||||
#endif
|
||||
#define HAVE__STRDUP
|
||||
#define HAVE__STRICMP
|
||||
#define HAVE__STRTOI64
|
||||
#define HAVE__STRTOUI64
|
||||
#define HAVE__UMASK
|
||||
/* #undef HAVE__UMASK */
|
||||
#define HAVE__UNLINK
|
||||
/* #undef HAVE_ARC4RANDOM */
|
||||
/* #undef HAVE_CLONEFILE */
|
||||
/* #undef HAVE_COMMONCRYPTO */
|
||||
/* #undef HAVE_CRYPTO */
|
||||
#define HAVE_CRYPTO
|
||||
/* #undef HAVE_FICLONERANGE */
|
||||
#define HAVE_FILENO
|
||||
/* #undef HAVE_FCHMOD */
|
||||
/* #undef HAVE_FSEEKO */
|
||||
/* #undef HAVE_FTELLO */
|
||||
/* #undef HAVE_GETPROGNAME */
|
||||
/* #undef HAVE_GNUTLS */
|
||||
/* #undef HAVE_LIBBZ2 */
|
||||
#define HAVE_OPEN
|
||||
/* #undef HAVE_OPENSSL */
|
||||
/* #undef HAVE_LIBLZMA */
|
||||
/* #undef HAVE_LIBZSTD */
|
||||
/* #undef HAVE_LOCALTIME_R */
|
||||
/* #undef HAVE_MBEDTLS */
|
||||
/* #undef HAVE_MKSTEMP */
|
||||
/* #undef HAVE_NULLABLE */
|
||||
/* #undef HAVE_OPENSSL */
|
||||
#define HAVE_SETMODE
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
/* #undef HAVE_SNPRINTF */
|
||||
/* #undef HAVE_SSIZE_T_LIBZIP */
|
||||
#else
|
||||
#define HAVE_SNPRINTF
|
||||
#endif
|
||||
/* #undef HAVE_STRCASECMP */
|
||||
#define HAVE_STRDUP
|
||||
#define HAVE_STRICMP
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
/* #undef HAVE_STRTOLL */
|
||||
/* #undef HAVE_STRTOULL */
|
||||
#else
|
||||
#define HAVE_STRTOLL
|
||||
#define HAVE_STRTOULL
|
||||
#endif
|
||||
/* #undef HAVE_STRUCT_TM_TM_ZONE */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
/* #undef HAVE_STDBOOL_H */
|
||||
#else
|
||||
#define HAVE_STDBOOL_H
|
||||
#endif
|
||||
/* #undef HAVE_STRINGS_H */
|
||||
/* #undef HAVE_UNISTD_H */
|
||||
#define __INT8_LIBZIP 1
|
||||
#define INT8_T_LIBZIP 1
|
||||
#define UINT8_T_LIBZIP 1
|
||||
#define __INT16_LIBZIP 2
|
||||
#define INT16_T_LIBZIP 2
|
||||
#define UINT16_T_LIBZIP 2
|
||||
#define __INT32_LIBZIP 4
|
||||
#define INT32_T_LIBZIP 4
|
||||
#define UINT32_T_LIBZIP 4
|
||||
#define __INT64_LIBZIP 8
|
||||
#define INT64_T_LIBZIP 8
|
||||
#define UINT64_T_LIBZIP 8
|
||||
#define SHORT_LIBZIP 2
|
||||
#define INT_LIBZIP 4
|
||||
#define LONG_LIBZIP 4
|
||||
#define LONG_LONG_LIBZIP 8
|
||||
#define HAVE_WINDOWS_CRYPTO
|
||||
#define SIZEOF_OFF_T 4
|
||||
#ifdef _WIN64
|
||||
#define SIZE_T_LIBZIP 8
|
||||
#define SIZEOF_SIZE_T 8
|
||||
#else
|
||||
#define SIZE_T_LIBZIP 4
|
||||
#define SIZEOF_SIZE_T 4
|
||||
#endif
|
||||
/* #undef SSIZE_T_LIBZIP */
|
||||
/* #undef HAVE_DIRENT_H */
|
||||
/* #undef HAVE_FTS_H */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
@ -76,18 +80,6 @@
|
||||
#define HAVE_SHARED
|
||||
/* END DEFINES */
|
||||
#define PACKAGE "libzip"
|
||||
#define VERSION "1.7.3"
|
||||
|
||||
#ifndef HAVE_SSIZE_T_LIBZIP
|
||||
# if SIZE_T_LIBZIP == INT_LIBZIP
|
||||
typedef int ssize_t;
|
||||
# elif SIZE_T_LIBZIP == LONG_LIBZIP
|
||||
typedef long ssize_t;
|
||||
# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP
|
||||
typedef long long ssize_t;
|
||||
# else
|
||||
#error no suitable type for ssize_t found
|
||||
# endif
|
||||
#endif
|
||||
#define VERSION "1.9.2"
|
||||
|
||||
#endif /* HAD_CONFIG_H */
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
/*
|
||||
zip.h -- exported declarations.
|
||||
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -45,9 +45,13 @@ extern "C" {
|
||||
#include <zipconf.h>
|
||||
|
||||
#ifndef ZIP_EXTERN
|
||||
#ifndef ZIP_STATIC
|
||||
#if defined(ZIP_DLL) && !defined(ZIP_STATIC)
|
||||
#ifdef _WIN32
|
||||
#ifdef BUILDING_LIBZIP
|
||||
#define ZIP_EXTERN __declspec(dllexport)
|
||||
#else
|
||||
#define ZIP_EXTERN __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define ZIP_EXTERN __attribute__((visibility("default")))
|
||||
#else
|
||||
@ -58,9 +62,6 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _Nullable
|
||||
#define _Nonnull
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
@ -126,7 +127,7 @@ extern "C" {
|
||||
#define ZIP_ER_INVAL 18 /* N Invalid argument */
|
||||
#define ZIP_ER_NOZIP 19 /* N Not a zip archive */
|
||||
#define ZIP_ER_INTERNAL 20 /* N Internal error */
|
||||
#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */
|
||||
#define ZIP_ER_INCONS 21 /* L Zip archive inconsistent */
|
||||
#define ZIP_ER_REMOVE 22 /* S Can't remove file */
|
||||
#define ZIP_ER_DELETED 23 /* N Entry has been deleted */
|
||||
#define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */
|
||||
@ -141,9 +142,10 @@ extern "C" {
|
||||
|
||||
/* type of system error value */
|
||||
|
||||
#define ZIP_ET_NONE 0 /* sys_err unused */
|
||||
#define ZIP_ET_SYS 1 /* sys_err is errno */
|
||||
#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */
|
||||
#define ZIP_ET_NONE 0 /* sys_err unused */
|
||||
#define ZIP_ET_SYS 1 /* sys_err is errno */
|
||||
#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */
|
||||
#define ZIP_ET_LIBZIP 3 /* sys_err is libzip error code */
|
||||
|
||||
/* compression methods */
|
||||
|
||||
@ -166,7 +168,9 @@ extern "C" {
|
||||
/* 15-17 - Reserved by PKWARE */
|
||||
#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
|
||||
#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */
|
||||
/* 20 - old value for Zstandard */
|
||||
#define ZIP_CM_LZMA2 33
|
||||
#define ZIP_CM_ZSTD 93 /* Zstandard compressed data */
|
||||
#define ZIP_CM_XZ 95 /* XZ compressed data */
|
||||
#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */
|
||||
#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */
|
||||
@ -242,6 +246,8 @@ typedef enum zip_source_cmd zip_source_cmd_t;
|
||||
|
||||
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd))
|
||||
|
||||
#define ZIP_SOURCE_CHECK_SUPPORTED(supported, cmd) (((supported) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)) != 0)
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
|
||||
@ -397,6 +403,7 @@ ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_N
|
||||
ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t);
|
||||
ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable);
|
||||
ZIP_EXTERN int zip_file_is_seekable(zip_file_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t);
|
||||
ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t);
|
||||
@ -463,8 +470,10 @@ ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
|
||||
#endif
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_window_create(zip_source_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
|
||||
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
|
||||
ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull);
|
||||
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_add.c -- add file via callback function
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,9 +38,9 @@
|
||||
|
||||
/*
|
||||
NOTE: Return type is signed so we can return -1 on error.
|
||||
The index can not be larger than ZIP_INT64_MAX since the size
|
||||
of the central directory cannot be larger than
|
||||
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
|
||||
The index can not be larger than ZIP_INT64_MAX since the size
|
||||
of the central directory cannot be larger than
|
||||
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
|
||||
*/
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_add_dir.c -- add directory
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_add_entry.c -- create and init struct zip_entry
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -44,32 +44,32 @@ _zip_add_entry(zip_t *za) {
|
||||
zip_uint64_t idx;
|
||||
|
||||
if (za->nentry + 1 >= za->nentry_alloc) {
|
||||
zip_entry_t *rentries;
|
||||
zip_uint64_t nalloc = za->nentry_alloc;
|
||||
zip_uint64_t additional_entries = 2 * nalloc;
|
||||
zip_uint64_t realloc_size;
|
||||
zip_entry_t *rentries;
|
||||
zip_uint64_t nalloc = za->nentry_alloc;
|
||||
zip_uint64_t additional_entries = 2 * nalloc;
|
||||
zip_uint64_t realloc_size;
|
||||
|
||||
if (additional_entries < 16) {
|
||||
additional_entries = 16;
|
||||
}
|
||||
else if (additional_entries > 1024) {
|
||||
additional_entries = 1024;
|
||||
}
|
||||
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
|
||||
nalloc += additional_entries;
|
||||
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
|
||||
if (additional_entries < 16) {
|
||||
additional_entries = 16;
|
||||
}
|
||||
else if (additional_entries > 1024) {
|
||||
additional_entries = 1024;
|
||||
}
|
||||
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
|
||||
nalloc += additional_entries;
|
||||
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
|
||||
|
||||
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
|
||||
if (!rentries) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
za->entry = rentries;
|
||||
za->nentry_alloc = nalloc;
|
||||
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
|
||||
if (!rentries) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
za->entry = rentries;
|
||||
za->nentry_alloc = nalloc;
|
||||
}
|
||||
|
||||
idx = za->nentry++;
|
||||
|
285
src/Common/libzip/zip_algorithm_bzip2.c
Normal file
285
src/Common/libzip/zip_algorithm_bzip2.c
Normal file
@ -0,0 +1,285 @@
|
||||
/*
|
||||
zip_algorithm_bzip2.c -- bzip2 (de)compression routines
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <bzlib.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct ctx {
|
||||
zip_error_t *error;
|
||||
bool compress;
|
||||
int compression_flags;
|
||||
bool end_of_input;
|
||||
bz_stream zstr;
|
||||
};
|
||||
|
||||
|
||||
static zip_uint64_t
|
||||
maximum_compressed_size(zip_uint64_t uncompressed_size) {
|
||||
zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.006);
|
||||
|
||||
if (compressed_size < uncompressed_size) {
|
||||
return ZIP_UINT64_MAX;
|
||||
}
|
||||
return compressed_size;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
allocate(bool compress, int compression_flags, zip_error_t *error) {
|
||||
struct ctx *ctx;
|
||||
|
||||
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->error = error;
|
||||
ctx->compress = compress;
|
||||
ctx->compression_flags = compression_flags;
|
||||
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
|
||||
ctx->compression_flags = 9;
|
||||
}
|
||||
ctx->end_of_input = false;
|
||||
|
||||
ctx->zstr.bzalloc = NULL;
|
||||
ctx->zstr.bzfree = NULL;
|
||||
ctx->zstr.opaque = NULL;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(true, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(false, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deallocate(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static zip_uint16_t
|
||||
general_purpose_bit_flags(void *ud) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
map_error(int ret) {
|
||||
switch (ret) {
|
||||
case BZ_FINISH_OK:
|
||||
case BZ_FLUSH_OK:
|
||||
case BZ_OK:
|
||||
case BZ_RUN_OK:
|
||||
case BZ_STREAM_END:
|
||||
return ZIP_ER_OK;
|
||||
|
||||
case BZ_DATA_ERROR:
|
||||
case BZ_DATA_ERROR_MAGIC:
|
||||
case BZ_UNEXPECTED_EOF:
|
||||
return ZIP_ER_COMPRESSED_DATA;
|
||||
|
||||
case BZ_MEM_ERROR:
|
||||
return ZIP_ER_MEMORY;
|
||||
|
||||
case BZ_PARAM_ERROR:
|
||||
return ZIP_ER_INVAL;
|
||||
|
||||
case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */
|
||||
case BZ_IO_ERROR:
|
||||
case BZ_OUTBUFF_FULL:
|
||||
case BZ_SEQUENCE_ERROR:
|
||||
return ZIP_ER_INTERNAL;
|
||||
|
||||
default:
|
||||
return ZIP_ER_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int ret;
|
||||
|
||||
ctx->zstr.avail_in = 0;
|
||||
ctx->zstr.next_in = NULL;
|
||||
ctx->zstr.avail_out = 0;
|
||||
ctx->zstr.next_out = NULL;
|
||||
|
||||
if (ctx->compress) {
|
||||
ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30);
|
||||
}
|
||||
else {
|
||||
ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0);
|
||||
}
|
||||
|
||||
if (ret != BZ_OK) {
|
||||
zip_error_set(ctx->error, map_error(ret), 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
end(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int err;
|
||||
|
||||
if (ctx->compress) {
|
||||
err = BZ2_bzCompressEnd(&ctx->zstr);
|
||||
}
|
||||
else {
|
||||
err = BZ2_bzDecompressEnd(&ctx->zstr);
|
||||
}
|
||||
|
||||
if (err != BZ_OK) {
|
||||
zip_error_set(ctx->error, map_error(err), 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->zstr.avail_in = (unsigned int)length;
|
||||
ctx->zstr.next_in = (char *)data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
}
|
||||
|
||||
|
||||
static zip_compression_status_t
|
||||
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
int ret;
|
||||
|
||||
if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) {
|
||||
*length = 0;
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
|
||||
ctx->zstr.next_out = (char *)data;
|
||||
|
||||
if (ctx->compress) {
|
||||
ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
|
||||
}
|
||||
else {
|
||||
ret = BZ2_bzDecompress(&ctx->zstr);
|
||||
}
|
||||
|
||||
*length = *length - ctx->zstr.avail_out;
|
||||
|
||||
switch (ret) {
|
||||
case BZ_FINISH_OK: /* compression */
|
||||
return ZIP_COMPRESSION_OK;
|
||||
|
||||
case BZ_OK: /* decompression */
|
||||
case BZ_RUN_OK: /* compression */
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
return ZIP_COMPRESSION_OK;
|
||||
|
||||
case BZ_STREAM_END:
|
||||
return ZIP_COMPRESSION_END;
|
||||
|
||||
default:
|
||||
zip_error_set(ctx->error, map_error(ret), 0);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_bzip2_compress = {
|
||||
maximum_compressed_size,
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
46,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_bzip2_decompress = {
|
||||
maximum_compressed_size,
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
46,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
/* clang-format on */
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_algorithm_deflate.c -- deflate (de)compression routines
|
||||
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -46,20 +46,33 @@ struct ctx {
|
||||
};
|
||||
|
||||
|
||||
static zip_uint64_t
|
||||
maximum_compressed_size(zip_uint64_t uncompressed_size) {
|
||||
/* max deflate size increase: size + ceil(size/16k)*5+6 */
|
||||
|
||||
zip_uint64_t compressed_size = uncompressed_size + (uncompressed_size + 16383) / 16384 * 5 + 6;
|
||||
|
||||
if (compressed_size < uncompressed_size) {
|
||||
return ZIP_UINT64_MAX;
|
||||
}
|
||||
return compressed_size;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
allocate(bool compress, int compression_flags, zip_error_t *error) {
|
||||
struct ctx *ctx;
|
||||
|
||||
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ET_SYS, errno);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ET_SYS, errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->error = error;
|
||||
ctx->compress = compress;
|
||||
ctx->compression_flags = compression_flags;
|
||||
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
|
||||
ctx->compression_flags = Z_BEST_COMPRESSION;
|
||||
ctx->compression_flags = Z_BEST_COMPRESSION;
|
||||
}
|
||||
ctx->end_of_input = false;
|
||||
|
||||
@ -96,21 +109,21 @@ general_purpose_bit_flags(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (!ctx->compress) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->compression_flags < 3) {
|
||||
return 2 << 1;
|
||||
return 2 << 1;
|
||||
}
|
||||
else if (ctx->compression_flags > 7) {
|
||||
return 1 << 1;
|
||||
return 1 << 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
start(void *ud) {
|
||||
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
int ret;
|
||||
|
||||
@ -120,16 +133,16 @@ start(void *ud) {
|
||||
ctx->zstr.next_out = NULL;
|
||||
|
||||
if (ctx->compress) {
|
||||
/* negative value to tell zlib not to write a header */
|
||||
ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
/* negative value to tell zlib not to write a header */
|
||||
ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
else {
|
||||
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
|
||||
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
|
||||
}
|
||||
|
||||
if (ret != Z_OK) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return false;
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -143,15 +156,15 @@ end(void *ud) {
|
||||
int err;
|
||||
|
||||
if (ctx->compress) {
|
||||
err = deflateEnd(&ctx->zstr);
|
||||
err = deflateEnd(&ctx->zstr);
|
||||
}
|
||||
else {
|
||||
err = inflateEnd(&ctx->zstr);
|
||||
err = inflateEnd(&ctx->zstr);
|
||||
}
|
||||
|
||||
if (err != Z_OK) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
|
||||
return false;
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -163,8 +176,8 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
ctx->zstr.avail_in = (uInt)length;
|
||||
@ -192,37 +205,38 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
||||
ctx->zstr.next_out = (Bytef *)data;
|
||||
|
||||
if (ctx->compress) {
|
||||
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
|
||||
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
|
||||
}
|
||||
else {
|
||||
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
|
||||
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
|
||||
}
|
||||
|
||||
*length = *length - ctx->zstr.avail_out;
|
||||
|
||||
switch (ret) {
|
||||
case Z_OK:
|
||||
return ZIP_COMPRESSION_OK;
|
||||
return ZIP_COMPRESSION_OK;
|
||||
|
||||
case Z_STREAM_END:
|
||||
return ZIP_COMPRESSION_END;
|
||||
return ZIP_COMPRESSION_END;
|
||||
|
||||
case Z_BUF_ERROR:
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
/* fallthrough */
|
||||
|
||||
default:
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
|
||||
maximum_compressed_size,
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
@ -236,6 +250,7 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = {
|
||||
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
|
||||
maximum_compressed_size,
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
|
406
src/Common/libzip/zip_algorithm_xz.c
Normal file
406
src/Common/libzip/zip_algorithm_xz.c
Normal file
@ -0,0 +1,406 @@
|
||||
/*
|
||||
zip_algorithm_xz.c -- LZMA/XZ (de)compression routines
|
||||
Bazed on zip_algorithm_deflate.c -- deflate (de)compression routines
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <lzma.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
|
||||
enum header_state { INCOMPLETE, OUTPUT, DONE };
|
||||
|
||||
#define HEADER_BYTES_ZIP 9
|
||||
#define HEADER_MAGIC_LENGTH 4
|
||||
#define HEADER_MAGIC1_OFFSET 0
|
||||
#define HEADER_MAGIC2_OFFSET 2
|
||||
#define HEADER_SIZE_OFFSET 9
|
||||
#define HEADER_SIZE_LENGTH 8
|
||||
#define HEADER_PARAMETERS_LENGTH 5
|
||||
#define HEADER_LZMA_ALONE_LENGTH (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH)
|
||||
|
||||
struct ctx {
|
||||
zip_error_t *error;
|
||||
bool compress;
|
||||
zip_uint32_t compression_flags;
|
||||
bool end_of_input;
|
||||
lzma_stream zstr;
|
||||
zip_uint16_t method;
|
||||
/* header member is used for converting from zip to "lzma alone"
|
||||
* format
|
||||
*
|
||||
* "lzma alone" file format starts with:
|
||||
* 5 bytes lzma parameters
|
||||
* 8 bytes uncompressed size
|
||||
* compressed data
|
||||
*
|
||||
* zip archive on-disk format starts with
|
||||
* 4 bytes magic (first two bytes vary, e.g. 0x0914 or 0x1002, next bytes are 0x0500)
|
||||
* 5 bytes lzma parameters
|
||||
* compressed data
|
||||
*
|
||||
* we read the data into a header of the form
|
||||
* 4 bytes magic
|
||||
* 5 bytes lzma parameters
|
||||
* 8 bytes uncompressed size
|
||||
*/
|
||||
zip_uint8_t header[HEADER_MAGIC_LENGTH + HEADER_LZMA_ALONE_LENGTH];
|
||||
zip_uint8_t header_bytes_offset;
|
||||
enum header_state header_state;
|
||||
zip_uint64_t uncompresssed_size;
|
||||
};
|
||||
|
||||
|
||||
static zip_uint64_t
|
||||
maximum_compressed_size(zip_uint64_t uncompressed_size) {
|
||||
/*
|
||||
According to https://sourceforge.net/p/sevenzip/discussion/45797/thread/b6bd62f8/
|
||||
|
||||
1) you can use
|
||||
outSize = 1.10 * originalSize + 64 KB.
|
||||
in most cases outSize is less then 1.02 from originalSize.
|
||||
2) You can try LZMA2, where
|
||||
outSize can be = 1.001 * originalSize + 1 KB.
|
||||
*/
|
||||
/* 13 bytes added for lzma alone header */
|
||||
zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.1) + 64 * 1024 + 13;
|
||||
|
||||
if (compressed_size < uncompressed_size) {
|
||||
return ZIP_UINT64_MAX;
|
||||
}
|
||||
return compressed_size;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method) {
|
||||
struct ctx *ctx;
|
||||
|
||||
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->error = error;
|
||||
ctx->compress = compress;
|
||||
if (compression_flags < 0 || compression_flags > 9) {
|
||||
ctx->compression_flags = 6; /* default value */
|
||||
} else {
|
||||
ctx->compression_flags = (zip_uint32_t)compression_flags;
|
||||
}
|
||||
ctx->compression_flags |= LZMA_PRESET_EXTREME;
|
||||
ctx->end_of_input = false;
|
||||
memset(ctx->header, 0, sizeof(ctx->header));
|
||||
ctx->header_bytes_offset = 0;
|
||||
if (ZIP_CM_LZMA) {
|
||||
ctx->header_state = INCOMPLETE;
|
||||
}
|
||||
else {
|
||||
ctx->header_state = DONE;
|
||||
}
|
||||
memset(&ctx->zstr, 0, sizeof(ctx->zstr));
|
||||
ctx->method = method;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(true, compression_flags, error, method);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(false, compression_flags, error, method);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deallocate(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static zip_uint16_t
|
||||
general_purpose_bit_flags(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (!ctx->compress) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ctx->method == ZIP_CM_LZMA) {
|
||||
/* liblzma always returns an EOS/EOPM marker, see
|
||||
* https://sourceforge.net/p/lzmautils/discussion/708858/thread/84c5dbb9/#a5e4/3764 */
|
||||
return 1 << 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
map_error(lzma_ret ret) {
|
||||
switch (ret) {
|
||||
case LZMA_DATA_ERROR:
|
||||
case LZMA_UNSUPPORTED_CHECK:
|
||||
return ZIP_ER_COMPRESSED_DATA;
|
||||
|
||||
case LZMA_MEM_ERROR:
|
||||
return ZIP_ER_MEMORY;
|
||||
|
||||
case LZMA_OPTIONS_ERROR:
|
||||
return ZIP_ER_INVAL;
|
||||
|
||||
default:
|
||||
return ZIP_ER_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
lzma_ret ret;
|
||||
|
||||
lzma_options_lzma opt_lzma;
|
||||
lzma_lzma_preset(&opt_lzma, ctx->compression_flags);
|
||||
lzma_filter filters[] = {
|
||||
{.id = (ctx->method == ZIP_CM_LZMA ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2), .options = &opt_lzma},
|
||||
{.id = LZMA_VLI_UNKNOWN, .options = NULL},
|
||||
};
|
||||
|
||||
ctx->zstr.avail_in = 0;
|
||||
ctx->zstr.next_in = NULL;
|
||||
ctx->zstr.avail_out = 0;
|
||||
ctx->zstr.next_out = NULL;
|
||||
|
||||
if (ctx->compress) {
|
||||
if (ctx->method == ZIP_CM_LZMA)
|
||||
ret = lzma_alone_encoder(&ctx->zstr, filters[0].options);
|
||||
else
|
||||
ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64);
|
||||
}
|
||||
else {
|
||||
if (ctx->method == ZIP_CM_LZMA)
|
||||
ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX);
|
||||
else
|
||||
ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED);
|
||||
}
|
||||
|
||||
if (ret != LZMA_OK) {
|
||||
zip_error_set(ctx->error, map_error(ret), 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If general purpose bits 1 & 2 are both zero, write real uncompressed size in header. */
|
||||
if ((attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) && (attributes->general_purpose_bit_mask & 0x6) == 0x6 && (attributes->general_purpose_bit_flags & 0x06) == 0 && (st->valid & ZIP_STAT_SIZE)) {
|
||||
ctx->uncompresssed_size = st->size;
|
||||
}
|
||||
else {
|
||||
ctx->uncompresssed_size = ZIP_UINT64_MAX;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
end(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
lzma_end(&ctx->zstr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* For decompression of LZMA1: Have we read the full "lzma alone" header yet? */
|
||||
if (ctx->method == ZIP_CM_LZMA && !ctx->compress && ctx->header_state == INCOMPLETE) {
|
||||
/* if not, get more of the data */
|
||||
zip_uint8_t got = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, length);
|
||||
memcpy(ctx->header + ctx->header_bytes_offset, data, got);
|
||||
ctx->header_bytes_offset += got;
|
||||
length -= got;
|
||||
data += got;
|
||||
/* Do we have a complete header now? */
|
||||
if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) {
|
||||
Bytef empty_buffer[1];
|
||||
zip_buffer_t *buffer;
|
||||
/* check magic */
|
||||
if (ctx->header[HEADER_MAGIC2_OFFSET] != 0x05 || ctx->header[HEADER_MAGIC2_OFFSET + 1] != 0x00) {
|
||||
/* magic does not match */
|
||||
zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0);
|
||||
return false;
|
||||
}
|
||||
/* set size of uncompressed data in "lzma alone" header to "unknown" */
|
||||
if ((buffer = _zip_buffer_new(ctx->header + HEADER_SIZE_OFFSET, HEADER_SIZE_LENGTH)) == NULL) {
|
||||
zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
_zip_buffer_put_64(buffer, ctx->uncompresssed_size);
|
||||
_zip_buffer_free(buffer);
|
||||
/* Feed header into "lzma alone" decoder, for
|
||||
* initialization; this should not produce output. */
|
||||
ctx->zstr.next_in = (void *)(ctx->header + HEADER_MAGIC_LENGTH);
|
||||
ctx->zstr.avail_in = HEADER_LZMA_ALONE_LENGTH;
|
||||
ctx->zstr.total_in = 0;
|
||||
ctx->zstr.next_out = empty_buffer;
|
||||
ctx->zstr.avail_out = sizeof(*empty_buffer);
|
||||
ctx->zstr.total_out = 0;
|
||||
/* this just initializes the decoder and does not produce output, so it consumes the complete header */
|
||||
if (lzma_code(&ctx->zstr, LZMA_RUN) != LZMA_OK || ctx->zstr.total_out > 0) {
|
||||
zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0);
|
||||
return false;
|
||||
}
|
||||
ctx->header_state = DONE;
|
||||
}
|
||||
}
|
||||
ctx->zstr.avail_in = (uInt)length;
|
||||
ctx->zstr.next_in = (Bytef *)data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
}
|
||||
|
||||
|
||||
static zip_compression_status_t
|
||||
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
lzma_ret ret;
|
||||
/* for compression of LZMA1 */
|
||||
if (ctx->method == ZIP_CM_LZMA && ctx->compress) {
|
||||
if (ctx->header_state == INCOMPLETE) {
|
||||
/* write magic to output buffer */
|
||||
ctx->header[0] = 0x09;
|
||||
ctx->header[1] = 0x14;
|
||||
ctx->header[2] = 0x05;
|
||||
ctx->header[3] = 0x00;
|
||||
/* generate lzma parameters into output buffer */
|
||||
ctx->zstr.avail_out = HEADER_LZMA_ALONE_LENGTH;
|
||||
ctx->zstr.next_out = ctx->header + HEADER_MAGIC_LENGTH;
|
||||
ret = lzma_code(&ctx->zstr, LZMA_RUN);
|
||||
if (ret != LZMA_OK || ctx->zstr.avail_out != 0) {
|
||||
/* assume that the whole header will be provided with the first call to lzma_code */
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
ctx->header_state = OUTPUT;
|
||||
}
|
||||
if (ctx->header_state == OUTPUT) {
|
||||
/* write header */
|
||||
zip_uint8_t write_len = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, *length);
|
||||
memcpy(data, ctx->header + ctx->header_bytes_offset, write_len);
|
||||
ctx->header_bytes_offset += write_len;
|
||||
*length = write_len;
|
||||
if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) {
|
||||
ctx->header_state = DONE;
|
||||
}
|
||||
return ZIP_COMPRESSION_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
|
||||
ctx->zstr.next_out = (Bytef *)data;
|
||||
|
||||
ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN);
|
||||
*length = *length - ctx->zstr.avail_out;
|
||||
|
||||
switch (ret) {
|
||||
case LZMA_OK:
|
||||
return ZIP_COMPRESSION_OK;
|
||||
|
||||
case LZMA_STREAM_END:
|
||||
return ZIP_COMPRESSION_END;
|
||||
|
||||
case LZMA_BUF_ERROR:
|
||||
if (ctx->zstr.avail_in == 0) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
default:
|
||||
zip_error_set(ctx->error, map_error(ret), 0);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Version Required should be set to 63 (6.3) because this compression
|
||||
method was only defined in appnote.txt version 6.3.8, but Winzip
|
||||
does not unpack it if the value is not 20. */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_xz_compress = {
|
||||
maximum_compressed_size,
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_xz_decompress = {
|
||||
maximum_compressed_size,
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
/* clang-format on */
|
294
src/Common/libzip/zip_algorithm_zstd.c
Normal file
294
src/Common/libzip/zip_algorithm_zstd.c
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
zip_algorithm_zstd.c -- zstd (de)compression routines
|
||||
Copyright (C) 2020-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <zstd.h>
|
||||
#include <zstd_errors.h>
|
||||
|
||||
struct ctx {
|
||||
zip_error_t *error;
|
||||
bool compress;
|
||||
int compression_flags;
|
||||
bool end_of_input;
|
||||
ZSTD_DStream *zdstream;
|
||||
ZSTD_CStream *zcstream;
|
||||
ZSTD_outBuffer out;
|
||||
ZSTD_inBuffer in;
|
||||
};
|
||||
|
||||
static zip_uint64_t
|
||||
maximum_compressed_size(zip_uint64_t uncompressed_size) {
|
||||
return ZSTD_compressBound(uncompressed_size);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
allocate(bool compress, int compression_flags, zip_error_t *error) {
|
||||
struct ctx *ctx;
|
||||
|
||||
/* 0: let zstd choose */
|
||||
if (compression_flags < ZSTD_minCLevel() || compression_flags > ZSTD_maxCLevel()) {
|
||||
compression_flags = 0;
|
||||
}
|
||||
|
||||
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->error = error;
|
||||
ctx->compress = compress;
|
||||
ctx->compression_flags = compression_flags;
|
||||
ctx->end_of_input = false;
|
||||
|
||||
ctx->zdstream = NULL;
|
||||
ctx->zcstream = NULL;
|
||||
ctx->in.src = NULL;
|
||||
ctx->in.pos = 0;
|
||||
ctx->in.size = 0;
|
||||
ctx->out.dst = NULL;
|
||||
ctx->out.pos = 0;
|
||||
ctx->out.size = 0;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(true, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
|
||||
return allocate(false, compression_flags, error);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
deallocate(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
static zip_uint16_t
|
||||
general_purpose_bit_flags(void *ud) {
|
||||
/* struct ctx *ctx = (struct ctx *)ud; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
map_error(size_t ret) {
|
||||
switch (ret) {
|
||||
case ZSTD_error_no_error:
|
||||
return ZIP_ER_OK;
|
||||
|
||||
case ZSTD_error_corruption_detected:
|
||||
case ZSTD_error_checksum_wrong:
|
||||
case ZSTD_error_dictionary_corrupted:
|
||||
case ZSTD_error_dictionary_wrong:
|
||||
return ZIP_ER_COMPRESSED_DATA;
|
||||
|
||||
case ZSTD_error_memory_allocation:
|
||||
return ZIP_ER_MEMORY;
|
||||
|
||||
case ZSTD_error_parameter_unsupported:
|
||||
case ZSTD_error_parameter_outOfBound:
|
||||
return ZIP_ER_INVAL;
|
||||
|
||||
default:
|
||||
return ZIP_ER_INTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
ctx->in.src = NULL;
|
||||
ctx->in.pos = 0;
|
||||
ctx->in.size = 0;
|
||||
ctx->out.dst = NULL;
|
||||
ctx->out.pos = 0;
|
||||
ctx->out.size = 0;
|
||||
if (ctx->compress) {
|
||||
size_t ret;
|
||||
ctx->zcstream = ZSTD_createCStream();
|
||||
if (ctx->zcstream == NULL) {
|
||||
zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
ret = ZSTD_initCStream(ctx->zcstream, ctx->compression_flags);
|
||||
if (ZSTD_isError(ret)) {
|
||||
zip_error_set(ctx->error, ZIP_ER_ZLIB, map_error(ret));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx->zdstream = ZSTD_createDStream();
|
||||
if (ctx->zdstream == NULL) {
|
||||
zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
end(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
size_t ret;
|
||||
|
||||
if (ctx->compress) {
|
||||
ret = ZSTD_freeCStream(ctx->zcstream);
|
||||
ctx->zcstream = NULL;
|
||||
}
|
||||
else {
|
||||
ret = ZSTD_freeDStream(ctx->zdstream);
|
||||
ctx->zdstream = NULL;
|
||||
}
|
||||
|
||||
if (ZSTD_isError(ret)) {
|
||||
zip_error_set(ctx->error, map_error(ret), 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
if (length > SIZE_MAX || ctx->in.pos != ctx->in.size) {
|
||||
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
ctx->in.src = (const void *)data;
|
||||
ctx->in.size = (size_t)length;
|
||||
ctx->in.pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
end_of_input(void *ud) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
ctx->end_of_input = true;
|
||||
}
|
||||
|
||||
|
||||
static zip_compression_status_t
|
||||
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
|
||||
struct ctx *ctx = (struct ctx *)ud;
|
||||
|
||||
size_t ret;
|
||||
|
||||
if (ctx->in.pos == ctx->in.size && !ctx->end_of_input) {
|
||||
*length = 0;
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
ctx->out.dst = data;
|
||||
ctx->out.pos = 0;
|
||||
ctx->out.size = ZIP_MIN(SIZE_MAX, *length);
|
||||
|
||||
if (ctx->compress) {
|
||||
if (ctx->in.pos == ctx->in.size && ctx->end_of_input) {
|
||||
ret = ZSTD_endStream(ctx->zcstream, &ctx->out);
|
||||
if (ret == 0) {
|
||||
*length = ctx->out.pos;
|
||||
return ZIP_COMPRESSION_END;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = ZSTD_compressStream(ctx->zcstream, &ctx->out, &ctx->in);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = ZSTD_decompressStream(ctx->zdstream, &ctx->out, &ctx->in);
|
||||
}
|
||||
if (ZSTD_isError(ret)) {
|
||||
zip_error_set(ctx->error, map_error(ret), 0);
|
||||
return ZIP_COMPRESSION_ERROR;
|
||||
}
|
||||
|
||||
*length = ctx->out.pos;
|
||||
if (ctx->in.pos == ctx->in.size) {
|
||||
return ZIP_COMPRESSION_NEED_DATA;
|
||||
}
|
||||
|
||||
return ZIP_COMPRESSION_OK;
|
||||
}
|
||||
|
||||
/* Version Required should be set to 63 (6.3) because this compression
|
||||
method was only defined in appnote.txt version 6.3.7, but Winzip
|
||||
does not unpack it if the value is not 20. */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_zstd_compress = {
|
||||
maximum_compressed_size,
|
||||
compress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
|
||||
zip_compression_algorithm_t zip_algorithm_zstd_decompress = {
|
||||
maximum_compressed_size,
|
||||
decompress_allocate,
|
||||
deallocate,
|
||||
general_purpose_bit_flags,
|
||||
20,
|
||||
start,
|
||||
end,
|
||||
input,
|
||||
end_of_input,
|
||||
process
|
||||
};
|
||||
|
||||
/* clang-format on */
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_buffer.c -- bounds checked access to memory buffer
|
||||
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -45,11 +45,11 @@ _zip_buffer_data(zip_buffer_t *buffer) {
|
||||
void
|
||||
_zip_buffer_free(zip_buffer_t *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->free_data) {
|
||||
free(buffer->data);
|
||||
free(buffer->data);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
@ -69,7 +69,7 @@ _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
data = _zip_buffer_peek(buffer, length);
|
||||
|
||||
if (data != NULL) {
|
||||
buffer->offset += length;
|
||||
buffer->offset += length;
|
||||
}
|
||||
|
||||
return data;
|
||||
@ -81,7 +81,7 @@ _zip_buffer_get_16(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (zip_uint16_t)(data[0] + (data[1] << 8));
|
||||
@ -93,7 +93,7 @@ _zip_buffer_get_32(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
|
||||
@ -105,7 +105,7 @@ _zip_buffer_get_64(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0];
|
||||
@ -117,7 +117,7 @@ _zip_buffer_get_8(zip_buffer_t *buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||
|
||||
if (data == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return data[0];
|
||||
@ -133,7 +133,7 @@ _zip_buffer_left(zip_buffer_t *buffer) {
|
||||
zip_uint64_t
|
||||
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
|
||||
if (_zip_buffer_left(buffer) < length) {
|
||||
length = _zip_buffer_left(buffer);
|
||||
length = _zip_buffer_left(buffer);
|
||||
}
|
||||
|
||||
memcpy(data, _zip_buffer_get(buffer, length), length);
|
||||
@ -148,16 +148,16 @@ _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
|
||||
zip_buffer_t *buffer;
|
||||
|
||||
if (data == NULL) {
|
||||
if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
|
||||
if (free_data) {
|
||||
free(data);
|
||||
}
|
||||
return NULL;
|
||||
if (free_data) {
|
||||
free(data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->ok = true;
|
||||
@ -175,13 +175,13 @@ _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *b
|
||||
zip_buffer_t *buffer;
|
||||
|
||||
if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_zip_read(src, buffer->data, size, error) < 0) {
|
||||
_zip_buffer_free(buffer);
|
||||
return NULL;
|
||||
_zip_buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
@ -205,8 +205,8 @@ _zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint8_t *data;
|
||||
|
||||
if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
|
||||
buffer->ok = false;
|
||||
return NULL;
|
||||
buffer->ok = false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = buffer->data + buffer->offset;
|
||||
@ -218,7 +218,7 @@ _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
|
||||
zip_uint8_t *dst = _zip_buffer_get(buffer, length);
|
||||
|
||||
if (dst == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(dst, src, length);
|
||||
@ -231,7 +231,7 @@ _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (zip_uint8_t)(i & 0xff);
|
||||
@ -246,7 +246,7 @@ _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (zip_uint8_t)(i & 0xff);
|
||||
@ -263,7 +263,7 @@ _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = (zip_uint8_t)(i & 0xff);
|
||||
@ -284,7 +284,7 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
|
||||
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
data[0] = i;
|
||||
@ -296,8 +296,8 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
|
||||
int
|
||||
_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
|
||||
if (offset > buffer->size) {
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->ok = true;
|
||||
@ -312,8 +312,8 @@ _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
|
||||
zip_uint64_t offset = buffer->offset + length;
|
||||
|
||||
if (offset < buffer->offset) {
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
buffer->ok = false;
|
||||
return -1;
|
||||
}
|
||||
return _zip_buffer_set_offset(buffer, offset);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_close.c -- close zip archive and update changes
|
||||
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -57,225 +57,225 @@ zip_close(zip_t *za) {
|
||||
int changed;
|
||||
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
changed = _zip_changed(za, &survivors);
|
||||
|
||||
/* don't create zip files with no entries */
|
||||
if (survivors == 0) {
|
||||
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
|
||||
if (zip_source_remove(za->src) < 0) {
|
||||
if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
zip_discard(za);
|
||||
return 0;
|
||||
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
|
||||
if (zip_source_remove(za->src) < 0) {
|
||||
if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
zip_discard(za);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
zip_discard(za);
|
||||
return 0;
|
||||
zip_discard(za);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (survivors > za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
unchanged_offset = ZIP_UINT64_MAX;
|
||||
/* create list of files with index into original archive */
|
||||
for (i = j = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
|
||||
}
|
||||
if (za->entry[i].deleted) {
|
||||
continue;
|
||||
}
|
||||
if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
|
||||
}
|
||||
if (za->entry[i].deleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (j >= survivors) {
|
||||
free(filelist);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (j >= survivors) {
|
||||
free(filelist);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
filelist[j].idx = i;
|
||||
j++;
|
||||
filelist[j].idx = i;
|
||||
j++;
|
||||
}
|
||||
if (j < survivors) {
|
||||
free(filelist);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
free(filelist);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
|
||||
unchanged_offset = 0;
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
else {
|
||||
if (unchanged_offset == ZIP_UINT64_MAX) {
|
||||
/* we're keeping all file data, find the end of the last one */
|
||||
zip_uint64_t last_index = ZIP_UINT64_MAX;
|
||||
unchanged_offset = 0;
|
||||
if (unchanged_offset == ZIP_UINT64_MAX) {
|
||||
/* we're keeping all file data, find the end of the last one */
|
||||
zip_uint64_t last_index = ZIP_UINT64_MAX;
|
||||
unchanged_offset = 0;
|
||||
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL) {
|
||||
if (za->entry[i].orig->offset >= unchanged_offset) {
|
||||
unchanged_offset = za->entry[i].orig->offset;
|
||||
last_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_index != ZIP_UINT64_MAX) {
|
||||
if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset > 0) {
|
||||
if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
|
||||
/* cloning not supported, need to copy everything */
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (za->entry[i].orig != NULL) {
|
||||
if (za->entry[i].orig->offset >= unchanged_offset) {
|
||||
unchanged_offset = za->entry[i].orig->offset;
|
||||
last_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_index != ZIP_UINT64_MAX) {
|
||||
if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset > 0) {
|
||||
if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
|
||||
/* cloning not supported, need to copy everything */
|
||||
unchanged_offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unchanged_offset == 0) {
|
||||
if (zip_source_begin_write(za->src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
if (zip_source_begin_write(za->src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_zip_progress_start(za->progress) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
zip_source_rollback_write(za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
zip_source_rollback_write(za->src);
|
||||
free(filelist);
|
||||
return -1;
|
||||
}
|
||||
error = 0;
|
||||
for (j = 0; j < survivors; j++) {
|
||||
int new_data;
|
||||
zip_entry_t *entry;
|
||||
zip_dirent_t *de;
|
||||
int new_data;
|
||||
zip_entry_t *entry;
|
||||
zip_dirent_t *de;
|
||||
|
||||
if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
i = filelist[j].idx;
|
||||
entry = za->entry + i;
|
||||
i = filelist[j].idx;
|
||||
entry = za->entry + i;
|
||||
|
||||
if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
|
||||
/* already implicitly copied by cloning */
|
||||
continue;
|
||||
}
|
||||
if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
|
||||
/* already implicitly copied by cloning */
|
||||
continue;
|
||||
}
|
||||
|
||||
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
|
||||
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
|
||||
|
||||
/* create new local directory entry */
|
||||
if (entry->changes == NULL) {
|
||||
if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
de = entry->changes;
|
||||
|
||||
if (_zip_read_local_ef(za, i) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((off = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
de->offset = (zip_uint64_t)off;
|
||||
|
||||
if (new_data) {
|
||||
zip_source_t *zs;
|
||||
|
||||
zs = NULL;
|
||||
if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
|
||||
if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add_data writes dirent */
|
||||
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
|
||||
error = 1;
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
break;
|
||||
}
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
}
|
||||
else {
|
||||
zip_uint64_t offset;
|
||||
|
||||
if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
|
||||
/* when copying data, all sizes are known -> no data descriptor needed */
|
||||
/* except for PKWare encryption, where removing the data descriptor breaks password validation */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
/* create new local directory entry */
|
||||
if (entry->changes == NULL) {
|
||||
if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (copy_data(za, de->comp_size) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
de = entry->changes;
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_zip_read_local_ef(za, i) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((off = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
de->offset = (zip_uint64_t)off;
|
||||
|
||||
if (new_data) {
|
||||
zip_source_t *zs;
|
||||
|
||||
zs = NULL;
|
||||
if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
|
||||
if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add_data writes dirent */
|
||||
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
|
||||
error = 1;
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
break;
|
||||
}
|
||||
if (zs)
|
||||
zip_source_free(zs);
|
||||
}
|
||||
else {
|
||||
zip_uint64_t offset;
|
||||
|
||||
if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
|
||||
/* when copying data, all sizes are known -> no data descriptor needed */
|
||||
/* except for PKWare encryption, where removing the data descriptor breaks password validation */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
if (copy_data(za, de->comp_size) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
if (write_cdir(za, filelist, survivors) < 0)
|
||||
error = 1;
|
||||
if (write_cdir(za, filelist, survivors) < 0)
|
||||
error = 1;
|
||||
}
|
||||
|
||||
free(filelist);
|
||||
|
||||
if (!error) {
|
||||
if (zip_source_commit_write(za->src) != 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
}
|
||||
_zip_progress_end(za->progress);
|
||||
if (zip_source_commit_write(za->src) != 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
error = 1;
|
||||
}
|
||||
_zip_progress_end(za->progress);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
zip_source_rollback_write(za->src);
|
||||
return -1;
|
||||
zip_source_rollback_write(za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_discard(za);
|
||||
@ -296,86 +296,83 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
|
||||
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
|
||||
st.valid |= ZIP_STAT_COMP_METHOD;
|
||||
st.comp_method = ZIP_CM_STORE;
|
||||
st.valid |= ZIP_STAT_COMP_METHOD;
|
||||
st.comp_method = ZIP_CM_STORE;
|
||||
}
|
||||
|
||||
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
|
||||
de->comp_method = st.comp_method;
|
||||
de->comp_method = st.comp_method;
|
||||
else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
|
||||
st.valid |= ZIP_STAT_COMP_SIZE;
|
||||
st.comp_size = st.size;
|
||||
st.valid |= ZIP_STAT_COMP_SIZE;
|
||||
st.comp_size = st.size;
|
||||
}
|
||||
else {
|
||||
/* we'll recompress */
|
||||
st.valid &= ~ZIP_STAT_COMP_SIZE;
|
||||
/* we'll recompress */
|
||||
st.valid &= ~ZIP_STAT_COMP_SIZE;
|
||||
}
|
||||
|
||||
if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
|
||||
st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
|
||||
st.encryption_method = ZIP_EM_NONE;
|
||||
st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
|
||||
st.encryption_method = ZIP_EM_NONE;
|
||||
}
|
||||
|
||||
flags = ZIP_EF_LOCAL;
|
||||
|
||||
if ((st.valid & ZIP_STAT_SIZE) == 0) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
data_length = -1;
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
data_length = -1;
|
||||
}
|
||||
else {
|
||||
de->uncomp_size = st.size;
|
||||
/* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
|
||||
data_length = (zip_int64_t)st.size;
|
||||
de->uncomp_size = st.size;
|
||||
/* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
|
||||
data_length = (zip_int64_t)st.size;
|
||||
|
||||
if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
|
||||
zip_uint64_t max_size;
|
||||
if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
|
||||
zip_uint64_t max_compressed_size;
|
||||
zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method);
|
||||
|
||||
switch (ZIP_CM_ACTUAL(de->comp_method)) {
|
||||
case ZIP_CM_BZIP2:
|
||||
/* computed by looking at increase of 10 random files of size 1MB when
|
||||
* compressed with bzip2, rounded up: 1.006 */
|
||||
max_size = 4269351188u;
|
||||
break;
|
||||
if (compression_method == ZIP_CM_STORE) {
|
||||
max_compressed_size = st.size;
|
||||
}
|
||||
else {
|
||||
zip_compression_algorithm_t *algorithm = _zip_get_compression_algorithm(compression_method, true);
|
||||
if (algorithm == NULL) {
|
||||
max_compressed_size = ZIP_UINT64_MAX;
|
||||
}
|
||||
else {
|
||||
max_compressed_size = algorithm->maximum_compressed_size(st.size);
|
||||
}
|
||||
}
|
||||
|
||||
case ZIP_CM_DEFLATE:
|
||||
/* max deflate size increase: size + ceil(size/16k)*5+6 */
|
||||
max_size = 4293656963u;
|
||||
break;
|
||||
|
||||
case ZIP_CM_STORE:
|
||||
max_size = 0xffffffffu;
|
||||
break;
|
||||
|
||||
default:
|
||||
max_size = 0;
|
||||
}
|
||||
|
||||
if (st.size > max_size) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
}
|
||||
}
|
||||
else
|
||||
de->comp_size = st.comp_size;
|
||||
if (max_compressed_size > 0xffffffffu) {
|
||||
flags |= ZIP_FL_FORCE_ZIP64;
|
||||
}
|
||||
}
|
||||
else {
|
||||
de->comp_size = st.comp_size;
|
||||
data_length = (zip_int64_t)st.comp_size;
|
||||
}
|
||||
}
|
||||
|
||||
if ((offstart = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* as long as we don't support non-seekable output, clear data descriptor bit */
|
||||
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
|
||||
needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
|
||||
/* in these cases we can compute the CRC ourselves, so we do */
|
||||
needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
|
||||
needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
|
||||
|
||||
@ -387,127 +384,143 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
zip_source_keep(src_final);
|
||||
|
||||
if (needs_decrypt) {
|
||||
zip_encryption_implementation impl;
|
||||
zip_encryption_implementation impl;
|
||||
|
||||
if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
|
||||
/* error set by impl */
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
|
||||
/* error set by impl */
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (needs_decompress) {
|
||||
if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (needs_crc) {
|
||||
if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
if (needs_compress) {
|
||||
if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
|
||||
if (needs_encrypt) {
|
||||
zip_encryption_implementation impl;
|
||||
const char *password = NULL;
|
||||
zip_encryption_implementation impl;
|
||||
const char *password = NULL;
|
||||
|
||||
if (de->password) {
|
||||
password = de->password;
|
||||
}
|
||||
else if (za->default_password) {
|
||||
password = za->default_password;
|
||||
}
|
||||
if (de->password) {
|
||||
password = de->password;
|
||||
}
|
||||
else if (za->default_password) {
|
||||
password = za->default_password;
|
||||
}
|
||||
|
||||
if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
|
||||
/* error set by impl */
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
}
|
||||
if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
|
||||
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
|
||||
|
||||
/* PKWare encryption uses last_mod, make sure it gets the right value. */
|
||||
if (de->changed & ZIP_DIRENT_LAST_MOD) {
|
||||
zip_stat_t st_mtime;
|
||||
zip_stat_init(&st_mtime);
|
||||
st_mtime.valid = ZIP_STAT_MTIME;
|
||||
st_mtime.mtime = de->last_mod;
|
||||
if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, NULL, NULL, 0, &za->error)) == NULL) {
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
|
||||
/* error set by impl */
|
||||
zip_source_free(src_final);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
src_final = src_tmp;
|
||||
}
|
||||
|
||||
|
||||
if ((offdata = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = copy_source(za, src_final, data_length);
|
||||
|
||||
if (zip_source_stat(src_final, &st) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
_zip_error_set_from_source(&za->error, src_final);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
zip_source_free(src_final);
|
||||
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((offend = zip_source_tell_write(za->src)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
|
||||
if (st.valid & ZIP_STAT_MTIME)
|
||||
de->last_mod = st.mtime;
|
||||
else
|
||||
time(&de->last_mod);
|
||||
if (st.valid & ZIP_STAT_MTIME)
|
||||
de->last_mod = st.mtime;
|
||||
else
|
||||
time(&de->last_mod);
|
||||
}
|
||||
de->comp_method = st.comp_method;
|
||||
de->crc = st.crc;
|
||||
@ -516,23 +529,23 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
|
||||
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
|
||||
|
||||
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (is_zip64 != ret) {
|
||||
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
if (write_data_descriptor(za, de, is_zip64) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (write_data_descriptor(za, de, is_zip64) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -546,28 +559,28 @@ copy_data(zip_t *za, zip_uint64_t len) {
|
||||
double total = (double)len;
|
||||
|
||||
if (!byte_array_init(buf, BUFSIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
n = len > BUFSIZE ? BUFSIZE : len;
|
||||
if (_zip_read(za->src, buf, n, &za->error) < 0) {
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
n = len > BUFSIZE ? BUFSIZE : len;
|
||||
if (_zip_read(za->src, buf, n, &za->error) < 0) {
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_write(za, buf, n) < 0) {
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
if (_zip_write(za, buf, n) < 0) {
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
len -= n;
|
||||
len -= n;
|
||||
|
||||
if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
return -1;
|
||||
}
|
||||
if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
byte_array_fini(buf);
|
||||
@ -582,35 +595,35 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
|
||||
int ret;
|
||||
|
||||
if (zip_source_open(src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!byte_array_init(buf, BUFSIZE)) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
current = 0;
|
||||
while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) {
|
||||
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (n == BUFSIZE && za->progress && data_length > 0) {
|
||||
current += n;
|
||||
if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
if (n == BUFSIZE && za->progress && data_length > 0) {
|
||||
current += n;
|
||||
if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
ret = -1;
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
byte_array_fini(buf);
|
||||
@ -622,18 +635,16 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
|
||||
|
||||
static int
|
||||
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
|
||||
zip_int64_t cd_start, end, size;
|
||||
|
||||
if ((cd_start = zip_source_tell_write(za->src)) < 0) {
|
||||
return -1;
|
||||
if (zip_source_tell_write(za->src) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
|
||||
return -1;
|
||||
if (_zip_cdir_write(za, filelist, survivors) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((end = zip_source_tell_write(za->src)) < 0) {
|
||||
return -1;
|
||||
if (zip_source_tell_write(za->src) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -649,20 +660,20 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
|
||||
survivors = 0;
|
||||
|
||||
if (za->comment_changed || za->ch_flags != za->flags) {
|
||||
changed = 1;
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
changed = 1;
|
||||
}
|
||||
if (!za->entry[i].deleted) {
|
||||
survivors++;
|
||||
}
|
||||
if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
|
||||
changed = 1;
|
||||
}
|
||||
if (!za->entry[i].deleted) {
|
||||
survivors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (survivorsp) {
|
||||
*survivorsp = survivors;
|
||||
*survivorsp = survivors;
|
||||
}
|
||||
|
||||
return changed;
|
||||
@ -674,27 +685,27 @@ write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
|
||||
int ret = 0;
|
||||
|
||||
if (buffer == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_zip_buffer_put(buffer, DATADES_MAGIC, 4);
|
||||
_zip_buffer_put_32(buffer, de->crc);
|
||||
if (is_zip64) {
|
||||
_zip_buffer_put_64(buffer, de->comp_size);
|
||||
_zip_buffer_put_64(buffer, de->uncomp_size);
|
||||
_zip_buffer_put_64(buffer, de->comp_size);
|
||||
_zip_buffer_put_64(buffer, de->uncomp_size);
|
||||
}
|
||||
else {
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size);
|
||||
_zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size);
|
||||
}
|
||||
|
||||
if (!_zip_buffer_ok(buffer)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
ret = -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
|
||||
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
|
||||
}
|
||||
|
||||
_zip_buffer_free(buffer);
|
||||
|
54
src/Common/libzip/zip_crypto.h
Normal file
54
src/Common/libzip/zip_crypto.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
zip_crypto.h -- crypto definitions
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HAD_ZIP_CRYPTO_H
|
||||
#define HAD_ZIP_CRYPTO_H
|
||||
|
||||
#define ZIP_CRYPTO_SHA1_LENGTH 20
|
||||
#define ZIP_CRYPTO_AES_BLOCK_LENGTH 16
|
||||
|
||||
#if defined(HAVE_WINDOWS_CRYPTO)
|
||||
#include "zip_crypto_win.h"
|
||||
#elif defined(HAVE_COMMONCRYPTO)
|
||||
#include "zip_crypto_commoncrypto.h"
|
||||
#elif defined(HAVE_GNUTLS)
|
||||
#include "zip_crypto_gnutls.h"
|
||||
#elif defined(HAVE_OPENSSL)
|
||||
#include "zip_crypto_openssl.h"
|
||||
#elif defined(HAVE_MBEDTLS)
|
||||
#include "zip_crypto_mbedtls.h"
|
||||
#else
|
||||
#error "no crypto backend found"
|
||||
#endif
|
||||
|
||||
#endif /* HAD_ZIP_CRYPTO_H */
|
110
src/Common/libzip/zip_crypto_commoncrypto.c
Normal file
110
src/Common/libzip/zip_crypto_commoncrypto.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
zip_crypto_commoncrypto.c -- CommonCrypto wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_crypto.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||
if (aes == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
CCCryptorRelease(aes);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||
size_t len;
|
||||
CCCryptorUpdate(aes, in, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &len);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_zip_crypto_aes_t *
|
||||
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
|
||||
_zip_crypto_aes_t *aes;
|
||||
CCCryptorStatus ret;
|
||||
|
||||
ret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, key, key_size / 8, NULL, &aes);
|
||||
|
||||
switch (ret) {
|
||||
case kCCSuccess:
|
||||
return aes;
|
||||
|
||||
case kCCMemoryFailure:
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
|
||||
case kCCParamError:
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
|
||||
default:
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||
if (hmac == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
_zip_crypto_clear(hmac, sizeof(*hmac));
|
||||
free(hmac);
|
||||
}
|
||||
|
||||
|
||||
_zip_crypto_hmac_t *
|
||||
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
|
||||
_zip_crypto_hmac_t *hmac;
|
||||
|
||||
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CCHmacInit(hmac, kCCHmacAlgSHA1, secret, secret_length);
|
||||
|
||||
return hmac;
|
||||
}
|
53
src/Common/libzip/zip_crypto_commoncrypto.h
Normal file
53
src/Common/libzip/zip_crypto_commoncrypto.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
zip_crypto_commoncrypto.h -- definitions for CommonCrypto wrapper.
|
||||
Copyright (C) 2018 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HAD_ZIP_CRYPTO_COMMONCRYPTO_H
|
||||
#define HAD_ZIP_CRYPTO_COMMONCRYPTO_H
|
||||
|
||||
#include <CommonCrypto/CommonCrypto.h>
|
||||
|
||||
#define _zip_crypto_aes_t struct _CCCryptor
|
||||
#define _zip_crypto_hmac_t CCHmacContext
|
||||
|
||||
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||
|
||||
#define _zip_crypto_hmac(hmac, data, length) (CCHmacUpdate((hmac), (data), (length)), true)
|
||||
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||
#define _zip_crypto_hmac_output(hmac, data) (CCHmacFinal((hmac), (data)), true)
|
||||
|
||||
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)(key), (key_length), (salt), (salt_length), kCCPRFHmacAlgSHA1, (iterations), (output), (output_length)) == kCCSuccess)
|
||||
|
||||
#endif /* HAD_ZIP_CRYPTO_COMMONCRYPTO_H */
|
134
src/Common/libzip/zip_crypto_gnutls.c
Normal file
134
src/Common/libzip/zip_crypto_gnutls.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
zip_crypto_gnutls.c -- GnuTLS wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_crypto.h"
|
||||
|
||||
_zip_crypto_aes_t *
|
||||
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
|
||||
_zip_crypto_aes_t *aes;
|
||||
|
||||
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aes->key_size = key_size;
|
||||
|
||||
switch (aes->key_size) {
|
||||
case 128:
|
||||
nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key);
|
||||
break;
|
||||
case 192:
|
||||
nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key);
|
||||
break;
|
||||
case 256:
|
||||
nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key);
|
||||
break;
|
||||
default:
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
free(aes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return aes;
|
||||
}
|
||||
|
||||
bool
|
||||
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||
switch (aes->key_size) {
|
||||
case 128:
|
||||
nettle_aes128_encrypt(&aes->ctx.ctx_128, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
|
||||
break;
|
||||
case 192:
|
||||
nettle_aes192_encrypt(&aes->ctx.ctx_192, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
|
||||
break;
|
||||
case 256:
|
||||
nettle_aes256_encrypt(&aes->ctx.ctx_256, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||
if (aes == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
_zip_crypto_clear(aes, sizeof(*aes));
|
||||
free(aes);
|
||||
}
|
||||
|
||||
|
||||
_zip_crypto_hmac_t *
|
||||
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
|
||||
_zip_crypto_hmac_t *hmac;
|
||||
|
||||
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (gnutls_hmac_init(hmac, GNUTLS_MAC_SHA1, secret, secret_length) < 0) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||
zip_uint8_t buf[ZIP_CRYPTO_SHA1_LENGTH];
|
||||
|
||||
if (hmac == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
gnutls_hmac_deinit(*hmac, buf);
|
||||
_zip_crypto_clear(hmac, sizeof(*hmac));
|
||||
free(hmac);
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
return gnutls_rnd(GNUTLS_RND_KEY, buffer, length) == 0;
|
||||
}
|
68
src/Common/libzip/zip_crypto_gnutls.h
Normal file
68
src/Common/libzip/zip_crypto_gnutls.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
zip_crypto_gnutls.h -- definitions for GnuTLS wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HAD_ZIP_CRYPTO_GNUTLS_H
|
||||
#define HAD_ZIP_CRYPTO_GNUTLS_H
|
||||
|
||||
#define HAVE_SECURE_RANDOM
|
||||
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/pbkdf2.h>
|
||||
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
#include <gnutls/crypto.h>
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct aes128_ctx ctx_128;
|
||||
struct aes192_ctx ctx_192;
|
||||
struct aes256_ctx ctx_256;
|
||||
} ctx;
|
||||
zip_uint16_t key_size;
|
||||
} _zip_crypto_aes_t;
|
||||
|
||||
#define _zip_crypto_hmac_t gnutls_hmac_hd_t
|
||||
|
||||
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||
|
||||
#define _zip_crypto_hmac(hmac, data, length) (gnutls_hmac(*(hmac), (data), (length)) == 0)
|
||||
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||
#define _zip_crypto_hmac_output(hmac, data) (gnutls_hmac_output(*(hmac), (data)), true)
|
||||
|
||||
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (pbkdf2_hmac_sha1((key_length), (key), (iterations), (salt_length), (salt), (output_length), (output)), true)
|
||||
|
||||
#endif /* HAD_ZIP_CRYPTO_GNUTLS_H */
|
162
src/Common/libzip/zip_crypto_mbedtls.c
Normal file
162
src/Common/libzip/zip_crypto_mbedtls.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
zip_crypto_mbedtls.c -- mbed TLS wrapper
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_crypto.h"
|
||||
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/pkcs5.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
_zip_crypto_aes_t *
|
||||
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
|
||||
_zip_crypto_aes_t *aes;
|
||||
|
||||
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_aes_init(aes);
|
||||
mbedtls_aes_setkey_enc(aes, (const unsigned char *)key, (unsigned int)key_size);
|
||||
|
||||
return aes;
|
||||
}
|
||||
|
||||
void
|
||||
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||
if (aes == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_aes_free(aes);
|
||||
free(aes);
|
||||
}
|
||||
|
||||
|
||||
_zip_crypto_hmac_t *
|
||||
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
|
||||
_zip_crypto_hmac_t *hmac;
|
||||
|
||||
if (secret_length > INT_MAX) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_md_init(hmac);
|
||||
|
||||
if (mbedtls_md_setup(hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mbedtls_md_hmac_starts(hmac, (const unsigned char *)secret, (size_t)secret_length) != 0) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||
if (hmac == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mbedtls_md_free(hmac);
|
||||
free(hmac);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length) {
|
||||
mbedtls_md_context_t sha1_ctx;
|
||||
bool ok = true;
|
||||
|
||||
mbedtls_md_init(&sha1_ctx);
|
||||
|
||||
if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ok && mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const unsigned char *)key, (size_t)key_length, (const unsigned char *)salt, (size_t)salt_length, (unsigned int)iterations, (uint32_t)output_length, (unsigned char *)output) != 0) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
mbedtls_md_free(&sha1_ctx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
} zip_random_context_t;
|
||||
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
static zip_random_context_t *ctx = NULL;
|
||||
const unsigned char *pers = "zip_crypto_mbedtls";
|
||||
|
||||
if (!ctx) {
|
||||
ctx = (zip_random_context_t *)malloc(sizeof(zip_random_context_t));
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
mbedtls_entropy_init(&ctx->entropy);
|
||||
mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
|
||||
if (mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, pers, strlen(pers)) != 0) {
|
||||
mbedtls_ctr_drbg_free(&ctx->ctr_drbg);
|
||||
mbedtls_entropy_free(&ctx->entropy);
|
||||
free(ctx);
|
||||
ctx = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return mbedtls_ctr_drbg_random(&ctx->ctr_drbg, (unsigned char *)buffer, (size_t)length) == 0;
|
||||
}
|
56
src/Common/libzip/zip_crypto_mbedtls.h
Normal file
56
src/Common/libzip/zip_crypto_mbedtls.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
zip_crypto_mbedtls.h -- definitions for mbedtls wrapper
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HAD_ZIP_CRYPTO_MBEDTLS_H
|
||||
#define HAD_ZIP_CRYPTO_MBEDTLS_H
|
||||
|
||||
#define HAVE_SECURE_RANDOM
|
||||
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/md.h>
|
||||
|
||||
#define _zip_crypto_aes_t mbedtls_aes_context
|
||||
#define _zip_crypto_hmac_t mbedtls_md_context_t
|
||||
|
||||
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||
#define _zip_crypto_aes_encrypt_block(aes, in, out) (mbedtls_aes_crypt_ecb((aes), MBEDTLS_AES_ENCRYPT, (in), (out)) == 0)
|
||||
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||
|
||||
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||
#define _zip_crypto_hmac(hmac, data, length) (mbedtls_md_hmac_update((hmac), (data), (length)) == 0)
|
||||
#define _zip_crypto_hmac_output(hmac, data) (mbedtls_md_hmac_finish((hmac), (data)) == 0)
|
||||
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||
|
||||
bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length);
|
||||
|
||||
#endif /* HAD_ZIP_CRYPTO_MBEDTLS_H */
|
184
src/Common/libzip/zip_crypto_openssl.c
Normal file
184
src/Common/libzip/zip_crypto_openssl.c
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
zip_crypto_openssl.c -- OpenSSL wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_crypto.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
|
||||
#define USE_OPENSSL_1_0_API
|
||||
#endif
|
||||
|
||||
|
||||
_zip_crypto_aes_t *
|
||||
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
|
||||
_zip_crypto_aes_t *aes;
|
||||
const EVP_CIPHER* cipher_type;
|
||||
|
||||
switch (key_size) {
|
||||
case 128:
|
||||
cipher_type = EVP_aes_128_ecb();
|
||||
break;
|
||||
case 192:
|
||||
cipher_type = EVP_aes_192_ecb();
|
||||
break;
|
||||
case 256:
|
||||
cipher_type = EVP_aes_256_ecb();
|
||||
break;
|
||||
default:
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENSSL_1_0_API
|
||||
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
memset(aes, 0, sizeof(*aes));
|
||||
#else
|
||||
if ((aes = EVP_CIPHER_CTX_new()) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (EVP_EncryptInit_ex(aes, cipher_type, NULL, key, NULL) != 1) {
|
||||
#ifdef USE_OPENSSL_1_0_API
|
||||
free(aes);
|
||||
#else
|
||||
EVP_CIPHER_CTX_free(aes);
|
||||
#endif
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return aes;
|
||||
}
|
||||
|
||||
void
|
||||
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||
if (aes == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENSSL_1_0_API
|
||||
EVP_CIPHER_CTX_cleanup(aes);
|
||||
_zip_crypto_clear(aes, sizeof(*aes));
|
||||
free(aes);
|
||||
#else
|
||||
EVP_CIPHER_CTX_free(aes);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||
int len;
|
||||
if (EVP_EncryptUpdate(aes, out, &len, in, ZIP_CRYPTO_AES_BLOCK_LENGTH) != 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_zip_crypto_hmac_t *
|
||||
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
|
||||
_zip_crypto_hmac_t *hmac;
|
||||
|
||||
if (secret_length > INT_MAX) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENSSL_1_0_API
|
||||
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(hmac);
|
||||
#else
|
||||
if ((hmac = HMAC_CTX_new()) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (HMAC_Init_ex(hmac, secret, (int)secret_length, EVP_sha1(), NULL) != 1) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
#ifdef USE_OPENSSL_1_0_API
|
||||
free(hmac);
|
||||
#else
|
||||
HMAC_CTX_free(hmac);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||
if (hmac == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENSSL_1_0_API
|
||||
HMAC_CTX_cleanup(hmac);
|
||||
_zip_crypto_clear(hmac, sizeof(*hmac));
|
||||
free(hmac);
|
||||
#else
|
||||
HMAC_CTX_free(hmac);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
|
||||
unsigned int length;
|
||||
|
||||
return HMAC_Final(hmac, data, &length) == 1;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
return RAND_bytes(buffer, length) == 1;
|
||||
}
|
56
src/Common/libzip/zip_crypto_openssl.h
Normal file
56
src/Common/libzip/zip_crypto_openssl.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
zip_crypto_openssl.h -- definitions for OpenSSL wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HAD_ZIP_CRYPTO_OPENSSL_H
|
||||
#define HAD_ZIP_CRYPTO_OPENSSL_H
|
||||
|
||||
#define HAVE_SECURE_RANDOM
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#define _zip_crypto_aes_t EVP_CIPHER_CTX
|
||||
#define _zip_crypto_hmac_t HMAC_CTX
|
||||
|
||||
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||
|
||||
#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1)
|
||||
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data);
|
||||
|
||||
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (PKCS5_PBKDF2_HMAC_SHA1((const char *)(key), (key_length), (salt), (salt_length), (iterations), (output_length), (output)))
|
||||
|
||||
#endif /* HAD_ZIP_CRYPTO_OPENSSL_H */
|
495
src/Common/libzip/zip_crypto_win.c
Normal file
495
src/Common/libzip/zip_crypto_win.c
Normal file
@ -0,0 +1,495 @@
|
||||
/*
|
||||
zip_crypto_win.c -- Windows Crypto API wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include "zip_crypto.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOCRYPT
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <bcrypt.h>
|
||||
|
||||
#pragma comment(lib, "bcrypt.lib")
|
||||
|
||||
/*
|
||||
|
||||
This code is using the Cryptography API: Next Generation (CNG)
|
||||
https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal
|
||||
|
||||
This API is supported on
|
||||
- Windows Vista or later (client OS)
|
||||
- Windows Server 2008 (server OS)
|
||||
- Windows Embedded Compact 2013 (don't know about Windows Embedded Compact 7)
|
||||
|
||||
The code was developed for Windows Embedded Compact 2013 (WEC2013),
|
||||
but should be working for all of the above mentioned OSes.
|
||||
|
||||
There are 2 restrictions for WEC2013, Windows Vista and Windows Server 2008:
|
||||
|
||||
1.) The function "BCryptDeriveKeyPBKDF2" is not available
|
||||
|
||||
I found some code which is implementing this function using the deprecated Crypto API here:
|
||||
https://www.idrix.fr/Root/content/view/37/54/
|
||||
|
||||
I took this code and converted it to the newer CNG API. The original code was more
|
||||
flexible, but this is not needed here so i refactored it a bit and just kept what is needed.
|
||||
|
||||
The define "HAS_BCRYPTDERIVEKEYPBKDF2" controls whether "BCryptDeriveKeyPBKDF2"
|
||||
of the CNG API is used or not. This define must not be set if you are compiling for WEC2013 or Windows Vista.
|
||||
|
||||
|
||||
2.) "BCryptCreateHash" can't manage the memory needed for the hash object internally
|
||||
|
||||
On Windows 7 or later it is possible to pass NULL for the hash object buffer.
|
||||
This is not supported on WEC2013, so we have to handle the memory allocation/deallocation ourselves.
|
||||
There is no #ifdef to control that, because this is working for all supported OSes.
|
||||
|
||||
*/
|
||||
|
||||
#if !defined(WINCE) && !defined(__MINGW32__)
|
||||
#define HAS_BCRYPTDERIVEKEYPBKDF2
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BCRYPTDERIVEKEYPBKDF2
|
||||
|
||||
bool
|
||||
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
|
||||
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
|
||||
bool result;
|
||||
|
||||
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0));
|
||||
|
||||
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DIGEST_SIZE 20
|
||||
#define BLOCK_SIZE 64
|
||||
|
||||
typedef struct {
|
||||
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||
BCRYPT_HASH_HANDLE hInnerHash;
|
||||
BCRYPT_HASH_HANDLE hOuterHash;
|
||||
ULONG cbHashObject;
|
||||
PUCHAR pbInnerHash;
|
||||
PUCHAR pbOuterHash;
|
||||
} PRF_CTX;
|
||||
|
||||
static void
|
||||
hmacFree(PRF_CTX *pContext) {
|
||||
if (pContext->hOuterHash)
|
||||
BCryptDestroyHash(pContext->hOuterHash);
|
||||
if (pContext->hInnerHash)
|
||||
BCryptDestroyHash(pContext->hInnerHash);
|
||||
free(pContext->pbOuterHash);
|
||||
free(pContext->pbInnerHash);
|
||||
if (pContext->hAlgorithm)
|
||||
BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask) {
|
||||
BYTE buffer[BLOCK_SIZE];
|
||||
DWORD i;
|
||||
|
||||
if (cbPassword > BLOCK_SIZE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memset(buffer, mask, sizeof(buffer));
|
||||
|
||||
for (i = 0; i < cbPassword; ++i) {
|
||||
buffer[i] = (char)(pbPassword[i] ^ mask);
|
||||
}
|
||||
|
||||
return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
|
||||
}
|
||||
|
||||
static BOOL
|
||||
hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) {
|
||||
BOOL bStatus = FALSE;
|
||||
ULONG cbResult;
|
||||
BYTE key[DIGEST_SIZE];
|
||||
|
||||
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) || !BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pContext->cbHashObject, sizeof(pContext->cbHashObject), &cbResult, 0)) || ((pContext->pbInnerHash = malloc(pContext->cbHashObject)) == NULL) || ((pContext->pbOuterHash = malloc(pContext->cbHashObject)) == NULL) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, pContext->pbInnerHash, pContext->cbHashObject, NULL, 0, 0)) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, pContext->pbOuterHash, pContext->cbHashObject, NULL, 0, 0))) {
|
||||
goto hmacInit_end;
|
||||
}
|
||||
|
||||
if (cbPassword > BLOCK_SIZE) {
|
||||
BCRYPT_HASH_HANDLE hHash = NULL;
|
||||
PUCHAR pbHashObject = malloc(pContext->cbHashObject);
|
||||
if (pbHashObject == NULL) {
|
||||
goto hmacInit_end;
|
||||
}
|
||||
|
||||
bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0));
|
||||
|
||||
if (hHash)
|
||||
BCryptDestroyHash(hHash);
|
||||
free(pbHashObject);
|
||||
|
||||
if (!bStatus) {
|
||||
goto hmacInit_end;
|
||||
}
|
||||
|
||||
pbPassword = key;
|
||||
}
|
||||
|
||||
bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);
|
||||
|
||||
hmacInit_end:
|
||||
|
||||
if (bStatus == FALSE)
|
||||
hmacFree(pContext);
|
||||
|
||||
return bStatus;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput, DWORD cbHashObject) {
|
||||
BOOL success = FALSE;
|
||||
BCRYPT_HASH_HANDLE hHash = NULL;
|
||||
PUCHAR pbHashObject = malloc(cbHashObject);
|
||||
|
||||
if (pbHashObject == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, pbHashObject, cbHashObject, 0))) {
|
||||
success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));
|
||||
|
||||
BCryptDestroyHash(hHash);
|
||||
}
|
||||
|
||||
free(pbHashObject);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) {
|
||||
DWORD cbResult;
|
||||
DWORD cbHashObject;
|
||||
|
||||
return BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&cbHashObject, sizeof(cbHashObject), &cbResult, 0)) && hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE, cbHashObject) && hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE, cbHashObject);
|
||||
}
|
||||
|
||||
static void
|
||||
myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) {
|
||||
while (dwLen--)
|
||||
*ptr1++ ^= *ptr2++;
|
||||
}
|
||||
|
||||
BOOL
|
||||
pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey) {
|
||||
BOOL bStatus = FALSE;
|
||||
DWORD l, r, dwULen, i, j;
|
||||
BYTE Ti[DIGEST_SIZE];
|
||||
BYTE V[DIGEST_SIZE];
|
||||
LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE));
|
||||
PRF_CTX prfCtx = {0};
|
||||
|
||||
if (U == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) {
|
||||
free(U);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!hmacInit(&prfCtx, pbPassword, cbPassword)) {
|
||||
goto PBKDF2_end;
|
||||
}
|
||||
|
||||
l = (DWORD)ceil((double)cbDerivedKey / (double)DIGEST_SIZE);
|
||||
r = cbDerivedKey - (l - 1) * DIGEST_SIZE;
|
||||
|
||||
for (i = 1; i <= l; i++) {
|
||||
ZeroMemory(Ti, DIGEST_SIZE);
|
||||
for (j = 0; j < cIterations; j++) {
|
||||
if (j == 0) {
|
||||
/* construct first input for PRF */
|
||||
memcpy(U, pbSalt, cbSalt);
|
||||
U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24);
|
||||
U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16);
|
||||
U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8);
|
||||
U[cbSalt + 3] = (BYTE)((i & 0x000000FF));
|
||||
dwULen = cbSalt + 4;
|
||||
}
|
||||
else {
|
||||
memcpy(U, V, DIGEST_SIZE);
|
||||
dwULen = DIGEST_SIZE;
|
||||
}
|
||||
|
||||
if (!hmacCalculate(&prfCtx, U, dwULen, V)) {
|
||||
goto PBKDF2_end;
|
||||
}
|
||||
|
||||
myxor(Ti, V, DIGEST_SIZE);
|
||||
}
|
||||
|
||||
if (i != l) {
|
||||
memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
|
||||
}
|
||||
else {
|
||||
/* Take only the first r bytes */
|
||||
memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r);
|
||||
}
|
||||
}
|
||||
|
||||
bStatus = TRUE;
|
||||
|
||||
PBKDF2_end:
|
||||
|
||||
hmacFree(&prfCtx);
|
||||
free(U);
|
||||
return bStatus;
|
||||
}
|
||||
|
||||
bool
|
||||
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
|
||||
return (key_length <= ZIP_UINT32_MAX) && pbkdf2((PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct _zip_crypto_aes_s {
|
||||
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||
BCRYPT_KEY_HANDLE hKey;
|
||||
ULONG cbKeyObject;
|
||||
PUCHAR pbKeyObject;
|
||||
};
|
||||
|
||||
_zip_crypto_aes_t *
|
||||
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
|
||||
_zip_crypto_aes_t *aes = (_zip_crypto_aes_t *)calloc(1, sizeof(*aes));
|
||||
|
||||
ULONG cbResult;
|
||||
ULONG key_length = key_size / 8;
|
||||
|
||||
if (aes == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&aes->hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0))) {
|
||||
_zip_crypto_aes_free(aes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!BCRYPT_SUCCESS(BCryptSetProperty(aes->hAlgorithm, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) {
|
||||
_zip_crypto_aes_free(aes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) {
|
||||
_zip_crypto_aes_free(aes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aes->pbKeyObject = malloc(aes->cbKeyObject);
|
||||
if (aes->pbKeyObject == NULL) {
|
||||
_zip_crypto_aes_free(aes);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) {
|
||||
_zip_crypto_aes_free(aes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return aes;
|
||||
}
|
||||
|
||||
void
|
||||
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
|
||||
if (aes == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aes->hKey != NULL) {
|
||||
BCryptDestroyKey(aes->hKey);
|
||||
}
|
||||
|
||||
if (aes->pbKeyObject != NULL) {
|
||||
free(aes->pbKeyObject);
|
||||
}
|
||||
|
||||
if (aes->hAlgorithm != NULL) {
|
||||
BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0);
|
||||
}
|
||||
|
||||
free(aes);
|
||||
}
|
||||
|
||||
bool
|
||||
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
|
||||
ULONG cbResult;
|
||||
NTSTATUS status = BCryptEncrypt(aes->hKey, (PUCHAR)in, ZIP_CRYPTO_AES_BLOCK_LENGTH, NULL, NULL, 0, (PUCHAR)out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &cbResult, 0);
|
||||
return BCRYPT_SUCCESS(status);
|
||||
}
|
||||
|
||||
struct _zip_crypto_hmac_s {
|
||||
BCRYPT_ALG_HANDLE hAlgorithm;
|
||||
BCRYPT_HASH_HANDLE hHash;
|
||||
DWORD cbHashObject;
|
||||
PUCHAR pbHashObject;
|
||||
DWORD cbHash;
|
||||
PUCHAR pbHash;
|
||||
};
|
||||
|
||||
/* https://code.msdn.microsoft.com/windowsdesktop/Hmac-Computation-Sample-11fe8ec1/sourcecode?fileId=42820&pathId=283874677 */
|
||||
|
||||
_zip_crypto_hmac_t *
|
||||
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
|
||||
NTSTATUS status;
|
||||
ULONG cbResult;
|
||||
_zip_crypto_hmac_t *hmac;
|
||||
|
||||
if (secret_length > INT_MAX) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hmac = (_zip_crypto_hmac_t *)calloc(1, sizeof(*hmac));
|
||||
|
||||
if (hmac == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
_zip_crypto_hmac_free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hmac->cbHashObject, sizeof(hmac->cbHashObject), &cbResult, 0);
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
_zip_crypto_hmac_free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hmac->pbHashObject = malloc(hmac->cbHashObject);
|
||||
if (hmac->pbHashObject == NULL) {
|
||||
_zip_crypto_hmac_free(hmac);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&hmac->cbHash, sizeof(hmac->cbHash), &cbResult, 0);
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
_zip_crypto_hmac_free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hmac->pbHash = malloc(hmac->cbHash);
|
||||
if (hmac->pbHash == NULL) {
|
||||
_zip_crypto_hmac_free(hmac);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = BCryptCreateHash(hmac->hAlgorithm, &hmac->hHash, hmac->pbHashObject, hmac->cbHashObject, (PUCHAR)secret, (ULONG)secret_length, 0);
|
||||
if (!BCRYPT_SUCCESS(status)) {
|
||||
_zip_crypto_hmac_free(hmac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hmac;
|
||||
}
|
||||
|
||||
void
|
||||
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
|
||||
if (hmac == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hmac->hHash != NULL) {
|
||||
BCryptDestroyHash(hmac->hHash);
|
||||
}
|
||||
|
||||
if (hmac->pbHash != NULL) {
|
||||
free(hmac->pbHash);
|
||||
}
|
||||
|
||||
if (hmac->pbHashObject != NULL) {
|
||||
free(hmac->pbHashObject);
|
||||
}
|
||||
|
||||
if (hmac->hAlgorithm) {
|
||||
BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0);
|
||||
}
|
||||
|
||||
free(hmac);
|
||||
}
|
||||
|
||||
bool
|
||||
_zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length) {
|
||||
if (hmac == NULL || length > ULONG_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0));
|
||||
}
|
||||
|
||||
bool
|
||||
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
|
||||
if (hmac == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0));
|
||||
}
|
||||
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
return BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG));
|
||||
}
|
53
src/Common/libzip/zip_crypto_win.h
Normal file
53
src/Common/libzip/zip_crypto_win.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
zip_crypto_win.h -- Windows Crypto API wrapper.
|
||||
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HAD_ZIP_CRYPTO_WIN_H
|
||||
#define HAD_ZIP_CRYPTO_WIN_H
|
||||
|
||||
#define HAVE_SECURE_RANDOM
|
||||
|
||||
typedef struct _zip_crypto_aes_s _zip_crypto_aes_t;
|
||||
typedef struct _zip_crypto_hmac_s _zip_crypto_hmac_t;
|
||||
|
||||
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
|
||||
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
|
||||
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
|
||||
|
||||
bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length);
|
||||
|
||||
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
|
||||
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
|
||||
bool _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length);
|
||||
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data);
|
||||
|
||||
#endif /* HAD_ZIP_CRYPTO_WIN_H */
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_delete.c -- delete file from zip archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,27 +40,27 @@ zip_delete(zip_t *za, zip_uint64_t idx) {
|
||||
const char *name;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* allow duplicate file names, because the file will
|
||||
* be removed directly afterwards */
|
||||
if (_zip_unchange(za, idx, 1) != 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
za->entry[idx].deleted = 1;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_dir_add.c -- add directory
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -48,31 +48,31 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
|
||||
zip_source_t *source;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = NULL;
|
||||
len = strlen(name);
|
||||
|
||||
if (name[len - 1] != '/') {
|
||||
if ((s = (char *)malloc(len + 2)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
strcpy(s, name);
|
||||
s[len] = '/';
|
||||
s[len + 1] = '\0';
|
||||
if ((s = (char *)malloc(len + 2)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
strcpy(s, name);
|
||||
s[len] = '/';
|
||||
s[len + 1] = '\0';
|
||||
}
|
||||
|
||||
if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) {
|
||||
free(s);
|
||||
return -1;
|
||||
free(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
|
||||
@ -80,12 +80,12 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
|
||||
free(s);
|
||||
|
||||
if (idx < 0)
|
||||
zip_source_free(source);
|
||||
zip_source_free(source);
|
||||
else {
|
||||
if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
|
||||
zip_delete(za, (zip_uint64_t)idx);
|
||||
return -1;
|
||||
}
|
||||
if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
|
||||
zip_delete(za, (zip_uint64_t)idx);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_discard.c -- discard and free struct zip
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -46,11 +46,11 @@ zip_discard(zip_t *za) {
|
||||
zip_uint64_t i;
|
||||
|
||||
if (za == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
if (za->src) {
|
||||
zip_source_close(za->src);
|
||||
zip_source_free(za->src);
|
||||
zip_source_close(za->src);
|
||||
zip_source_free(za->src);
|
||||
}
|
||||
|
||||
free(za->default_password);
|
||||
@ -60,13 +60,13 @@ zip_discard(zip_t *za) {
|
||||
_zip_hash_free(za->names);
|
||||
|
||||
if (za->entry) {
|
||||
for (i = 0; i < za->nentry; i++)
|
||||
_zip_entry_finalize(za->entry + i);
|
||||
free(za->entry);
|
||||
for (i = 0; i < za->nentry; i++)
|
||||
_zip_entry_finalize(za->entry + i);
|
||||
free(za->entry);
|
||||
}
|
||||
|
||||
for (i = 0; i < za->nopen_source; i++) {
|
||||
_zip_source_invalidate(za->open_source[i]);
|
||||
_zip_source_invalidate(za->open_source[i]);
|
||||
}
|
||||
free(za->open_source);
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_entry.c -- struct zip_entry helper functions
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_error.c -- zip_error_t helper functions
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -67,30 +67,31 @@ zip_error_init_with_code(zip_error_t *error, int ze) {
|
||||
zip_error_init(error);
|
||||
error->zip_err = ze;
|
||||
switch (zip_error_system_type(error)) {
|
||||
case ZIP_ET_SYS:
|
||||
error->sys_err = errno;
|
||||
break;
|
||||
|
||||
default:
|
||||
error->sys_err = 0;
|
||||
break;
|
||||
case ZIP_ET_SYS:
|
||||
case ZIP_ET_LIBZIP:
|
||||
error->sys_err = errno;
|
||||
break;
|
||||
|
||||
default:
|
||||
error->sys_err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_system_type(const zip_error_t *error) {
|
||||
if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str)
|
||||
return ZIP_ET_NONE;
|
||||
if (error->zip_err < 0 || error->zip_err >= _zip_err_str_count)
|
||||
return ZIP_ET_NONE;
|
||||
|
||||
return _zip_err_type[error->zip_err];
|
||||
return _zip_err_str[error->zip_err].type;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_zip_error_clear(zip_error_t *err) {
|
||||
if (err == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
err->zip_err = ZIP_ER_OK;
|
||||
err->sys_err = 0;
|
||||
@ -100,7 +101,7 @@ _zip_error_clear(zip_error_t *err) {
|
||||
void
|
||||
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
|
||||
if (dst == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
dst->zip_err = src->zip_err;
|
||||
@ -111,12 +112,12 @@ _zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
|
||||
void
|
||||
_zip_error_get(const zip_error_t *err, int *zep, int *sep) {
|
||||
if (zep)
|
||||
*zep = err->zip_err;
|
||||
*zep = err->zip_err;
|
||||
if (sep) {
|
||||
if (zip_error_system_type(err) != ZIP_ET_NONE)
|
||||
*sep = err->sys_err;
|
||||
else
|
||||
*sep = 0;
|
||||
if (zip_error_system_type(err) != ZIP_ET_NONE)
|
||||
*sep = err->sys_err;
|
||||
else
|
||||
*sep = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,8 +125,8 @@ _zip_error_get(const zip_error_t *err, int *zep, int *sep) {
|
||||
void
|
||||
zip_error_set(zip_error_t *err, int ze, int se) {
|
||||
if (err) {
|
||||
err->zip_err = ze;
|
||||
err->sys_err = se;
|
||||
err->zip_err = ze;
|
||||
err->sys_err = se;
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +142,7 @@ zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) {
|
||||
int *e = (int *)data;
|
||||
|
||||
if (length < sizeof(int) * 2) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
e[0] = zip_error_code_zip(error);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_error_clear.c -- clear zip error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,7 +38,7 @@
|
||||
ZIP_EXTERN void
|
||||
zip_error_clear(zip_t *za) {
|
||||
if (za == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
_zip_error_clear(&za->error);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_error_get.c -- get zip error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_error_get_sys_type.c -- return type of system error code
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -37,8 +37,9 @@
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_error_get_sys_type(int ze) {
|
||||
if (ze < 0 || ze >= _zip_nerr_str)
|
||||
return 0;
|
||||
if (ze < 0 || ze >= _zip_err_str_count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _zip_err_type[ze];
|
||||
return _zip_err_str[ze].type;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_error_sterror.c -- get string representation of struct zip_error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -39,45 +39,70 @@
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_error_strerror(zip_error_t *err) {
|
||||
const char *zs, *ss;
|
||||
const char *zip_error_string, *system_error_string;
|
||||
char buf[128], *s;
|
||||
|
||||
zip_error_fini(err);
|
||||
|
||||
if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) {
|
||||
sprintf(buf, "Unknown error %d", err->zip_err);
|
||||
zs = NULL;
|
||||
ss = buf;
|
||||
if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) {
|
||||
snprintf(buf, sizeof(buf), "Unknown error %d", err->zip_err);
|
||||
buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
|
||||
zip_error_string = NULL;
|
||||
system_error_string = buf;
|
||||
}
|
||||
else {
|
||||
zs = _zip_err_str[err->zip_err];
|
||||
zip_error_string = _zip_err_str[err->zip_err].description;
|
||||
|
||||
switch (_zip_err_type[err->zip_err]) {
|
||||
case ZIP_ET_SYS:
|
||||
ss = strerror(err->sys_err);
|
||||
break;
|
||||
|
||||
case ZIP_ET_ZLIB:
|
||||
ss = zError(err->sys_err);
|
||||
break;
|
||||
|
||||
default:
|
||||
ss = NULL;
|
||||
}
|
||||
switch (_zip_err_str[err->zip_err].type) {
|
||||
case ZIP_ET_SYS:
|
||||
system_error_string = strerror(err->sys_err);
|
||||
break;
|
||||
|
||||
case ZIP_ET_ZLIB:
|
||||
system_error_string = zError(err->sys_err);
|
||||
break;
|
||||
|
||||
case ZIP_ET_LIBZIP: {
|
||||
zip_uint8_t error = GET_ERROR_FROM_DETAIL(err->sys_err);
|
||||
int index = GET_INDEX_FROM_DETAIL(err->sys_err);
|
||||
|
||||
if (error == 0) {
|
||||
system_error_string = NULL;
|
||||
}
|
||||
else if (error >= _zip_err_details_count) {
|
||||
snprintf(buf, sizeof(buf), "invalid detail error %u", error);
|
||||
buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
|
||||
system_error_string = buf;
|
||||
}
|
||||
else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) {
|
||||
snprintf(buf, sizeof(buf), "entry %d: %s", index, _zip_err_details[error].description);
|
||||
buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
|
||||
system_error_string = buf;
|
||||
}
|
||||
else {
|
||||
system_error_string = _zip_err_details[error].description;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
system_error_string = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ss == NULL)
|
||||
return zs;
|
||||
if (system_error_string == NULL) {
|
||||
return zip_error_string;
|
||||
}
|
||||
else {
|
||||
if ((s = (char *)malloc(strlen(ss) + (zs ? strlen(zs) + 2 : 0) + 1)) == NULL)
|
||||
return _zip_err_str[ZIP_ER_MEMORY];
|
||||
if ((s = (char *)malloc(strlen(system_error_string) + (zip_error_string ? strlen(zip_error_string) + 2 : 0) + 1)) == NULL) {
|
||||
return _zip_err_str[ZIP_ER_MEMORY].description;
|
||||
}
|
||||
|
||||
sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss);
|
||||
err->str = s;
|
||||
sprintf(s, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
|
||||
err->str = s;
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_error_to_str.c -- get string representation of zip error code
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -44,22 +44,23 @@ ZIP_EXTERN int
|
||||
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
|
||||
const char *zs, *ss;
|
||||
|
||||
if (ze < 0 || ze >= _zip_nerr_str)
|
||||
return snprintf(buf, len, "Unknown error %d", ze);
|
||||
if (ze < 0 || ze >= _zip_err_str_count) {
|
||||
return snprintf(buf, len, "Unknown error %d", ze);
|
||||
}
|
||||
|
||||
zs = _zip_err_str[ze];
|
||||
zs = _zip_err_str[ze].description;
|
||||
|
||||
switch (_zip_err_type[ze]) {
|
||||
case ZIP_ET_SYS:
|
||||
ss = strerror(se);
|
||||
break;
|
||||
|
||||
case ZIP_ET_ZLIB:
|
||||
ss = zError(se);
|
||||
break;
|
||||
|
||||
default:
|
||||
ss = NULL;
|
||||
switch (_zip_err_str[ze].type) {
|
||||
case ZIP_ET_SYS:
|
||||
ss = strerror(se);
|
||||
break;
|
||||
|
||||
case ZIP_ET_ZLIB:
|
||||
ss = zError(se);
|
||||
break;
|
||||
|
||||
default:
|
||||
ss = NULL;
|
||||
}
|
||||
|
||||
return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : ""));
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_extra_field.c -- manipulate extra fields
|
||||
Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -44,19 +44,19 @@ _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
|
||||
head = prev = NULL;
|
||||
|
||||
while (ef) {
|
||||
if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
_zip_ef_free(head);
|
||||
return NULL;
|
||||
}
|
||||
if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
_zip_ef_free(head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (head == NULL)
|
||||
head = def;
|
||||
if (prev)
|
||||
prev->next = def;
|
||||
prev = def;
|
||||
if (head == NULL)
|
||||
head = def;
|
||||
if (prev)
|
||||
prev->next = def;
|
||||
prev = def;
|
||||
|
||||
ef = ef->next;
|
||||
ef = ef->next;
|
||||
}
|
||||
|
||||
return head;
|
||||
@ -72,27 +72,27 @@ _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx
|
||||
head = ef;
|
||||
prev = NULL;
|
||||
for (; ef; ef = (prev ? prev->next : head)) {
|
||||
if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
|
||||
if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
|
||||
ef->flags &= ~(flags & ZIP_EF_BOTH);
|
||||
if ((ef->flags & ZIP_EF_BOTH) == 0) {
|
||||
if (prev)
|
||||
prev->next = ef->next;
|
||||
else
|
||||
head = ef->next;
|
||||
ef->next = NULL;
|
||||
_zip_ef_free(ef);
|
||||
if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
|
||||
if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
|
||||
ef->flags &= ~(flags & ZIP_EF_BOTH);
|
||||
if ((ef->flags & ZIP_EF_BOTH) == 0) {
|
||||
if (prev)
|
||||
prev->next = ef->next;
|
||||
else
|
||||
head = ef->next;
|
||||
ef->next = NULL;
|
||||
_zip_ef_free(ef);
|
||||
|
||||
if (id_idx == ZIP_EXTRA_FIELD_ALL)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (id_idx == ZIP_EXTRA_FIELD_ALL)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
if (i > id_idx)
|
||||
break;
|
||||
}
|
||||
prev = ef;
|
||||
i++;
|
||||
if (i > id_idx)
|
||||
break;
|
||||
}
|
||||
prev = ef;
|
||||
}
|
||||
|
||||
return head;
|
||||
@ -104,10 +104,10 @@ _zip_ef_free(zip_extra_field_t *ef) {
|
||||
zip_extra_field_t *ef2;
|
||||
|
||||
while (ef) {
|
||||
ef2 = ef->next;
|
||||
free(ef->data);
|
||||
free(ef);
|
||||
ef = ef2;
|
||||
ef2 = ef->next;
|
||||
free(ef->data);
|
||||
free(ef);
|
||||
ef = ef2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,19 +120,19 @@ _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t
|
||||
|
||||
i = 0;
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
|
||||
if (i < id_idx) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
|
||||
if (i < id_idx) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lenp)
|
||||
*lenp = ef->size;
|
||||
if (ef->size > 0)
|
||||
return ef->data;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
if (lenp)
|
||||
*lenp = ef->size;
|
||||
if (ef->size > 0)
|
||||
return ef->data;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
@ -146,28 +146,28 @@ _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
|
||||
int duplicate;
|
||||
|
||||
if (to == NULL)
|
||||
return from;
|
||||
return from;
|
||||
|
||||
for (tail = to; tail->next; tail = tail->next)
|
||||
;
|
||||
;
|
||||
|
||||
for (; from; from = ef2) {
|
||||
ef2 = from->next;
|
||||
ef2 = from->next;
|
||||
|
||||
duplicate = 0;
|
||||
for (tt = to; tt; tt = tt->next) {
|
||||
if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
|
||||
tt->flags |= (from->flags & ZIP_EF_BOTH);
|
||||
duplicate = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
duplicate = 0;
|
||||
for (tt = to; tt; tt = tt->next) {
|
||||
if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
|
||||
tt->flags |= (from->flags & ZIP_EF_BOTH);
|
||||
duplicate = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
from->next = NULL;
|
||||
if (duplicate)
|
||||
_zip_ef_free(from);
|
||||
else
|
||||
tail = tail->next = from;
|
||||
from->next = NULL;
|
||||
if (duplicate)
|
||||
_zip_ef_free(from);
|
||||
else
|
||||
tail = tail->next = from;
|
||||
}
|
||||
|
||||
return to;
|
||||
@ -179,20 +179,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
|
||||
zip_extra_field_t *ef;
|
||||
|
||||
if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ef->next = NULL;
|
||||
ef->flags = flags;
|
||||
ef->id = id;
|
||||
ef->size = size;
|
||||
if (size > 0) {
|
||||
if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
|
||||
free(ef);
|
||||
return NULL;
|
||||
}
|
||||
if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
|
||||
free(ef);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
ef->data = NULL;
|
||||
ef->data = NULL;
|
||||
|
||||
return ef;
|
||||
}
|
||||
@ -204,63 +204,63 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
|
||||
zip_extra_field_t *ef, *ef2, *ef_head;
|
||||
|
||||
if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
ef_head = ef = NULL;
|
||||
|
||||
while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
|
||||
zip_uint16_t fid, flen;
|
||||
zip_uint8_t *ef_data;
|
||||
zip_uint16_t fid, flen;
|
||||
zip_uint8_t *ef_data;
|
||||
|
||||
fid = _zip_buffer_get_16(buffer);
|
||||
flen = _zip_buffer_get_16(buffer);
|
||||
ef_data = _zip_buffer_get(buffer, flen);
|
||||
fid = _zip_buffer_get_16(buffer);
|
||||
flen = _zip_buffer_get_16(buffer);
|
||||
ef_data = _zip_buffer_get(buffer, flen);
|
||||
|
||||
if (ef_data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
_zip_buffer_free(buffer);
|
||||
_zip_ef_free(ef_head);
|
||||
return false;
|
||||
}
|
||||
if (ef_data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_EF_LENGTH);
|
||||
_zip_buffer_free(buffer);
|
||||
_zip_ef_free(ef_head);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
_zip_buffer_free(buffer);
|
||||
_zip_ef_free(ef_head);
|
||||
return false;
|
||||
}
|
||||
if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
_zip_buffer_free(buffer);
|
||||
_zip_ef_free(ef_head);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ef_head) {
|
||||
ef->next = ef2;
|
||||
ef = ef2;
|
||||
}
|
||||
else
|
||||
ef_head = ef = ef2;
|
||||
if (ef_head) {
|
||||
ef->next = ef2;
|
||||
ef = ef2;
|
||||
}
|
||||
else
|
||||
ef_head = ef = ef2;
|
||||
}
|
||||
|
||||
if (!_zip_buffer_eof(buffer)) {
|
||||
/* Android APK files align stored file data with padding in extra fields; ignore. */
|
||||
/* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
|
||||
size_t glen = _zip_buffer_left(buffer);
|
||||
zip_uint8_t *garbage;
|
||||
garbage = _zip_buffer_get(buffer, glen);
|
||||
if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, 0);
|
||||
_zip_buffer_free(buffer);
|
||||
_zip_ef_free(ef_head);
|
||||
return false;
|
||||
}
|
||||
/* Android APK files align stored file data with padding in extra fields; ignore. */
|
||||
/* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
|
||||
size_t glen = _zip_buffer_left(buffer);
|
||||
zip_uint8_t *garbage;
|
||||
garbage = _zip_buffer_get(buffer, glen);
|
||||
if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
|
||||
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE);
|
||||
_zip_buffer_free(buffer);
|
||||
_zip_ef_free(ef_head);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_zip_buffer_free(buffer);
|
||||
|
||||
if (ef_head_p) {
|
||||
*ef_head_p = ef_head;
|
||||
*ef_head_p = ef_head;
|
||||
}
|
||||
else {
|
||||
_zip_ef_free(ef_head);
|
||||
_zip_ef_free(ef_head);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -276,20 +276,20 @@ _zip_ef_remove_internal(zip_extra_field_t *ef) {
|
||||
prev = NULL;
|
||||
|
||||
while (ef) {
|
||||
if (ZIP_EF_IS_INTERNAL(ef->id)) {
|
||||
next = ef->next;
|
||||
if (ef_head == ef)
|
||||
ef_head = next;
|
||||
ef->next = NULL;
|
||||
_zip_ef_free(ef);
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
ef = next;
|
||||
}
|
||||
else {
|
||||
prev = ef;
|
||||
ef = ef->next;
|
||||
}
|
||||
if (ZIP_EF_IS_INTERNAL(ef->id)) {
|
||||
next = ef->next;
|
||||
if (ef_head == ef)
|
||||
ef_head = next;
|
||||
ef->next = NULL;
|
||||
_zip_ef_free(ef);
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
ef = next;
|
||||
}
|
||||
else {
|
||||
prev = ef;
|
||||
ef = ef->next;
|
||||
}
|
||||
}
|
||||
|
||||
return ef_head;
|
||||
@ -302,8 +302,8 @@ _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
|
||||
|
||||
size = 0;
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||
size = (zip_uint16_t)(size + 4 + ef->size);
|
||||
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||
size = (zip_uint16_t)(size + 4 + ef->size);
|
||||
}
|
||||
|
||||
return size;
|
||||
@ -316,30 +316,30 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
|
||||
zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
|
||||
|
||||
if (buffer == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->flags & flags & ZIP_EF_BOTH) {
|
||||
_zip_buffer_set_offset(buffer, 0);
|
||||
_zip_buffer_put_16(buffer, ef->id);
|
||||
_zip_buffer_put_16(buffer, ef->size);
|
||||
if (!_zip_buffer_ok(buffer)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
_zip_buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
if (_zip_write(za, b, 4) < 0) {
|
||||
_zip_buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
if (ef->size > 0) {
|
||||
if (_zip_write(za, ef->data, ef->size) < 0) {
|
||||
_zip_buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ef->flags & flags & ZIP_EF_BOTH) {
|
||||
_zip_buffer_set_offset(buffer, 0);
|
||||
_zip_buffer_put_16(buffer, ef->id);
|
||||
_zip_buffer_put_16(buffer, ef->size);
|
||||
if (!_zip_buffer_ok(buffer)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
_zip_buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
if (_zip_write(za, b, 4) < 0) {
|
||||
_zip_buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
if (ef->size > 0) {
|
||||
if (_zip_write(za, ef->data, ef->size) < 0) {
|
||||
_zip_buffer_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_zip_buffer_free(buffer);
|
||||
@ -355,71 +355,71 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
|
||||
zip_uint16_t fname_len, ef_len;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->orig == NULL || e->orig->local_extra_fields_read)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
if (e->orig->offset + 26 > ZIP_INT64_MAX) {
|
||||
zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fname_len = _zip_buffer_get_16(buffer);
|
||||
ef_len = _zip_buffer_get_16(buffer);
|
||||
|
||||
if (!_zip_buffer_eof(buffer)) {
|
||||
_zip_buffer_free(buffer);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
_zip_buffer_free(buffer);
|
||||
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_zip_buffer_free(buffer);
|
||||
|
||||
if (ef_len > 0) {
|
||||
zip_extra_field_t *ef;
|
||||
zip_uint8_t *ef_raw;
|
||||
zip_extra_field_t *ef;
|
||||
zip_uint8_t *ef_raw;
|
||||
|
||||
if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_SEEK, errno);
|
||||
return -1;
|
||||
}
|
||||
if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_SEEK, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
|
||||
ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
|
||||
|
||||
if (ef_raw == NULL)
|
||||
return -1;
|
||||
if (ef_raw == NULL)
|
||||
return -1;
|
||||
|
||||
if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
|
||||
free(ef_raw);
|
||||
return -1;
|
||||
}
|
||||
free(ef_raw);
|
||||
if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
|
||||
free(ef_raw);
|
||||
return -1;
|
||||
}
|
||||
free(ef_raw);
|
||||
|
||||
if (ef) {
|
||||
ef = _zip_ef_remove_internal(ef);
|
||||
e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
|
||||
}
|
||||
if (ef) {
|
||||
ef = _zip_ef_remove_internal(ef);
|
||||
e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
|
||||
}
|
||||
}
|
||||
|
||||
e->orig->local_extra_fields_read = 1;
|
||||
|
||||
if (e->changes && e->changes->local_extra_fields_read == 0) {
|
||||
e->changes->extra_fields = e->orig->extra_fields;
|
||||
e->changes->local_extra_fields_read = 1;
|
||||
e->changes->extra_fields = e->orig->extra_fields;
|
||||
e->changes->local_extra_fields_read = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_extra_field_api.c -- public extra fields API functions
|
||||
Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,25 +40,25 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
de = za->entry[idx].changes;
|
||||
|
||||
@ -72,25 +72,25 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
de = za->entry[idx].changes;
|
||||
|
||||
@ -108,34 +108,34 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
|
||||
int i;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return NULL;
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
for (ef = de->extra_fields; ef; ef = ef->next) {
|
||||
if (ef->flags & flags & ZIP_EF_BOTH) {
|
||||
if (i < ef_idx) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (ef->flags & flags & ZIP_EF_BOTH) {
|
||||
if (i < ef_idx) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (idp)
|
||||
*idp = ef->id;
|
||||
if (lenp)
|
||||
*lenp = ef->size;
|
||||
if (ef->size > 0)
|
||||
return ef->data;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
if (idp)
|
||||
*idp = ef->id;
|
||||
if (lenp)
|
||||
*lenp = ef->size;
|
||||
if (ef->size > 0)
|
||||
return ef->data;
|
||||
else
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(&za->error, ZIP_ER_NOENT, 0);
|
||||
@ -148,16 +148,16 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id,
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return NULL;
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return NULL;
|
||||
|
||||
return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error);
|
||||
}
|
||||
@ -170,21 +170,21 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
|
||||
zip_uint16_t n;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return -1;
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return -1;
|
||||
|
||||
n = 0;
|
||||
for (ef = de->extra_fields; ef; ef = ef->next)
|
||||
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||
n++;
|
||||
if (ef->flags & flags & ZIP_EF_BOTH)
|
||||
n++;
|
||||
|
||||
return (zip_int16_t)n;
|
||||
}
|
||||
@ -197,21 +197,21 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
|
||||
zip_uint16_t n;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (flags & ZIP_FL_LOCAL)
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return -1;
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return -1;
|
||||
|
||||
n = 0;
|
||||
for (ef = de->extra_fields; ef; ef = ef->next)
|
||||
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
|
||||
n++;
|
||||
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
|
||||
n++;
|
||||
|
||||
return (zip_int16_t)n;
|
||||
}
|
||||
@ -225,25 +225,25 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
|
||||
int i, found, new_len;
|
||||
|
||||
if ((flags & ZIP_EF_BOTH) == 0) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_EF_IS_INTERNAL(ef_id)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
de = za->entry[idx].changes;
|
||||
|
||||
@ -253,67 +253,67 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
|
||||
found = 0;
|
||||
|
||||
for (; ef; ef = ef->next) {
|
||||
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
|
||||
if (i == ef_idx) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ef_prev = ef;
|
||||
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
|
||||
if (i == ef_idx) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
ef_prev = ef;
|
||||
}
|
||||
|
||||
if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & ZIP_EF_LOCAL)
|
||||
ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
|
||||
ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
|
||||
else
|
||||
ls = 0;
|
||||
ls = 0;
|
||||
if (flags & ZIP_EF_CENTRAL)
|
||||
cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
|
||||
cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
|
||||
else
|
||||
cs = 0;
|
||||
cs = 0;
|
||||
|
||||
new_len = ls > cs ? ls : cs;
|
||||
if (found)
|
||||
new_len -= ef->size + 4;
|
||||
new_len -= ef->size + 4;
|
||||
new_len += len + 4;
|
||||
|
||||
if (new_len > ZIP_UINT16_MAX) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
|
||||
ef_new->next = ef->next;
|
||||
ef->next = NULL;
|
||||
_zip_ef_free(ef);
|
||||
if (ef_prev)
|
||||
ef_prev->next = ef_new;
|
||||
else
|
||||
de->extra_fields = ef_new;
|
||||
}
|
||||
else {
|
||||
ef->flags &= ~(flags & ZIP_EF_BOTH);
|
||||
ef_new->next = ef->next;
|
||||
ef->next = ef_new;
|
||||
}
|
||||
if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
|
||||
ef_new->next = ef->next;
|
||||
ef->next = NULL;
|
||||
_zip_ef_free(ef);
|
||||
if (ef_prev)
|
||||
ef_prev->next = ef_new;
|
||||
else
|
||||
de->extra_fields = ef_new;
|
||||
}
|
||||
else {
|
||||
ef->flags &= ~(flags & ZIP_EF_BOTH);
|
||||
ef_new->next = ef->next;
|
||||
ef->next = ef_new;
|
||||
}
|
||||
}
|
||||
else if (ef_prev) {
|
||||
ef_new->next = ef_prev->next;
|
||||
ef_prev->next = ef_new;
|
||||
ef_new->next = ef_prev->next;
|
||||
ef_prev->next = ef_new;
|
||||
}
|
||||
else
|
||||
de->extra_fields = ef_new;
|
||||
de->extra_fields = ef_new;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -324,30 +324,30 @@ _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) {
|
||||
zip_entry_t *e;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
if (e->orig) {
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return -1;
|
||||
if (_zip_read_local_ef(za, idx) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->orig && e->orig->extra_fields) {
|
||||
if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
|
||||
return -1;
|
||||
}
|
||||
e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fclose.c -- close file in zip archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -42,11 +42,11 @@ zip_fclose(zip_file_t *zf) {
|
||||
int ret;
|
||||
|
||||
if (zf->src)
|
||||
zip_source_free(zf->src);
|
||||
zip_source_free(zf->src);
|
||||
|
||||
ret = 0;
|
||||
if (zf->error.zip_err)
|
||||
ret = zf->error.zip_err;
|
||||
ret = zf->error.zip_err;
|
||||
|
||||
zip_error_fini(&zf->error);
|
||||
free(zf);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fdopen.c -- open read-only archive from file descriptor
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -47,37 +47,37 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
|
||||
struct zip_error error;
|
||||
|
||||
if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
|
||||
return NULL;
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We dup() here to avoid messing with the passed in fd.
|
||||
We could not restore it to the original state in case of error. */
|
||||
|
||||
if ((fd = dup(fd_orig)) < 0) {
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
|
||||
return NULL;
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((fp = fdopen(fd, "rb")) == NULL) {
|
||||
close(fd);
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
|
||||
return NULL;
|
||||
close(fd);
|
||||
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_error_init(&error);
|
||||
if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) {
|
||||
fclose(fp);
|
||||
_zip_set_open_error(zep, &error, 0);
|
||||
zip_error_fini(&error);
|
||||
return NULL;
|
||||
fclose(fp);
|
||||
_zip_set_open_error(zep, &error, 0);
|
||||
zip_error_fini(&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
|
||||
zip_source_free(src);
|
||||
_zip_set_open_error(zep, &error, 0);
|
||||
zip_error_fini(&error);
|
||||
return NULL;
|
||||
zip_source_free(src);
|
||||
_zip_set_open_error(zep, &error, 0);
|
||||
zip_error_fini(&error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_error_fini(&error);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_add.c -- add file via callback function
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -36,16 +36,16 @@
|
||||
|
||||
/*
|
||||
NOTE: Return type is signed so we can return -1 on error.
|
||||
The index can not be larger than ZIP_INT64_MAX since the size
|
||||
of the central directory cannot be larger than
|
||||
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
|
||||
The index can not be larger than ZIP_INT64_MAX since the size
|
||||
of the central directory cannot be larger than
|
||||
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
|
||||
*/
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags) {
|
||||
if (name == NULL || source == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_error_clear.c -- clear zip file error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,7 +38,7 @@
|
||||
ZIP_EXTERN void
|
||||
zip_file_error_clear(zip_file_t *zf) {
|
||||
if (zf == NULL)
|
||||
return;
|
||||
return;
|
||||
|
||||
_zip_error_clear(&zf->error);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_error_get.c -- get zip file error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_get_comment.c -- get file comment
|
||||
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -43,13 +43,13 @@ zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_
|
||||
const zip_uint8_t *str;
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (lenp)
|
||||
*lenp = len;
|
||||
*lenp = len;
|
||||
|
||||
return (const char *)str;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_get_external_attributes.c -- get opsys/external attributes
|
||||
Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,13 +38,13 @@ zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
|
||||
zip_dirent_t *de;
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (opsys)
|
||||
*opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
|
||||
*opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
|
||||
|
||||
if (attributes)
|
||||
*attributes = de->ext_attrib;
|
||||
*attributes = de->ext_attrib;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_get_offset.c -- get offset of file data in archive.
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -50,24 +50,24 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
|
||||
zip_int32_t size;
|
||||
|
||||
if (za->entry[idx].orig == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return 0;
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = za->entry[idx].orig->offset;
|
||||
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: cache? */
|
||||
if ((size = _zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return offset + (zip_uint32_t)size;
|
||||
@ -79,38 +79,38 @@ _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
|
||||
zip_dirent_t *entry;
|
||||
|
||||
if ((offset = _zip_file_get_offset(za, index, error)) == 0) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry = za->entry[index].orig;
|
||||
|
||||
if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
}
|
||||
offset += entry->comp_size;
|
||||
|
||||
if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
|
||||
zip_uint8_t buf[4];
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
if (zip_source_read(za->src, buf, 4) != 4) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
|
||||
offset += 4;
|
||||
}
|
||||
offset += 12;
|
||||
if (_zip_dirent_needs_zip64(entry, 0)) {
|
||||
offset += 8;
|
||||
}
|
||||
if (offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
}
|
||||
zip_uint8_t buf[4];
|
||||
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
if (zip_source_read(za->src, buf, 4) != 4) {
|
||||
_zip_error_set_from_source(error, za->src);
|
||||
return 0;
|
||||
}
|
||||
if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
|
||||
offset += 4;
|
||||
}
|
||||
offset += 12;
|
||||
if (_zip_dirent_needs_zip64(entry, 0)) {
|
||||
offset += 8;
|
||||
}
|
||||
if (offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_rename.c -- rename file in zip archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -43,24 +43,24 @@ zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags
|
||||
int old_is_dir, new_is_dir;
|
||||
|
||||
if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((old_name = zip_get_name(za, idx, 0)) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
new_is_dir = (name != NULL && name[strlen(name) - 1] == '/');
|
||||
old_is_dir = (old_name[strlen(old_name) - 1] == '/');
|
||||
|
||||
if (new_is_dir != old_is_dir) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _zip_set_name(za, idx, name, flags);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_replace.c -- replace file via callback function
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,12 +38,12 @@
|
||||
ZIP_EXTERN int
|
||||
zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags) {
|
||||
if (idx >= za->nentry || source == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -56,31 +56,31 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
|
||||
zip_uint64_t za_nentry_prev;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
za_nentry_prev = za->nentry;
|
||||
if (idx == ZIP_UINT64_MAX) {
|
||||
zip_int64_t i = -1;
|
||||
zip_int64_t i = -1;
|
||||
|
||||
if (flags & ZIP_FL_OVERWRITE)
|
||||
i = _zip_name_locate(za, name, flags, NULL);
|
||||
if (flags & ZIP_FL_OVERWRITE)
|
||||
i = _zip_name_locate(za, name, flags, NULL);
|
||||
|
||||
if (i == -1) {
|
||||
/* create and use new entry, used by zip_add */
|
||||
if ((i = _zip_add_entry(za)) < 0)
|
||||
return -1;
|
||||
}
|
||||
idx = (zip_uint64_t)i;
|
||||
if (i == -1) {
|
||||
/* create and use new entry, used by zip_add */
|
||||
if ((i = _zip_add_entry(za)) < 0)
|
||||
return -1;
|
||||
}
|
||||
idx = (zip_uint64_t)i;
|
||||
}
|
||||
|
||||
if (name && _zip_set_name(za, idx, name, flags) != 0) {
|
||||
if (za->nentry != za_nentry_prev) {
|
||||
_zip_entry_finalize(za->entry + idx);
|
||||
za->nentry = za_nentry_prev;
|
||||
}
|
||||
return -1;
|
||||
if (za->nentry != za_nentry_prev) {
|
||||
_zip_entry_finalize(za->entry + idx);
|
||||
za->nentry = za_nentry_prev;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* does not change any name related data, so we can do it here;
|
||||
@ -88,15 +88,15 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
|
||||
_zip_unchange_data(za->entry + idx);
|
||||
|
||||
if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) {
|
||||
if (za->entry[idx].changes == NULL) {
|
||||
if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (za->entry[idx].changes == NULL) {
|
||||
if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
|
||||
za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
|
||||
za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
}
|
||||
|
||||
za->entry[idx].source = source;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_set_comment.c -- set comment for file in archive
|
||||
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -44,57 +44,57 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint1
|
||||
int changed;
|
||||
|
||||
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > 0 && comment == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
|
||||
cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
|
||||
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
|
||||
cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
|
||||
}
|
||||
else
|
||||
cstr = NULL;
|
||||
cstr = NULL;
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->changes) {
|
||||
_zip_string_free(e->changes->comment);
|
||||
e->changes->comment = NULL;
|
||||
e->changes->changed &= ~ZIP_DIRENT_COMMENT;
|
||||
_zip_string_free(e->changes->comment);
|
||||
e->changes->comment = NULL;
|
||||
e->changes->changed &= ~ZIP_DIRENT_COMMENT;
|
||||
}
|
||||
|
||||
if (e->orig && e->orig->comment)
|
||||
changed = !_zip_string_equal(e->orig->comment, cstr);
|
||||
changed = !_zip_string_equal(e->orig->comment, cstr);
|
||||
else
|
||||
changed = (cstr != NULL);
|
||||
changed = (cstr != NULL);
|
||||
|
||||
if (changed) {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
_zip_string_free(cstr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
e->changes->comment = cstr;
|
||||
e->changes->changed |= ZIP_DIRENT_COMMENT;
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
_zip_string_free(cstr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
e->changes->comment = cstr;
|
||||
e->changes->changed |= ZIP_DIRENT_COMMENT;
|
||||
}
|
||||
else {
|
||||
_zip_string_free(cstr);
|
||||
if (e->changes && e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
_zip_string_free(cstr);
|
||||
if (e->changes && e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
116
src/Common/libzip/zip_file_set_encryption.c
Normal file
116
src/Common/libzip/zip_file_set_encryption.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
zip_file_set_encryption.c -- set encryption for file in archive
|
||||
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) {
|
||||
zip_entry_t *e;
|
||||
zip_uint16_t old_method;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method);
|
||||
|
||||
if (method == old_method && password == NULL) {
|
||||
if (e->changes) {
|
||||
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
|
||||
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
|
||||
free(e->changes->password);
|
||||
e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
|
||||
}
|
||||
e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *our_password = NULL;
|
||||
|
||||
if (password) {
|
||||
if ((our_password = strdup(password)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
if (our_password) {
|
||||
_zip_crypto_clear(our_password, strlen(our_password));
|
||||
}
|
||||
free(our_password);
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->encryption_method = method;
|
||||
e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
|
||||
if (password) {
|
||||
e->changes->password = our_password;
|
||||
e->changes->changed |= ZIP_DIRENT_PASSWORD;
|
||||
}
|
||||
else {
|
||||
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
|
||||
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
|
||||
free(e->changes->password);
|
||||
e->changes->password = e->orig ? e->orig->password : NULL;
|
||||
e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_set_external_attributes.c -- set external attributes for entry
|
||||
Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -41,11 +41,11 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
|
||||
zip_uint32_t unchanged_attributes;
|
||||
|
||||
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
@ -56,26 +56,26 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
|
||||
changed = (opsys != unchanged_opsys || attributes != unchanged_attributes);
|
||||
|
||||
if (changed) {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
|
||||
e->changes->ext_attrib = attributes;
|
||||
e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
|
||||
e->changes->ext_attrib = attributes;
|
||||
e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
|
||||
}
|
||||
else if (e->changes) {
|
||||
e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
else {
|
||||
e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
|
||||
e->changes->ext_attrib = unchanged_attributes;
|
||||
}
|
||||
e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
else {
|
||||
e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
|
||||
e->changes->ext_attrib = unchanged_attributes;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_set_mtime.c -- set modification time of entry.
|
||||
Copyright (C) 2014-2020 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2014-2022 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -45,20 +45,25 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
|
||||
zip_entry_t *e;
|
||||
|
||||
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->orig != NULL && e->orig->encryption_method == ZIP_EM_TRAD_PKWARE && !ZIP_ENTRY_CHANGED(e, ZIP_DIRENT_ENCRYPTION_METHOD) && !ZIP_ENTRY_DATA_CHANGED(e)) {
|
||||
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->last_mod = mtime;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_file_sterror.c -- get string representation of zip file error
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fopen.c -- open file in zip archive for reading
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,7 +40,7 @@ zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) {
|
||||
zip_int64_t idx;
|
||||
|
||||
if ((idx = zip_name_locate(za, fname, flags)) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fopen_encrypted.c -- open file for reading with password
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,7 +40,7 @@ zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char
|
||||
zip_int64_t idx;
|
||||
|
||||
if ((idx = zip_name_locate(za, fname, flags)) < 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fopen_index.c -- open file in zip archive for reading by index
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fopen_index_encrypted.c -- open file for reading by index w/ password
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -45,18 +45,22 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, cons
|
||||
zip_file_t *zf;
|
||||
zip_source_t *src;
|
||||
|
||||
if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
|
||||
return NULL;
|
||||
if (password != NULL && password[0] == '\0') {
|
||||
password = NULL;
|
||||
}
|
||||
|
||||
if ((src = _zip_source_zip_new(za, index, flags, 0, 0, password, &za->error)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (zip_source_open(src) < 0) {
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
zip_source_free(src);
|
||||
return NULL;
|
||||
_zip_error_set_from_source(&za->error, src);
|
||||
zip_source_free(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((zf = _zip_file_new(za)) == NULL) {
|
||||
zip_source_free(src);
|
||||
return NULL;
|
||||
zip_source_free(src);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zf->src = src;
|
||||
@ -70,8 +74,8 @@ _zip_file_new(zip_t *za) {
|
||||
zip_file_t *zf;
|
||||
|
||||
if ((zf = (zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zf->za = za;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_fread.c -- read from file
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,22 +40,22 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
|
||||
zip_int64_t n;
|
||||
|
||||
if (!zf)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (zf->error.zip_err != 0)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (toread > ZIP_INT64_MAX) {
|
||||
zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((zf->eof) || (toread == 0))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) {
|
||||
_zip_error_set_from_source(&zf->error, zf->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&zf->error, zf->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
61
src/Common/libzip/zip_fseek.c
Normal file
61
src/Common/libzip/zip_fseek.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
zip_fseek.c -- seek in file
|
||||
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
ZIP_EXTERN zip_int8_t
|
||||
zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) {
|
||||
if (!zf)
|
||||
return -1;
|
||||
|
||||
if (zf->error.zip_err != 0)
|
||||
return -1;
|
||||
|
||||
if (zip_source_seek(zf->src, offset, whence) < 0) {
|
||||
_zip_error_set_from_source(&zf->error, zf->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_file_is_seekable(zip_file_t *zfile) {
|
||||
if (!zfile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ZIP_SOURCE_CHECK_SUPPORTED(zip_source_supports(zfile->src), ZIP_SOURCE_SEEK);
|
||||
}
|
54
src/Common/libzip/zip_ftell.c
Normal file
54
src/Common/libzip/zip_ftell.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
zip_ftell.c -- tell position in file
|
||||
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
ZIP_EXTERN zip_int64_t
|
||||
zip_ftell(zip_file_t *zf) {
|
||||
zip_int64_t res;
|
||||
|
||||
if (!zf)
|
||||
return -1;
|
||||
|
||||
if (zf->error.zip_err != 0)
|
||||
return -1;
|
||||
|
||||
res = zip_source_tell(zf->src);
|
||||
if (res < 0) {
|
||||
_zip_error_set_from_source(&zf->error, zf->src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_archive_comment.c -- get archive comment
|
||||
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -44,15 +44,15 @@ zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
|
||||
const zip_uint8_t *str;
|
||||
|
||||
if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
|
||||
comment = za->comment_orig;
|
||||
comment = za->comment_orig;
|
||||
else
|
||||
comment = za->comment_changes;
|
||||
comment = za->comment_changes;
|
||||
|
||||
if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if (lenp)
|
||||
*lenp = (int)len;
|
||||
*lenp = (int)len;
|
||||
|
||||
return (const char *)str;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_archive_flag.c -- get archive global flag
|
||||
Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_encryption_implementation.c -- get encryption implementation
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -39,24 +39,24 @@ zip_encryption_implementation
|
||||
_zip_get_encryption_implementation(zip_uint16_t em, int operation) {
|
||||
switch (em) {
|
||||
case ZIP_EM_TRAD_PKWARE:
|
||||
return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
|
||||
return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
|
||||
|
||||
#if defined(HAVE_CRYPTO)
|
||||
case ZIP_EM_AES_128:
|
||||
case ZIP_EM_AES_192:
|
||||
case ZIP_EM_AES_256:
|
||||
return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
|
||||
return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ZIP_EXTERN int
|
||||
zip_encryption_method_supported(zip_uint16_t method, int encode) {
|
||||
if (method == ZIP_EM_NONE) {
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_file_comment.c -- get file comment
|
||||
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -42,8 +42,8 @@ zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) {
|
||||
const char *s;
|
||||
|
||||
if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
|
||||
if (lenp)
|
||||
*lenp = (int)len;
|
||||
if (lenp)
|
||||
*lenp = (int)len;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_name.c -- get filename for a file in zip file
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -49,10 +49,10 @@ _zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error
|
||||
const zip_uint8_t *str;
|
||||
|
||||
if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return (const char *)str;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_num_entries.c -- get number of entries in archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,13 +40,13 @@ zip_get_num_entries(zip_t *za, zip_flags_t flags) {
|
||||
zip_uint64_t n;
|
||||
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
n = za->nentry;
|
||||
while (n > 0 && za->entry[n - 1].orig == NULL)
|
||||
--n;
|
||||
return (zip_int64_t)n;
|
||||
n = za->nentry;
|
||||
while (n > 0 && za->entry[n - 1].orig == NULL)
|
||||
--n;
|
||||
return (zip_int64_t)n;
|
||||
}
|
||||
return (zip_int64_t)za->nentry;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_num_files.c -- get number of files in archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,11 +40,11 @@
|
||||
ZIP_EXTERN int
|
||||
zip_get_num_files(zip_t *za) {
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (za->nentry > INT_MAX) {
|
||||
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)za->nentry;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_hash.c -- hash table string -> uint64
|
||||
Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -67,9 +67,9 @@ struct zip_hash {
|
||||
static void
|
||||
free_list(zip_hash_entry_t *entry) {
|
||||
while (entry != NULL) {
|
||||
zip_hash_entry_t *next = entry->next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
zip_hash_entry_t *next = entry->next;
|
||||
free(entry);
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +80,12 @@ hash_string(const zip_uint8_t *name) {
|
||||
zip_uint64_t value = HASH_START;
|
||||
|
||||
if (name == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*name != 0) {
|
||||
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
|
||||
name++;
|
||||
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
|
||||
name++;
|
||||
}
|
||||
|
||||
return (zip_uint32_t)value;
|
||||
@ -98,30 +98,30 @@ hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) {
|
||||
zip_hash_entry_t **new_table;
|
||||
|
||||
if (new_size == hash->table_size) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((new_table = (zip_hash_entry_t **)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hash->nentries > 0) {
|
||||
zip_uint32_t i;
|
||||
zip_uint32_t i;
|
||||
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
zip_hash_entry_t *entry = hash->table[i];
|
||||
while (entry) {
|
||||
zip_hash_entry_t *next = entry->next;
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
zip_hash_entry_t *entry = hash->table[i];
|
||||
while (entry) {
|
||||
zip_hash_entry_t *next = entry->next;
|
||||
|
||||
zip_uint32_t new_index = entry->hash_value % new_size;
|
||||
zip_uint32_t new_index = entry->hash_value % new_size;
|
||||
|
||||
entry->next = new_table[new_index];
|
||||
new_table[new_index] = entry;
|
||||
entry->next = new_table[new_index];
|
||||
new_table[new_index] = entry;
|
||||
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
entry = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(hash->table);
|
||||
@ -138,14 +138,14 @@ size_for_capacity(zip_uint64_t capacity) {
|
||||
zip_uint32_t v;
|
||||
|
||||
if (needed_size > ZIP_UINT32_MAX) {
|
||||
v = ZIP_UINT32_MAX;
|
||||
v = ZIP_UINT32_MAX;
|
||||
}
|
||||
else {
|
||||
v = (zip_uint32_t)needed_size;
|
||||
v = (zip_uint32_t)needed_size;
|
||||
}
|
||||
|
||||
if (v > HASH_MAX_SIZE) {
|
||||
return HASH_MAX_SIZE;
|
||||
return HASH_MAX_SIZE;
|
||||
}
|
||||
|
||||
/* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
|
||||
@ -168,8 +168,8 @@ _zip_hash_new(zip_error_t *error) {
|
||||
zip_hash_t *hash;
|
||||
|
||||
if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hash->table_size = 0;
|
||||
@ -185,16 +185,16 @@ _zip_hash_free(zip_hash_t *hash) {
|
||||
zip_uint32_t i;
|
||||
|
||||
if (hash == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hash->table != NULL) {
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
if (hash->table[i] != NULL) {
|
||||
free_list(hash->table[i]);
|
||||
}
|
||||
}
|
||||
free(hash->table);
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
if (hash->table[i] != NULL) {
|
||||
free_list(hash->table[i]);
|
||||
}
|
||||
}
|
||||
free(hash->table);
|
||||
}
|
||||
free(hash);
|
||||
}
|
||||
@ -207,51 +207,51 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
|
||||
zip_hash_entry_t *entry;
|
||||
|
||||
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hash->table_size == 0) {
|
||||
if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
|
||||
return false;
|
||||
}
|
||||
if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hash_value = hash_string(name);
|
||||
table_index = hash_value % hash->table_size;
|
||||
|
||||
for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) {
|
||||
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
|
||||
zip_error_set(error, ZIP_ER_EXISTS, 0);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
|
||||
zip_error_set(error, ZIP_ER_EXISTS, 0);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
entry->name = name;
|
||||
entry->next = hash->table[table_index];
|
||||
hash->table[table_index] = entry;
|
||||
entry->hash_value = hash_value;
|
||||
entry->orig_index = -1;
|
||||
hash->nentries++;
|
||||
if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
|
||||
if (!hash_resize(hash, hash->table_size * 2, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
entry->name = name;
|
||||
entry->next = hash->table[table_index];
|
||||
hash->table[table_index] = entry;
|
||||
entry->hash_value = hash_value;
|
||||
entry->orig_index = -1;
|
||||
hash->nentries++;
|
||||
if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
|
||||
if (!hash_resize(hash, hash->table_size * 2, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
entry->orig_index = (zip_int64_t)index;
|
||||
entry->orig_index = (zip_int64_t)index;
|
||||
}
|
||||
entry->current_index = (zip_int64_t)index;
|
||||
|
||||
@ -266,40 +266,40 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
|
||||
zip_hash_entry_t *entry, *previous;
|
||||
|
||||
if (hash == NULL || name == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hash->nentries > 0) {
|
||||
hash_value = hash_string(name);
|
||||
index = hash_value % hash->table_size;
|
||||
previous = NULL;
|
||||
entry = hash->table[index];
|
||||
while (entry) {
|
||||
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (entry->orig_index == -1) {
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
}
|
||||
else {
|
||||
hash->table[index] = entry->next;
|
||||
}
|
||||
free(entry);
|
||||
hash->nentries--;
|
||||
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
|
||||
if (!hash_resize(hash, hash->table_size / 2, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
entry->current_index = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
hash_value = hash_string(name);
|
||||
index = hash_value % hash->table_size;
|
||||
previous = NULL;
|
||||
entry = hash->table[index];
|
||||
while (entry) {
|
||||
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (entry->orig_index == -1) {
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
}
|
||||
else {
|
||||
hash->table[index] = entry->next;
|
||||
}
|
||||
free(entry);
|
||||
hash->nentries--;
|
||||
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
|
||||
if (!hash_resize(hash, hash->table_size / 2, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
entry->current_index = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
@ -314,28 +314,28 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z
|
||||
zip_hash_entry_t *entry;
|
||||
|
||||
if (hash == NULL || name == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hash->nentries > 0) {
|
||||
hash_value = hash_string(name);
|
||||
index = hash_value % hash->table_size;
|
||||
for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
|
||||
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
if (entry->orig_index != -1) {
|
||||
return entry->orig_index;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (entry->current_index != -1) {
|
||||
return entry->current_index;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
hash_value = hash_string(name);
|
||||
index = hash_value % hash->table_size;
|
||||
for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
|
||||
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
|
||||
if (flags & ZIP_FL_UNCHANGED) {
|
||||
if (entry->orig_index != -1) {
|
||||
return entry->orig_index;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (entry->current_index != -1) {
|
||||
return entry->current_index;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
@ -348,17 +348,17 @@ _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t
|
||||
zip_uint32_t new_size;
|
||||
|
||||
if (capacity == 0) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
new_size = size_for_capacity(capacity);
|
||||
|
||||
if (new_size <= hash->table_size) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hash_resize(hash, new_size, error)) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -371,39 +371,39 @@ _zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
|
||||
zip_hash_entry_t *entry, *previous;
|
||||
|
||||
for (i = 0; i < hash->table_size; i++) {
|
||||
previous = NULL;
|
||||
entry = hash->table[i];
|
||||
while (entry) {
|
||||
if (entry->orig_index == -1) {
|
||||
zip_hash_entry_t *p;
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
}
|
||||
else {
|
||||
hash->table[i] = entry->next;
|
||||
}
|
||||
p = entry;
|
||||
entry = entry->next;
|
||||
/* previous does not change */
|
||||
free(p);
|
||||
hash->nentries--;
|
||||
}
|
||||
else {
|
||||
entry->current_index = entry->orig_index;
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
previous = NULL;
|
||||
entry = hash->table[i];
|
||||
while (entry) {
|
||||
if (entry->orig_index == -1) {
|
||||
zip_hash_entry_t *p;
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
}
|
||||
else {
|
||||
hash->table[i] = entry->next;
|
||||
}
|
||||
p = entry;
|
||||
entry = entry->next;
|
||||
/* previous does not change */
|
||||
free(p);
|
||||
hash->nentries--;
|
||||
}
|
||||
else {
|
||||
entry->current_index = entry->orig_index;
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
|
||||
zip_uint32_t new_size = hash->table_size / 2;
|
||||
while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
|
||||
new_size /= 2;
|
||||
}
|
||||
if (!hash_resize(hash, new_size, error)) {
|
||||
return false;
|
||||
}
|
||||
zip_uint32_t new_size = hash->table_size / 2;
|
||||
while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
|
||||
new_size /= 2;
|
||||
}
|
||||
if (!hash_resize(hash, new_size, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_io_util.c -- I/O helper functions
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -41,18 +41,18 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e
|
||||
zip_int64_t n;
|
||||
|
||||
if (length > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((n = zip_source_read(src, b, length)) < 0) {
|
||||
_zip_error_set_from_source(error, src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (n < (zip_int64_t)length) {
|
||||
zip_error_set(error, ZIP_ER_EOF, 0);
|
||||
return -1;
|
||||
zip_error_set(error, ZIP_ER_EOF, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -64,39 +64,39 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
|
||||
zip_uint8_t *r;
|
||||
|
||||
if (length == 0 && !nulp) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
|
||||
if (!r) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, length);
|
||||
zip_uint8_t *data = _zip_buffer_get(buffer, length);
|
||||
|
||||
if (data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(r, data, length);
|
||||
if (data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(r, data, length);
|
||||
}
|
||||
else {
|
||||
if (_zip_read(src, r, length, error) < 0) {
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
if (_zip_read(src, r, length, error) < 0) {
|
||||
free(r);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (nulp) {
|
||||
zip_uint8_t *o;
|
||||
/* replace any in-string NUL characters with spaces */
|
||||
r[length] = 0;
|
||||
for (o = r; o < r + length; o++)
|
||||
if (*o == '\0')
|
||||
*o = ' ';
|
||||
zip_uint8_t *o;
|
||||
/* replace any in-string NUL characters with spaces */
|
||||
r[length] = 0;
|
||||
for (o = r; o < r + length; o++)
|
||||
if (*o == '\0')
|
||||
*o = ' ';
|
||||
}
|
||||
|
||||
return r;
|
||||
@ -109,7 +109,7 @@ _zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool
|
||||
zip_string_t *s;
|
||||
|
||||
if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
|
||||
free(raw);
|
||||
@ -122,12 +122,12 @@ _zip_write(zip_t *za, const void *data, zip_uint64_t length) {
|
||||
zip_int64_t n;
|
||||
|
||||
if ((n = zip_source_write(za->src, data, length)) < 0) {
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
_zip_error_set_from_source(&za->error, za->src);
|
||||
return -1;
|
||||
}
|
||||
if ((zip_uint64_t)n != length) {
|
||||
zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
41
src/Common/libzip/zip_libzip_version.c
Normal file
41
src/Common/libzip/zip_libzip_version.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
zip_libzip_version.c -- return run-time version of library
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
|
||||
ZIP_EXTERN const char *
|
||||
zip_libzip_version(void) {
|
||||
return LIBZIP_VERSION;
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_memdup.c -- internal zip function, "strdup" with len
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -42,12 +42,12 @@ _zip_memdup(const void *mem, size_t len, zip_error_t *error) {
|
||||
void *ret;
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
ret = malloc(len);
|
||||
if (!ret) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(ret, mem, len);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_name_locate.c -- get index by name
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -49,44 +49,59 @@ zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) {
|
||||
zip_int64_t
|
||||
_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) {
|
||||
int (*cmp)(const char *, const char *);
|
||||
zip_string_t *str = NULL;
|
||||
const char *fn, *p;
|
||||
zip_uint64_t i;
|
||||
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
if (fname == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_CP437)) {
|
||||
/* can't use hash table */
|
||||
cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
|
||||
if ((flags & (ZIP_FL_ENC_UTF_8 | ZIP_FL_ENC_RAW)) == 0 && fname[0] != '\0') {
|
||||
if ((str = _zip_string_new((const zip_uint8_t *)fname, strlen(fname), flags, error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if ((fname = (const char *)_zip_string_get(str, NULL, 0, error)) == NULL) {
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
fn = _zip_get_name(za, i, flags, error);
|
||||
if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_RAW | ZIP_FL_ENC_STRICT)) {
|
||||
/* can't use hash table */
|
||||
cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
|
||||
|
||||
/* newly added (partially filled) entry or error */
|
||||
if (fn == NULL)
|
||||
continue;
|
||||
for (i = 0; i < za->nentry; i++) {
|
||||
fn = _zip_get_name(za, i, flags, error);
|
||||
|
||||
if (flags & ZIP_FL_NODIR) {
|
||||
p = strrchr(fn, '/');
|
||||
if (p)
|
||||
fn = p + 1;
|
||||
}
|
||||
/* newly added (partially filled) entry or error */
|
||||
if (fn == NULL)
|
||||
continue;
|
||||
|
||||
if (cmp(fname, fn) == 0) {
|
||||
_zip_error_clear(error);
|
||||
return (zip_int64_t)i;
|
||||
}
|
||||
}
|
||||
if (flags & ZIP_FL_NODIR) {
|
||||
p = strrchr(fn, '/');
|
||||
if (p)
|
||||
fn = p + 1;
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
return -1;
|
||||
if (cmp(fname, fn) == 0) {
|
||||
_zip_error_clear(error);
|
||||
_zip_string_free(str);
|
||||
return (zip_int64_t)i;
|
||||
}
|
||||
}
|
||||
|
||||
zip_error_set(error, ZIP_ER_NOENT, 0);
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
|
||||
zip_int64_t ret = _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
|
||||
_zip_string_free(str);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_new.c -- create and init struct zip
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -47,13 +47,13 @@ _zip_new(zip_error_t *error) {
|
||||
|
||||
za = (zip_t *)malloc(sizeof(struct zip));
|
||||
if (!za) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((za->names = _zip_hash_new(error)) == NULL) {
|
||||
free(za);
|
||||
return NULL;
|
||||
free(za);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
za->src = NULL;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
||||
Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -75,18 +75,18 @@ _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t
|
||||
zip_uint8_t tmp;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
b = in[i];
|
||||
b = in[i];
|
||||
|
||||
if (out != NULL) {
|
||||
tmp = crypt_byte(keys);
|
||||
update_keys(keys, b);
|
||||
b ^= tmp;
|
||||
out[i] = b;
|
||||
}
|
||||
else {
|
||||
/* during initialization, we're only interested in key updates */
|
||||
update_keys(keys, b);
|
||||
}
|
||||
if (out != NULL) {
|
||||
tmp = crypt_byte(keys);
|
||||
update_keys(keys, b);
|
||||
b ^= tmp;
|
||||
out[i] = b;
|
||||
}
|
||||
else {
|
||||
/* during initialization, we're only interested in key updates */
|
||||
update_keys(keys, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,15 +98,15 @@ _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t
|
||||
zip_uint8_t tmp;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
b = in[i];
|
||||
b = in[i];
|
||||
|
||||
/* during initialization, we're only interested in key updates */
|
||||
if (out != NULL) {
|
||||
tmp = crypt_byte(keys);
|
||||
b ^= tmp;
|
||||
out[i] = b;
|
||||
}
|
||||
/* during initialization, we're only interested in key updates */
|
||||
if (out != NULL) {
|
||||
tmp = crypt_byte(keys);
|
||||
b ^= tmp;
|
||||
out[i] = b;
|
||||
}
|
||||
|
||||
update_keys(keys, b);
|
||||
update_keys(keys, b);
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -73,7 +73,7 @@ _zip_progress_end(zip_progress_t *progress) {
|
||||
void
|
||||
_zip_progress_free(zip_progress_t *progress) {
|
||||
if (progress == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
_zip_progress_free_progress_callback(progress);
|
||||
@ -88,8 +88,8 @@ _zip_progress_new(zip_t *za) {
|
||||
zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress));
|
||||
|
||||
if (progress == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
progress->za = za;
|
||||
@ -109,7 +109,7 @@ _zip_progress_new(zip_t *za) {
|
||||
static void
|
||||
_zip_progress_free_progress_callback(zip_progress_t *progress) {
|
||||
if (progress->ud_progress_free) {
|
||||
progress->ud_progress_free(progress->ud_progress);
|
||||
progress->ud_progress_free(progress->ud_progress);
|
||||
}
|
||||
|
||||
progress->callback_progress = NULL;
|
||||
@ -120,7 +120,7 @@ _zip_progress_free_progress_callback(zip_progress_t *progress) {
|
||||
static void
|
||||
_zip_progress_free_cancel_callback(zip_progress_t *progress) {
|
||||
if (progress->ud_cancel_free) {
|
||||
progress->ud_cancel_free(progress->ud_cancel);
|
||||
progress->ud_cancel_free(progress->ud_cancel);
|
||||
}
|
||||
|
||||
progress->callback_cancel = NULL;
|
||||
@ -150,18 +150,18 @@ _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback
|
||||
int
|
||||
_zip_progress_start(zip_progress_t *progress) {
|
||||
if (progress == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (progress->callback_progress != NULL) {
|
||||
progress->last_update = 0.0;
|
||||
progress->callback_progress(progress->za, 0.0, progress->ud_progress);
|
||||
progress->last_update = 0.0;
|
||||
progress->callback_progress(progress->za, 0.0, progress->ud_progress);
|
||||
}
|
||||
|
||||
if (progress->callback_cancel != NULL) {
|
||||
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
|
||||
return -1;
|
||||
}
|
||||
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -171,7 +171,7 @@ _zip_progress_start(zip_progress_t *progress) {
|
||||
int
|
||||
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
|
||||
if (progress == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
progress->start = start;
|
||||
@ -185,22 +185,22 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
|
||||
double current;
|
||||
|
||||
if (progress == NULL) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (progress->callback_progress != NULL) {
|
||||
current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
|
||||
current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
|
||||
|
||||
if (current - progress->last_update > progress->precision) {
|
||||
progress->callback_progress(progress->za, current, progress->ud_progress);
|
||||
progress->last_update = current;
|
||||
}
|
||||
if (current - progress->last_update > progress->precision) {
|
||||
progress->callback_progress(progress->za, current, progress->ud_progress);
|
||||
progress->last_update = current;
|
||||
}
|
||||
}
|
||||
|
||||
if (progress->callback_cancel != NULL) {
|
||||
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
|
||||
return -1;
|
||||
}
|
||||
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -210,24 +210,24 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
|
||||
ZIP_EXTERN int
|
||||
zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
|
||||
if (callback != NULL) {
|
||||
if (za->progress == NULL) {
|
||||
if ((za->progress = _zip_progress_new(za)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (za->progress == NULL) {
|
||||
if ((za->progress = _zip_progress_new(za)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
|
||||
_zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
|
||||
}
|
||||
else {
|
||||
if (za->progress != NULL) {
|
||||
if (za->progress->callback_cancel == NULL) {
|
||||
_zip_progress_free(za->progress);
|
||||
za->progress = NULL;
|
||||
}
|
||||
else {
|
||||
_zip_progress_free_progress_callback(za->progress);
|
||||
}
|
||||
}
|
||||
if (za->progress != NULL) {
|
||||
if (za->progress->callback_cancel == NULL) {
|
||||
_zip_progress_free(za->progress);
|
||||
za->progress = NULL;
|
||||
}
|
||||
else {
|
||||
_zip_progress_free_progress_callback(za->progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -237,24 +237,24 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr
|
||||
ZIP_EXTERN int
|
||||
zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
|
||||
if (callback != NULL) {
|
||||
if (za->progress == NULL) {
|
||||
if ((za->progress = _zip_progress_new(za)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (za->progress == NULL) {
|
||||
if ((za->progress = _zip_progress_new(za)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
_zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
|
||||
_zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
|
||||
}
|
||||
else {
|
||||
if (za->progress != NULL) {
|
||||
if (za->progress->callback_progress == NULL) {
|
||||
_zip_progress_free(za->progress);
|
||||
za->progress = NULL;
|
||||
}
|
||||
else {
|
||||
_zip_progress_free_cancel_callback(za->progress);
|
||||
}
|
||||
}
|
||||
if (za->progress != NULL) {
|
||||
if (za->progress->callback_progress == NULL) {
|
||||
_zip_progress_free(za->progress);
|
||||
za->progress = NULL;
|
||||
}
|
||||
else {
|
||||
_zip_progress_free_cancel_callback(za->progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -278,16 +278,16 @@ zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callb
|
||||
struct legacy_ud *ud;
|
||||
|
||||
if (progress_callback == NULL) {
|
||||
zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
|
||||
zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
ud->callback = progress_callback;
|
||||
|
||||
if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
|
||||
free(ud);
|
||||
free(ud);
|
||||
}
|
||||
}
|
||||
|
104
src/Common/libzip/zip_random_unix.c
Normal file
104
src/Common/libzip/zip_random_unix.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
zip_random_unix.c -- fill the user's buffer with random stuff (Unix version)
|
||||
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#ifdef HAVE_CRYPTO
|
||||
#include "zip_crypto.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARC4RANDOM
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef HAVE_SECURE_RANDOM
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
arc4random_buf(buffer, length);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RANDOM_UINT32
|
||||
zip_uint32_t
|
||||
zip_random_uint32(void) {
|
||||
return arc4random();
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* HAVE_ARC4RANDOM */
|
||||
|
||||
#ifndef HAVE_SECURE_RANDOM
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
int fd;
|
||||
|
||||
if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (read(fd, buffer, length) != length) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RANDOM_UINT32
|
||||
#include <stdlib.h>
|
||||
|
||||
zip_uint32_t
|
||||
zip_random_uint32(void) {
|
||||
static bool seeded = false;
|
||||
|
||||
zip_uint32_t value;
|
||||
|
||||
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!seeded) {
|
||||
srandom((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
return (zip_uint32_t)random();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_ARC4RANDOM */
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_filerange_crc.c -- compute CRC32 for a range of a file
|
||||
Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
|
||||
zip_random_uwp.c -- fill the user's buffer with random stuff (UWP version)
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -31,54 +31,51 @@
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#ifdef HAVE_CRYPTO
|
||||
#include "zip_crypto.h"
|
||||
#endif
|
||||
|
||||
int
|
||||
_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) {
|
||||
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
|
||||
#ifndef HAVE_SECURE_RANDOM
|
||||
|
||||
zip_int64_t n;
|
||||
#include <windows.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
*crcp = crc32(0L, Z_NULL, 0);
|
||||
|
||||
if (start > ZIP_INT64_MAX) {
|
||||
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
|
||||
return -1;
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
BCRYPT_ALG_HANDLE hAlg = NULL;
|
||||
NTSTATUS hr = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
|
||||
if (!BCRYPT_SUCCESS(hr) || hAlg == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) {
|
||||
_zip_error_set_from_source(error, src);
|
||||
return -1;
|
||||
hr = BCryptGenRandom(&hAlg, buffer, length, 0);
|
||||
BCryptCloseAlgorithmProvider(&hAlg, 0);
|
||||
if (!BCRYPT_SUCCESS(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!byte_array_init(buf, BUFSIZE)) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len);
|
||||
if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) {
|
||||
_zip_error_set_from_source(error, src);
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
if (n == 0) {
|
||||
zip_error_set(error, ZIP_ER_EOF, 0);
|
||||
byte_array_fini(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*crcp = crc32(*crcp, buf, (uInt)n);
|
||||
|
||||
len -= (zip_uint64_t)n;
|
||||
}
|
||||
|
||||
byte_array_fini(buf);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RANDOM_UINT32
|
||||
#include <stdlib.h>
|
||||
|
||||
zip_uint32_t
|
||||
zip_random_uint32(void) {
|
||||
static bool seeded = false;
|
||||
|
||||
zip_uint32_t value;
|
||||
|
||||
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!seeded) {
|
||||
srand((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
return (zip_uint32_t)rand();
|
||||
}
|
||||
#endif
|
81
src/Common/libzip/zip_random_win32.c
Normal file
81
src/Common/libzip/zip_random_win32.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
zip_random_win32.c -- fill the user's buffer with random stuff (Windows version)
|
||||
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
3. The names of the authors may not be used to endorse or promote
|
||||
products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "zipint.h"
|
||||
|
||||
#ifdef HAVE_CRYPTO
|
||||
#include "zip_crypto.h"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef HAVE_SECURE_RANDOM
|
||||
|
||||
#include <wincrypt.h>
|
||||
|
||||
ZIP_EXTERN bool
|
||||
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
|
||||
HCRYPTPROV hprov;
|
||||
if (!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
return false;
|
||||
}
|
||||
if (!CryptGenRandom(hprov, length, buffer)) {
|
||||
return false;
|
||||
}
|
||||
if (!CryptReleaseContext(hprov, 0)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_RANDOM_UINT32
|
||||
#include <stdlib.h>
|
||||
|
||||
zip_uint32_t
|
||||
zip_random_uint32(void) {
|
||||
static bool seeded = false;
|
||||
|
||||
zip_uint32_t value;
|
||||
|
||||
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!seeded) {
|
||||
srand((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
return (zip_uint32_t)rand();
|
||||
}
|
||||
#endif
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_rename.c -- rename file in zip archive
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_replace.c -- replace file via callback function
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_set_archive_comment.c -- set archive comment
|
||||
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -42,38 +42,38 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) {
|
||||
zip_string_t *cstr;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > 0 && comment == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
|
||||
return -1;
|
||||
|
||||
if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
|
||||
_zip_string_free(cstr);
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
|
||||
_zip_string_free(cstr);
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
cstr = NULL;
|
||||
cstr = NULL;
|
||||
|
||||
_zip_string_free(za->comment_changes);
|
||||
za->comment_changes = NULL;
|
||||
|
||||
if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) {
|
||||
_zip_string_free(cstr);
|
||||
za->comment_changed = 0;
|
||||
_zip_string_free(cstr);
|
||||
za->comment_changed = 0;
|
||||
}
|
||||
else {
|
||||
za->comment_changes = cstr;
|
||||
za->comment_changed = 1;
|
||||
za->comment_changes = cstr;
|
||||
za->comment_changed = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_get_archive_flag.c -- set archive global flag
|
||||
Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,23 +40,23 @@ zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) {
|
||||
unsigned int new_flags;
|
||||
|
||||
if (value)
|
||||
new_flags = za->ch_flags | flag;
|
||||
new_flags = za->ch_flags | flag;
|
||||
else
|
||||
new_flags = za->ch_flags & ~flag;
|
||||
new_flags = za->ch_flags & ~flag;
|
||||
|
||||
if (new_flags == za->ch_flags)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flag & ZIP_AFL_RDONLY) && value && (za->ch_flags & ZIP_AFL_RDONLY) == 0) {
|
||||
if (_zip_changed(za, NULL)) {
|
||||
zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
|
||||
return -1;
|
||||
}
|
||||
if (_zip_changed(za, NULL)) {
|
||||
zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
za->ch_flags = new_flags;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_set_default_password.c -- set default password for decryption
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -41,18 +41,18 @@
|
||||
ZIP_EXTERN int
|
||||
zip_set_default_password(zip_t *za, const char *passwd) {
|
||||
if (za == NULL)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
free(za->default_password);
|
||||
|
||||
if (passwd) {
|
||||
if ((za->default_password = strdup(passwd)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
if (passwd && passwd[0] != '\0') {
|
||||
if ((za->default_password = strdup(passwd)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
za->default_password = NULL;
|
||||
za->default_password = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_set_file_comment.c -- set comment for file in archive
|
||||
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -39,8 +39,8 @@
|
||||
ZIP_EXTERN int
|
||||
zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) {
|
||||
if (len < 0 || len > ZIP_UINT16_MAX) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_set_file_compression.c -- set compression for file in archive
|
||||
Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,19 +40,19 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
|
||||
zip_entry_t *e;
|
||||
zip_int32_t old_method;
|
||||
|
||||
if (idx >= za->nentry || flags > 9) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!zip_compression_method_supported(method, true)) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
@ -65,26 +65,26 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
|
||||
* to levels */
|
||||
|
||||
if (method == old_method) {
|
||||
if (e->changes) {
|
||||
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
|
||||
e->changes->compression_level = 0;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
}
|
||||
if (e->changes) {
|
||||
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
|
||||
e->changes->compression_level = 0;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
e->changes->comp_method = method;
|
||||
e->changes->compression_level = (zip_uint16_t)flags;
|
||||
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
e->changes->comp_method = method;
|
||||
e->changes->compression_level = (zip_uint16_t)flags;
|
||||
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_set_name.c -- rename helper function
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -48,109 +48,109 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
|
||||
zip_string_t *old_str;
|
||||
|
||||
if (idx >= za->nentry) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ZIP_IS_RDONLY(za)) {
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name && name[0] != '\0') {
|
||||
/* TODO: check for string too long */
|
||||
if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
|
||||
str->encoding = ZIP_ENCODING_UTF8_KNOWN;
|
||||
/* TODO: check for string too long */
|
||||
if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
|
||||
return -1;
|
||||
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
|
||||
str->encoding = ZIP_ENCODING_UTF8_KNOWN;
|
||||
}
|
||||
else
|
||||
str = NULL;
|
||||
str = NULL;
|
||||
|
||||
/* TODO: encoding flags needed for CP437? */
|
||||
if ((i = _zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) {
|
||||
_zip_string_free(str);
|
||||
zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
|
||||
return -1;
|
||||
_zip_string_free(str);
|
||||
zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* no effective name change */
|
||||
if (i >= 0 && (zip_uint64_t)i == idx) {
|
||||
_zip_string_free(str);
|
||||
return 0;
|
||||
_zip_string_free(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
e = za->entry + idx;
|
||||
|
||||
if (e->orig)
|
||||
same_as_orig = _zip_string_equal(e->orig->filename, str);
|
||||
same_as_orig = _zip_string_equal(e->orig->filename, str);
|
||||
else
|
||||
same_as_orig = false;
|
||||
same_as_orig = false;
|
||||
|
||||
if (!same_as_orig && e->changes == NULL) {
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (e->changes) {
|
||||
old_str = e->changes->filename;
|
||||
old_str = e->changes->filename;
|
||||
}
|
||||
else if (e->orig) {
|
||||
old_str = e->orig->filename;
|
||||
old_str = e->orig->filename;
|
||||
}
|
||||
else {
|
||||
old_str = NULL;
|
||||
old_str = NULL;
|
||||
}
|
||||
|
||||
if (old_str) {
|
||||
if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
old_name = NULL;
|
||||
old_name = NULL;
|
||||
}
|
||||
|
||||
if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
_zip_string_free(str);
|
||||
return -1;
|
||||
}
|
||||
if (old_name) {
|
||||
_zip_hash_delete(za->names, old_name, NULL);
|
||||
_zip_hash_delete(za->names, old_name, NULL);
|
||||
}
|
||||
|
||||
if (same_as_orig) {
|
||||
if (e->changes) {
|
||||
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
|
||||
_zip_string_free(e->changes->filename);
|
||||
e->changes->changed &= ~ZIP_DIRENT_FILENAME;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
else {
|
||||
/* TODO: what if not cloned? can that happen? */
|
||||
e->changes->filename = e->orig->filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
_zip_string_free(str);
|
||||
if (e->changes) {
|
||||
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
|
||||
_zip_string_free(e->changes->filename);
|
||||
e->changes->changed &= ~ZIP_DIRENT_FILENAME;
|
||||
if (e->changes->changed == 0) {
|
||||
_zip_dirent_free(e->changes);
|
||||
e->changes = NULL;
|
||||
}
|
||||
else {
|
||||
/* TODO: what if not cloned? can that happen? */
|
||||
e->changes->filename = e->orig->filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
_zip_string_free(str);
|
||||
}
|
||||
else {
|
||||
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
|
||||
_zip_string_free(e->changes->filename);
|
||||
}
|
||||
e->changes->changed |= ZIP_DIRENT_FILENAME;
|
||||
e->changes->filename = str;
|
||||
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
|
||||
_zip_string_free(e->changes->filename);
|
||||
}
|
||||
e->changes->changed |= ZIP_DIRENT_FILENAME;
|
||||
e->changes->filename = str;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_accept_empty.c -- if empty source is a valid archive
|
||||
Copyright (C) 2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2019-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,10 +40,10 @@ zip_source_accept_empty(zip_source_t *src) {
|
||||
int ret;
|
||||
|
||||
if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) {
|
||||
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||
return zip_source_accept_empty(src->src);
|
||||
}
|
||||
return true;
|
||||
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||
return zip_source_accept_empty(src->src);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_begin_write.c -- start a new file for writing
|
||||
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,12 +38,12 @@
|
||||
ZIP_EXTERN int
|
||||
zip_source_begin_write(zip_source_t *src) {
|
||||
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
src->write_state = ZIP_SOURCE_WRITE_OPEN;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_begin_write_cloning.c -- clone part of file for writing
|
||||
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,12 +38,12 @@
|
||||
ZIP_EXTERN int
|
||||
zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
|
||||
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
src->write_state = ZIP_SOURCE_WRITE_OPEN;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_buffer.c -- create zip data source from buffer
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -87,7 +87,7 @@ zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
|
||||
if (za == NULL)
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
|
||||
}
|
||||
@ -104,12 +104,12 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int
|
||||
zip_buffer_fragment_t fragment;
|
||||
|
||||
if (data == NULL) {
|
||||
if (len > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (len > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
|
||||
return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
|
||||
}
|
||||
|
||||
fragment.data = (zip_uint8_t *)data;
|
||||
@ -122,7 +122,7 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int
|
||||
ZIP_EXTERN zip_source_t *
|
||||
zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) {
|
||||
if (za == NULL) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
|
||||
@ -141,35 +141,35 @@ zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *f
|
||||
buffer_t *buffer;
|
||||
|
||||
if (fragments == NULL && nfragments > 0) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->in = buffer;
|
||||
ctx->out = NULL;
|
||||
ctx->mtime = time(NULL);
|
||||
if (attributes) {
|
||||
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
|
||||
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
|
||||
}
|
||||
else {
|
||||
zip_file_attributes_init(&ctx->attributes);
|
||||
zip_file_attributes_init(&ctx->attributes);
|
||||
}
|
||||
zip_error_init(&ctx->error);
|
||||
|
||||
if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) {
|
||||
buffer_free(ctx->in);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
buffer_free(ctx->in);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zs;
|
||||
@ -187,133 +187,133 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_BEGIN_WRITE:
|
||||
if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->out->offset = 0;
|
||||
ctx->out->current_fragment = 0;
|
||||
return 0;
|
||||
if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->out->offset = 0;
|
||||
ctx->out->current_fragment = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
|
||||
if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->out->offset = len;
|
||||
ctx->out->current_fragment = ctx->out->nfragments;
|
||||
return 0;
|
||||
if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->out->offset = len;
|
||||
ctx->out->current_fragment = ctx->out->nfragments;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_COMMIT_WRITE:
|
||||
buffer_free(ctx->in);
|
||||
ctx->in = ctx->out;
|
||||
ctx->out = NULL;
|
||||
return 0;
|
||||
buffer_free(ctx->in);
|
||||
ctx->in = ctx->out;
|
||||
ctx->out = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
buffer_free(ctx->in);
|
||||
buffer_free(ctx->out);
|
||||
free(ctx);
|
||||
return 0;
|
||||
buffer_free(ctx->in);
|
||||
buffer_free(ctx->out);
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
|
||||
return sizeof(ctx->attributes);
|
||||
return sizeof(ctx->attributes);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->in->offset = 0;
|
||||
ctx->in->current_fragment = 0;
|
||||
return 0;
|
||||
ctx->in->offset = 0;
|
||||
ctx->in->current_fragment = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
if (len > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return buffer_read(ctx->in, data, len);
|
||||
if (len > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return buffer_read(ctx->in, data, len);
|
||||
|
||||
case ZIP_SOURCE_REMOVE: {
|
||||
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
|
||||
if (empty == NULL) {
|
||||
return -1;
|
||||
}
|
||||
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
|
||||
if (empty == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_free(ctx->in);
|
||||
ctx->in = empty;
|
||||
return 0;
|
||||
buffer_free(ctx->in);
|
||||
ctx->in = empty;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_ROLLBACK_WRITE:
|
||||
buffer_free(ctx->out);
|
||||
ctx->out = NULL;
|
||||
return 0;
|
||||
buffer_free(ctx->out);
|
||||
ctx->out = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SEEK:
|
||||
return buffer_seek(ctx->in, data, len, &ctx->error);
|
||||
return buffer_seek(ctx->in, data, len, &ctx->error);
|
||||
|
||||
case ZIP_SOURCE_SEEK_WRITE:
|
||||
return buffer_seek(ctx->out, data, len, &ctx->error);
|
||||
return buffer_seek(ctx->out, data, len, &ctx->error);
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
zip_stat_t *st;
|
||||
|
||||
if (len < sizeof(*st)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (len < sizeof(*st)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
zip_stat_init(st);
|
||||
st->mtime = ctx->mtime;
|
||||
st->size = ctx->in->size;
|
||||
st->comp_size = st->size;
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->encryption_method = ZIP_EM_NONE;
|
||||
st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
|
||||
zip_stat_init(st);
|
||||
st->mtime = ctx->mtime;
|
||||
st->size = ctx->in->size;
|
||||
st->comp_size = st->size;
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->encryption_method = ZIP_EM_NONE;
|
||||
st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
|
||||
|
||||
return sizeof(*st);
|
||||
return sizeof(*st);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
|
||||
return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1);
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
if (ctx->in->offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
return (zip_int64_t)ctx->in->offset;
|
||||
if (ctx->in->offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
return (zip_int64_t)ctx->in->offset;
|
||||
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE:
|
||||
if (ctx->out->offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
return (zip_int64_t)ctx->out->offset;
|
||||
if (ctx->out->offset > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
return (zip_int64_t)ctx->out->offset;
|
||||
|
||||
case ZIP_SOURCE_WRITE:
|
||||
if (len > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return buffer_write(ctx->out, data, len, &ctx->error);
|
||||
if (len > ZIP_INT64_MAX) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return buffer_write(ctx->out, data, len, &ctx->error);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,34 +324,34 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
|
||||
buffer_t *clone;
|
||||
|
||||
if (offset == 0) {
|
||||
return buffer_new(NULL, 0, 1, error);
|
||||
return buffer_new(NULL, 0, 1, error);
|
||||
}
|
||||
|
||||
if (offset > buffer->size) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (buffer->shared_buffer != NULL) {
|
||||
zip_error_set(error, ZIP_ER_INUSE, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INUSE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fragment = buffer_find_fragment(buffer, offset);
|
||||
fragment_offset = offset - buffer->fragment_offsets[fragment];
|
||||
|
||||
if (fragment_offset == 0) {
|
||||
fragment--;
|
||||
fragment_offset = buffer->fragments[fragment].length;
|
||||
fragment--;
|
||||
fragment_offset = buffer->fragments[fragment].length;
|
||||
}
|
||||
|
||||
waste = buffer->fragments[fragment].length - fragment_offset;
|
||||
if (waste > offset) {
|
||||
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef __clang_analyzer__
|
||||
@ -361,13 +361,13 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
|
||||
clone->fragment_offsets[clone->nfragments] = offset;
|
||||
clone->size = offset;
|
||||
|
||||
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments - 1);
|
||||
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments);
|
||||
|
||||
buffer->shared_buffer = clone;
|
||||
clone->shared_buffer = buffer;
|
||||
buffer->shared_fragments = clone->nfragments;
|
||||
clone->shared_fragments = fragment + 1;
|
||||
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@ -376,20 +376,24 @@ static zip_uint64_t
|
||||
buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) {
|
||||
zip_uint64_t low, high, mid;
|
||||
|
||||
if (buffer->nfragments == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
low = 0;
|
||||
high = buffer->nfragments - 1;
|
||||
|
||||
while (low < high) {
|
||||
mid = (high - low) / 2 + low;
|
||||
if (buffer->fragment_offsets[mid] > offset) {
|
||||
high = mid - 1;
|
||||
}
|
||||
else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
|
||||
return mid;
|
||||
}
|
||||
else {
|
||||
low = mid + 1;
|
||||
}
|
||||
mid = (high - low) / 2 + low;
|
||||
if (buffer->fragment_offsets[mid] > offset) {
|
||||
high = mid - 1;
|
||||
}
|
||||
else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
|
||||
return mid;
|
||||
}
|
||||
else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
@ -401,18 +405,18 @@ buffer_free(buffer_t *buffer) {
|
||||
zip_uint64_t i;
|
||||
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer->shared_buffer != NULL) {
|
||||
buffer->shared_buffer->shared_buffer = NULL;
|
||||
buffer->shared_buffer->shared_fragments = 0;
|
||||
buffer->shared_buffer->shared_buffer = NULL;
|
||||
buffer->shared_buffer->shared_fragments = 0;
|
||||
|
||||
buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
|
||||
buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
|
||||
}
|
||||
|
||||
for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
|
||||
free(buffer->fragments[i].data);
|
||||
free(buffer->fragments[i].data);
|
||||
}
|
||||
free(buffer->fragments);
|
||||
free(buffer->fragment_offsets);
|
||||
@ -426,17 +430,17 @@ buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *erro
|
||||
zip_uint64_t *offsets;
|
||||
|
||||
if (capacity < buffer->fragments_capacity) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
buffer->fragments = fragments;
|
||||
if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return false;
|
||||
}
|
||||
buffer->fragment_offsets = offsets;
|
||||
buffer->fragments_capacity = capacity;
|
||||
@ -450,7 +454,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
|
||||
buffer_t *buffer;
|
||||
|
||||
if ((buffer = malloc(sizeof(*buffer))) == NULL) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->offset = 0;
|
||||
@ -464,42 +468,42 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
|
||||
buffer->shared_fragments = 0;
|
||||
|
||||
if (nfragments == 0) {
|
||||
if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
|
||||
free(buffer);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragment_offsets[0] = 0;
|
||||
if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
|
||||
free(buffer);
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragment_offsets[0] = 0;
|
||||
}
|
||||
else {
|
||||
zip_uint64_t i, j, offset;
|
||||
zip_uint64_t i, j, offset;
|
||||
|
||||
if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
for (i = 0, j = 0; i < nfragments; i++) {
|
||||
if (fragments[i].length == 0) {
|
||||
continue;
|
||||
}
|
||||
if (fragments[i].data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragments[j].data = fragments[i].data;
|
||||
buffer->fragments[j].length = fragments[i].length;
|
||||
buffer->fragment_offsets[i] = offset;
|
||||
offset += fragments[i].length;
|
||||
j++;
|
||||
}
|
||||
buffer->nfragments = j;
|
||||
buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
|
||||
buffer->fragment_offsets[buffer->nfragments] = offset;
|
||||
buffer->size = offset;
|
||||
offset = 0;
|
||||
for (i = 0, j = 0; i < nfragments; i++) {
|
||||
if (fragments[i].length == 0) {
|
||||
continue;
|
||||
}
|
||||
if (fragments[i].data == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
buffer->fragments[j].data = fragments[i].data;
|
||||
buffer->fragments[j].length = fragments[i].length;
|
||||
buffer->fragment_offsets[i] = offset;
|
||||
offset += fragments[i].length;
|
||||
j++;
|
||||
}
|
||||
buffer->nfragments = j;
|
||||
buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
|
||||
buffer->fragment_offsets[buffer->nfragments] = offset;
|
||||
buffer->size = offset;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
@ -512,25 +516,25 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
|
||||
length = ZIP_MIN(length, buffer->size - buffer->offset);
|
||||
|
||||
if (length == 0) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (length > ZIP_INT64_MAX) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = buffer->current_fragment;
|
||||
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
|
||||
n = 0;
|
||||
while (n < length) {
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
|
||||
|
||||
memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
|
||||
memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
|
||||
|
||||
if (left == buffer->fragments[i].length - fragment_offset) {
|
||||
i++;
|
||||
}
|
||||
n += left;
|
||||
fragment_offset = 0;
|
||||
if (left == buffer->fragments[i].length - fragment_offset) {
|
||||
i++;
|
||||
}
|
||||
n += left;
|
||||
fragment_offset = 0;
|
||||
}
|
||||
|
||||
buffer->offset += n;
|
||||
@ -544,7 +548,7 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
|
||||
zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error);
|
||||
|
||||
if (new_offset < 0) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer->offset = (zip_uint64_t)new_offset;
|
||||
@ -558,62 +562,62 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip
|
||||
zip_uint64_t n, i, fragment_offset, capacity;
|
||||
|
||||
if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* grow buffer if needed */
|
||||
capacity = buffer_capacity(buffer);
|
||||
if (buffer->offset + length > capacity) {
|
||||
zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
|
||||
zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
|
||||
|
||||
if (needed_fragments > buffer->fragments_capacity) {
|
||||
zip_uint64_t new_capacity = buffer->fragments_capacity;
|
||||
if (needed_fragments > buffer->fragments_capacity) {
|
||||
zip_uint64_t new_capacity = buffer->fragments_capacity;
|
||||
|
||||
if (new_capacity == 0) {
|
||||
new_capacity = 16;
|
||||
}
|
||||
while (new_capacity < needed_fragments) {
|
||||
new_capacity *= 2;
|
||||
}
|
||||
if (new_capacity == 0) {
|
||||
new_capacity = 16;
|
||||
}
|
||||
while (new_capacity < needed_fragments) {
|
||||
new_capacity *= 2;
|
||||
}
|
||||
|
||||
if (!buffer_grow_fragments(buffer, new_capacity, error)) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!buffer_grow_fragments(buffer, new_capacity, error)) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (buffer->nfragments < needed_fragments) {
|
||||
if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
|
||||
buffer->nfragments++;
|
||||
capacity += WRITE_FRAGMENT_SIZE;
|
||||
buffer->fragment_offsets[buffer->nfragments] = capacity;
|
||||
}
|
||||
while (buffer->nfragments < needed_fragments) {
|
||||
if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return -1;
|
||||
}
|
||||
buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
|
||||
buffer->nfragments++;
|
||||
capacity += WRITE_FRAGMENT_SIZE;
|
||||
buffer->fragment_offsets[buffer->nfragments] = capacity;
|
||||
}
|
||||
}
|
||||
|
||||
i = buffer->current_fragment;
|
||||
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
|
||||
n = 0;
|
||||
while (n < length) {
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
|
||||
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
|
||||
|
||||
memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
|
||||
memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
|
||||
|
||||
if (left == buffer->fragments[i].length - fragment_offset) {
|
||||
i++;
|
||||
}
|
||||
n += left;
|
||||
fragment_offset = 0;
|
||||
if (left == buffer->fragments[i].length - fragment_offset) {
|
||||
i++;
|
||||
}
|
||||
n += left;
|
||||
fragment_offset = 0;
|
||||
}
|
||||
|
||||
buffer->offset += n;
|
||||
buffer->current_fragment = i;
|
||||
if (buffer->offset > buffer->size) {
|
||||
buffer->size = buffer->offset;
|
||||
buffer->size = buffer->offset;
|
||||
}
|
||||
|
||||
return (zip_int64_t)n;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_call.c -- invoke callback command on zip_source
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -40,28 +40,28 @@ _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_
|
||||
zip_int64_t ret;
|
||||
|
||||
if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) {
|
||||
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src->src == NULL) {
|
||||
ret = src->cb.f(src->ud, data, length, command);
|
||||
ret = src->cb.f(src->ud, data, length, command);
|
||||
}
|
||||
else {
|
||||
ret = src->cb.l(src->src, src->ud, data, length, command);
|
||||
ret = src->cb.l(src->src, src->ud, data, length, command);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
|
||||
int e[2];
|
||||
if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
|
||||
int e[2];
|
||||
|
||||
if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
|
||||
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
else {
|
||||
zip_error_set(&src->error, e[0], e[1]);
|
||||
}
|
||||
}
|
||||
if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
|
||||
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
else {
|
||||
zip_error_set(&src->error, e[0], e[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_close.c -- close zip_source (stop reading)
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,19 +38,19 @@
|
||||
int
|
||||
zip_source_close(zip_source_t *src) {
|
||||
if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
src->open_count--;
|
||||
if (src->open_count == 0) {
|
||||
_zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
|
||||
_zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
|
||||
|
||||
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||
if (zip_source_close(src->src) < 0) {
|
||||
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
}
|
||||
if (ZIP_SOURCE_IS_LAYERED(src)) {
|
||||
if (zip_source_close(src->src) < 0) {
|
||||
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_commit_write.c -- commit changes to file
|
||||
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -38,23 +38,23 @@
|
||||
ZIP_EXTERN int
|
||||
zip_source_commit_write(zip_source_t *src) {
|
||||
if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (src->open_count > 1) {
|
||||
zip_error_set(&src->error, ZIP_ER_INUSE, 0);
|
||||
return -1;
|
||||
zip_error_set(&src->error, ZIP_ER_INUSE, 0);
|
||||
return -1;
|
||||
}
|
||||
else if (ZIP_SOURCE_IS_OPEN_READING(src)) {
|
||||
if (zip_source_close(src) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (zip_source_close(src) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) {
|
||||
src->write_state = ZIP_SOURCE_WRITE_FAILED;
|
||||
return -1;
|
||||
src->write_state = ZIP_SOURCE_WRITE_FAILED;
|
||||
return -1;
|
||||
}
|
||||
|
||||
src->write_state = ZIP_SOURCE_WRITE_CLOSED;
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_compress.c -- (de)compression routines
|
||||
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -67,14 +67,17 @@ static struct implementation implementations[] = {
|
||||
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
|
||||
#endif
|
||||
#if defined(HAVE_LIBLZMA)
|
||||
/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
|
||||
archives made this way - and vice versa.
|
||||
{ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
/* Disabled - because 7z isn't able to unpack ZIP+LZMA2
|
||||
archives made this way - and vice versa.
|
||||
|
||||
{ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
{ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
{ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
*/
|
||||
{ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
|
||||
#endif
|
||||
#if defined(HAVE_LIBZSTD)
|
||||
{ZIP_CM_ZSTD, &zip_algorithm_zstd_compress, &zip_algorithm_zstd_decompress},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@ -86,20 +89,20 @@ static void context_free(struct context *ctx);
|
||||
static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm);
|
||||
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
|
||||
|
||||
static zip_compression_algorithm_t *
|
||||
get_algorithm(zip_int32_t method, bool compress) {
|
||||
zip_compression_algorithm_t *
|
||||
_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
|
||||
size_t i;
|
||||
zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
|
||||
|
||||
for (i = 0; i < implementations_size; i++) {
|
||||
if (implementations[i].method == real_method) {
|
||||
if (compress) {
|
||||
return implementations[i].compress;
|
||||
}
|
||||
else {
|
||||
return implementations[i].decompress;
|
||||
}
|
||||
}
|
||||
if (implementations[i].method == real_method) {
|
||||
if (compress) {
|
||||
return implementations[i].compress;
|
||||
}
|
||||
else {
|
||||
return implementations[i].decompress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -108,9 +111,9 @@ get_algorithm(zip_int32_t method, bool compress) {
|
||||
ZIP_EXTERN int
|
||||
zip_compression_method_supported(zip_int32_t method, int compress) {
|
||||
if (method == ZIP_CM_STORE) {
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
return get_algorithm(method, compress) != NULL;
|
||||
return _zip_get_compression_algorithm(method, compress) != NULL;
|
||||
}
|
||||
|
||||
zip_source_t *
|
||||
@ -131,23 +134,23 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
|
||||
zip_compression_algorithm_t *algorithm = NULL;
|
||||
|
||||
if (src == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((algorithm = get_algorithm(method, compress)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
return NULL;
|
||||
if ((algorithm = _zip_get_compression_algorithm(method, compress)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) {
|
||||
context_free(ctx);
|
||||
return NULL;
|
||||
context_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s2;
|
||||
@ -159,7 +162,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
|
||||
struct context *ctx;
|
||||
|
||||
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
zip_error_init(&ctx->error);
|
||||
ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
|
||||
@ -171,9 +174,9 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
|
||||
ctx->is_stored = false;
|
||||
|
||||
if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
|
||||
zip_error_fini(&ctx->error);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
zip_error_fini(&ctx->error);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
@ -183,7 +186,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
|
||||
static void
|
||||
context_free(struct context *ctx) {
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->algorithm->deallocate(ctx->ud);
|
||||
@ -202,96 +205,96 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
|
||||
zip_uint64_t out_len;
|
||||
|
||||
if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len == 0 || ctx->end_of_stream) {
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
out_offset = 0;
|
||||
|
||||
end = false;
|
||||
while (!end && out_offset < len) {
|
||||
out_len = len - out_offset;
|
||||
ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
|
||||
out_len = len - out_offset;
|
||||
ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
|
||||
|
||||
if (ret != ZIP_COMPRESSION_ERROR) {
|
||||
out_offset += out_len;
|
||||
}
|
||||
if (ret != ZIP_COMPRESSION_ERROR) {
|
||||
out_offset += out_len;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case ZIP_COMPRESSION_END:
|
||||
ctx->end_of_stream = true;
|
||||
switch (ret) {
|
||||
case ZIP_COMPRESSION_END:
|
||||
ctx->end_of_stream = true;
|
||||
|
||||
if (!ctx->end_of_input) {
|
||||
/* TODO: garbage after stream, or compression ended before all data read */
|
||||
}
|
||||
if (!ctx->end_of_input) {
|
||||
/* TODO: garbage after stream, or compression ended before all data read */
|
||||
}
|
||||
|
||||
if (ctx->first_read < 0) {
|
||||
/* we got end of processed stream before reading any input data */
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
|
||||
ctx->is_stored = true;
|
||||
ctx->size = (zip_uint64_t)ctx->first_read;
|
||||
memcpy(data, ctx->buffer, ctx->size);
|
||||
return (zip_int64_t)ctx->size;
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
if (ctx->first_read < 0) {
|
||||
/* we got end of processed stream before reading any input data */
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
|
||||
ctx->is_stored = true;
|
||||
ctx->size = (zip_uint64_t)ctx->first_read;
|
||||
memcpy(data, ctx->buffer, ctx->size);
|
||||
return (zip_int64_t)ctx->size;
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
|
||||
case ZIP_COMPRESSION_OK:
|
||||
break;
|
||||
case ZIP_COMPRESSION_OK:
|
||||
break;
|
||||
|
||||
case ZIP_COMPRESSION_NEED_DATA:
|
||||
if (ctx->end_of_input) {
|
||||
/* TODO: error: stream not ended, but no more input */
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
case ZIP_COMPRESSION_NEED_DATA:
|
||||
if (ctx->end_of_input) {
|
||||
/* TODO: error: stream not ended, but no more input */
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
else if (n == 0) {
|
||||
ctx->end_of_input = true;
|
||||
ctx->algorithm->end_of_input(ctx->ud);
|
||||
if (ctx->first_read < 0) {
|
||||
ctx->first_read = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ctx->first_read >= 0) {
|
||||
/* we overwrote a previously filled ctx->buffer */
|
||||
ctx->can_store = false;
|
||||
}
|
||||
else {
|
||||
ctx->first_read = n;
|
||||
}
|
||||
if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
else if (n == 0) {
|
||||
ctx->end_of_input = true;
|
||||
ctx->algorithm->end_of_input(ctx->ud);
|
||||
if (ctx->first_read < 0) {
|
||||
ctx->first_read = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ctx->first_read >= 0) {
|
||||
/* we overwrote a previously filled ctx->buffer */
|
||||
ctx->can_store = false;
|
||||
}
|
||||
else {
|
||||
ctx->first_read = n;
|
||||
}
|
||||
|
||||
ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
|
||||
}
|
||||
break;
|
||||
ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
|
||||
}
|
||||
break;
|
||||
|
||||
case ZIP_COMPRESSION_ERROR:
|
||||
/* error set by algorithm */
|
||||
if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
case ZIP_COMPRESSION_ERROR:
|
||||
/* error set by algorithm */
|
||||
if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
}
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (out_offset > 0) {
|
||||
ctx->can_store = false;
|
||||
ctx->size += out_offset;
|
||||
return (zip_int64_t)out_offset;
|
||||
ctx->can_store = false;
|
||||
ctx->size += out_offset;
|
||||
return (zip_int64_t)out_offset;
|
||||
}
|
||||
|
||||
return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
|
||||
@ -305,85 +308,91 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
|
||||
ctx = (struct context *)ud;
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->size = 0;
|
||||
ctx->end_of_input = false;
|
||||
ctx->end_of_stream = false;
|
||||
ctx->is_stored = false;
|
||||
ctx->first_read = -1;
|
||||
case ZIP_SOURCE_OPEN: {
|
||||
zip_stat_t st;
|
||||
zip_file_attributes_t attributes;
|
||||
|
||||
ctx->size = 0;
|
||||
ctx->end_of_input = false;
|
||||
ctx->end_of_stream = false;
|
||||
ctx->is_stored = false;
|
||||
ctx->first_read = -1;
|
||||
|
||||
if (zip_source_stat(src, &st) < 0 || zip_source_get_file_attributes(src, &attributes) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ctx->algorithm->start(ctx->ud)) {
|
||||
return -1;
|
||||
}
|
||||
if (!ctx->algorithm->start(ctx->ud, &st, &attributes)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
return compress_read(src, ctx, data, len);
|
||||
return compress_read(src, ctx, data, len);
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
if (!ctx->algorithm->end(ctx->ud)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (!ctx->algorithm->end(ctx->ud)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
if (ctx->compress) {
|
||||
if (ctx->end_of_stream) {
|
||||
st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
|
||||
st->comp_size = ctx->size;
|
||||
st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
|
||||
}
|
||||
else {
|
||||
st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
|
||||
}
|
||||
}
|
||||
else {
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->valid |= ZIP_STAT_COMP_METHOD;
|
||||
if (ctx->end_of_stream) {
|
||||
st->size = ctx->size;
|
||||
st->valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
else {
|
||||
st->valid &= ~ZIP_STAT_SIZE;
|
||||
}
|
||||
}
|
||||
if (ctx->compress) {
|
||||
if (ctx->end_of_stream) {
|
||||
st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
|
||||
st->comp_size = ctx->size;
|
||||
st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
|
||||
}
|
||||
else {
|
||||
st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
|
||||
}
|
||||
}
|
||||
else {
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->valid |= ZIP_STAT_COMP_METHOD;
|
||||
if (ctx->end_of_stream) {
|
||||
st->size = ctx->size;
|
||||
st->valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
context_free(ctx);
|
||||
return 0;
|
||||
context_free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
|
||||
zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
|
||||
zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
|
||||
|
||||
if (len < sizeof(*attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (len < sizeof(*attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
|
||||
attributes->version_needed = ctx->algorithm->version_needed;
|
||||
attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
|
||||
attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud));
|
||||
attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS;
|
||||
attributes->version_needed = ctx->algorithm->version_needed;
|
||||
attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK;
|
||||
attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud));
|
||||
|
||||
return sizeof(*attributes);
|
||||
return sizeof(*attributes);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
|
||||
return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_crc.c -- pass-through source that calculates CRC32 and size
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -52,17 +52,17 @@ static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_so
|
||||
|
||||
|
||||
zip_source_t *
|
||||
zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
|
||||
zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) {
|
||||
struct crc_context *ctx;
|
||||
|
||||
if (src == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
|
||||
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->error);
|
||||
@ -72,7 +72,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
|
||||
ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
|
||||
ctx->size = 0;
|
||||
|
||||
return zip_source_layered(za, src, crc_read, ctx);
|
||||
return zip_source_layered_create(src, crc_read, ctx, error);
|
||||
}
|
||||
|
||||
|
||||
@ -85,113 +85,114 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_OPEN:
|
||||
ctx->position = 0;
|
||||
return 0;
|
||||
ctx->position = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ:
|
||||
if ((n = zip_source_read(src, data, len)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
if ((n = zip_source_read(src, data, len)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
if (ctx->crc_position == ctx->position) {
|
||||
ctx->crc_complete = 1;
|
||||
ctx->size = ctx->position;
|
||||
if (n == 0) {
|
||||
if (ctx->crc_position == ctx->position) {
|
||||
ctx->crc_complete = 1;
|
||||
ctx->size = ctx->position;
|
||||
|
||||
if (ctx->validate) {
|
||||
struct zip_stat st;
|
||||
if (ctx->validate) {
|
||||
struct zip_stat st;
|
||||
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
if (zip_source_stat(src, &st) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
|
||||
return -1;
|
||||
}
|
||||
if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
|
||||
zip_uint64_t i, nn;
|
||||
if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
|
||||
return -1;
|
||||
}
|
||||
if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
|
||||
/* We don't have the index here, but the caller should know which file they are reading from. */
|
||||
zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_INVALID_FILE_LENGTH, MAX_DETAIL_INDEX));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
|
||||
zip_uint64_t i, nn;
|
||||
|
||||
for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
|
||||
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
|
||||
for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
|
||||
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
|
||||
|
||||
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
|
||||
ctx->crc_position += nn;
|
||||
}
|
||||
}
|
||||
ctx->position += (zip_uint64_t)n;
|
||||
return n;
|
||||
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
|
||||
ctx->crc_position += nn;
|
||||
}
|
||||
}
|
||||
ctx->position += (zip_uint64_t)n;
|
||||
return n;
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
zip_stat_t *st;
|
||||
zip_stat_t *st;
|
||||
|
||||
st = (zip_stat_t *)data;
|
||||
st = (zip_stat_t *)data;
|
||||
|
||||
if (ctx->crc_complete) {
|
||||
/* TODO: Set comp_size, comp_method, encryption_method?
|
||||
After all, this only works for uncompressed data. */
|
||||
st->size = ctx->size;
|
||||
st->crc = ctx->crc;
|
||||
st->comp_size = ctx->size;
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->encryption_method = ZIP_EM_NONE;
|
||||
st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
|
||||
}
|
||||
return 0;
|
||||
if (ctx->crc_complete) {
|
||||
/* TODO: Set comp_size, comp_method, encryption_method?
|
||||
After all, this only works for uncompressed data. */
|
||||
st->size = ctx->size;
|
||||
st->crc = ctx->crc;
|
||||
st->comp_size = ctx->size;
|
||||
st->comp_method = ZIP_CM_STORE;
|
||||
st->encryption_method = ZIP_EM_NONE;
|
||||
st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
free(ctx);
|
||||
return 0;
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS: {
|
||||
zip_int64_t mask = zip_source_supports(src);
|
||||
zip_int64_t mask = zip_source_supports(src);
|
||||
|
||||
if (mask < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
if (mask < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
|
||||
return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
zip_int64_t new_position;
|
||||
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
zip_int64_t new_position;
|
||||
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
|
||||
_zip_error_set_from_source(&ctx->error, src);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->position = (zip_uint64_t)new_position;
|
||||
ctx->position = (zip_uint64_t)new_position;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->position;
|
||||
return (zip_int64_t)ctx->position;
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_error.c -- get last error from zip_source
|
||||
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_file.h -- header for common file operations
|
||||
Copyright (C) 2020 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 2020-2022 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -34,7 +34,7 @@
|
||||
struct zip_source_file_stat {
|
||||
zip_uint64_t size; /* must be valid for regular files */
|
||||
time_t mtime; /* must always be valid, is initialized to current time */
|
||||
bool exists; /* must always be vaild */
|
||||
bool exists; /* must always be valid */
|
||||
bool regular_file; /* must always be valid */
|
||||
};
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
zip_source_file_common.c -- create data source from file
|
||||
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
|
||||
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
|
||||
|
||||
This file is part of libzip, a library to manipulate ZIP archives.
|
||||
The authors can be contacted at <libzip@nih.at>
|
||||
The authors can be contacted at <info@libzip.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -56,70 +56,70 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
|
||||
zip_source_file_stat_t sb;
|
||||
|
||||
if (ops == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fname != NULL) {
|
||||
if (ops->open == NULL || ops->string_duplicate == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
if (ops->open == NULL || ops->string_duplicate == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INTERNAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (file == NULL) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ctx = (zip_source_file_context_t *)malloc(sizeof(zip_source_file_context_t))) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->ops = ops;
|
||||
ctx->ops_userdata = ops_userdata;
|
||||
ctx->fname = NULL;
|
||||
if (fname) {
|
||||
if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) {
|
||||
zip_error_set(error, ZIP_ER_MEMORY, 0);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
ctx->f = file;
|
||||
ctx->start = start;
|
||||
ctx->len = (zip_uint64_t)len;
|
||||
if (st) {
|
||||
memcpy(&ctx->st, st, sizeof(ctx->st));
|
||||
ctx->st.name = NULL;
|
||||
ctx->st.valid &= ~ZIP_STAT_NAME;
|
||||
memcpy(&ctx->st, st, sizeof(ctx->st));
|
||||
ctx->st.name = NULL;
|
||||
ctx->st.valid &= ~ZIP_STAT_NAME;
|
||||
}
|
||||
else {
|
||||
zip_stat_init(&ctx->st);
|
||||
zip_stat_init(&ctx->st);
|
||||
}
|
||||
|
||||
if (ctx->len > 0) {
|
||||
ctx->st.size = ctx->len;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
ctx->st.size = ctx->len;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
}
|
||||
|
||||
zip_error_init(&ctx->stat_error);
|
||||
@ -154,46 +154,46 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
|
||||
ctx->st.mtime = sb.mtime;
|
||||
ctx->st.valid |= ZIP_STAT_MTIME;
|
||||
}
|
||||
if (sb.regular_file) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
|
||||
if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
|
||||
ctx->st.mtime = sb.mtime;
|
||||
ctx->st.valid |= ZIP_STAT_MTIME;
|
||||
}
|
||||
if (sb.regular_file) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
|
||||
|
||||
if (ctx->start + ctx->len > sb.size) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
if (ctx->start + ctx->len > sb.size) {
|
||||
zip_error_set(error, ZIP_ER_INVAL, 0);
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ctx->len == 0) {
|
||||
ctx->len = sb.size - ctx->start;
|
||||
ctx->st.size = ctx->len;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
if (ctx->len == 0) {
|
||||
ctx->len = sb.size - ctx->start;
|
||||
ctx->st.size = ctx->len;
|
||||
ctx->st.valid |= ZIP_STAT_SIZE;
|
||||
|
||||
/* when using a partial file, don't allow writing */
|
||||
if (ctx->fname && start == 0 && ops->write != NULL) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* when using a partial file, don't allow writing */
|
||||
if (ctx->fname && start == 0 && ops->write != NULL) {
|
||||
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES);
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES);
|
||||
}
|
||||
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
|
||||
if (ops->create_temp_output_cloning != NULL) {
|
||||
if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
|
||||
}
|
||||
if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
|
||||
ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) {
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
free(ctx->fname);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zs;
|
||||
@ -210,169 +210,169 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
|
||||
|
||||
switch (cmd) {
|
||||
case ZIP_SOURCE_ACCEPT_EMPTY:
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE:
|
||||
/* write support should not be set if fname is NULL */
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return ctx->ops->create_temp_output(ctx);
|
||||
/* write support should not be set if fname is NULL */
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return ctx->ops->create_temp_output(ctx);
|
||||
|
||||
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
|
||||
/* write support should not be set if fname is NULL */
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return ctx->ops->create_temp_output_cloning(ctx, len);
|
||||
/* write support should not be set if fname is NULL */
|
||||
if (ctx->fname == NULL) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
|
||||
return -1;
|
||||
}
|
||||
return ctx->ops->create_temp_output_cloning(ctx, len);
|
||||
|
||||
case ZIP_SOURCE_CLOSE:
|
||||
if (ctx->fname) {
|
||||
ctx->ops->close(ctx);
|
||||
ctx->f = NULL;
|
||||
}
|
||||
return 0;
|
||||
if (ctx->fname) {
|
||||
ctx->ops->close(ctx);
|
||||
ctx->f = NULL;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_COMMIT_WRITE: {
|
||||
zip_int64_t ret = ctx->ops->commit_write(ctx);
|
||||
ctx->fout = NULL;
|
||||
if (ret == 0) {
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
}
|
||||
return ret;
|
||||
zip_int64_t ret = ctx->ops->commit_write(ctx);
|
||||
ctx->fout = NULL;
|
||||
if (ret == 0) {
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_ERROR:
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
return zip_error_to_data(&ctx->error, data, len);
|
||||
|
||||
case ZIP_SOURCE_FREE:
|
||||
free(ctx->fname);
|
||||
free(ctx->tmpname);
|
||||
if (ctx->f) {
|
||||
ctx->ops->close(ctx);
|
||||
}
|
||||
free(ctx);
|
||||
return 0;
|
||||
free(ctx->fname);
|
||||
free(ctx->tmpname);
|
||||
if (ctx->f) {
|
||||
ctx->ops->close(ctx);
|
||||
}
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
return sizeof(ctx->attributes);
|
||||
if (len < sizeof(ctx->attributes)) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
|
||||
return sizeof(ctx->attributes);
|
||||
|
||||
case ZIP_SOURCE_OPEN:
|
||||
if (ctx->fname) {
|
||||
if (ctx->ops->open(ctx) == false) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ctx->fname) {
|
||||
if (ctx->ops->open(ctx) == false) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->start > 0) { // TODO: rewind on re-open
|
||||
if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) {
|
||||
/* TODO: skip by reading */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->offset = 0;
|
||||
return 0;
|
||||
if (ctx->start > 0) { // TODO: rewind on re-open
|
||||
if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) {
|
||||
/* TODO: skip by reading */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ctx->offset = 0;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_READ: {
|
||||
zip_int64_t i;
|
||||
zip_uint64_t n;
|
||||
zip_int64_t i;
|
||||
zip_uint64_t n;
|
||||
|
||||
if (ctx->len > 0) {
|
||||
n = ZIP_MIN(ctx->len - ctx->offset, len);
|
||||
}
|
||||
else {
|
||||
n = len;
|
||||
}
|
||||
if (ctx->len > 0) {
|
||||
n = ZIP_MIN(ctx->len - ctx->offset, len);
|
||||
}
|
||||
else {
|
||||
n = len;
|
||||
}
|
||||
|
||||
if ((i = ctx->ops->read(ctx, buf, n)) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, errno);
|
||||
return -1;
|
||||
}
|
||||
ctx->offset += (zip_uint64_t)i;
|
||||
if ((i = ctx->ops->read(ctx, buf, n)) < 0) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_READ, errno);
|
||||
return -1;
|
||||
}
|
||||
ctx->offset += (zip_uint64_t)i;
|
||||
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_REMOVE:
|
||||
return ctx->ops->remove(ctx);
|
||||
return ctx->ops->remove(ctx);
|
||||
|
||||
case ZIP_SOURCE_ROLLBACK_WRITE:
|
||||
ctx->ops->rollback_write(ctx);
|
||||
ctx->fout = NULL;
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
ctx->ops->rollback_write(ctx);
|
||||
ctx->fout = NULL;
|
||||
free(ctx->tmpname);
|
||||
ctx->tmpname = NULL;
|
||||
return 0;
|
||||
|
||||
case ZIP_SOURCE_SEEK: {
|
||||
zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
|
||||
zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
|
||||
|
||||
if (new_offset < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (new_offset < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The actual offset inside the file must be representable as zip_int64_t. */
|
||||
if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
/* The actual offset inside the file must be representable as zip_int64_t. */
|
||||
if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) {
|
||||
zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->offset = (zip_uint64_t)new_offset;
|
||||
ctx->offset = (zip_uint64_t)new_offset;
|
||||
|
||||
if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SEEK_WRITE: {
|
||||
zip_source_args_seek_t *args;
|
||||
zip_source_args_seek_t *args;
|
||||
|
||||
args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
|
||||
if (args == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_STAT: {
|
||||
if (len < sizeof(ctx->st))
|
||||
return -1;
|
||||
if (len < sizeof(ctx->st))
|
||||
return -1;
|
||||
|
||||
if (zip_error_code_zip(&ctx->stat_error) != 0) {
|
||||
zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
|
||||
return -1;
|
||||
}
|
||||
if (zip_error_code_zip(&ctx->stat_error) != 0) {
|
||||
zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data, &ctx->st, sizeof(ctx->st));
|
||||
return sizeof(ctx->st);
|
||||
memcpy(data, &ctx->st, sizeof(ctx->st));
|
||||
return sizeof(ctx->st);
|
||||
}
|
||||
|
||||
case ZIP_SOURCE_SUPPORTS:
|
||||
return ctx->supports;
|
||||
return ctx->supports;
|
||||
|
||||
case ZIP_SOURCE_TELL:
|
||||
return (zip_int64_t)ctx->offset;
|
||||
return (zip_int64_t)ctx->offset;
|
||||
|
||||
case ZIP_SOURCE_TELL_WRITE:
|
||||
return ctx->ops->tell(ctx, ctx->fout);
|
||||
return ctx->ops->tell(ctx, ctx->fout);
|
||||
|
||||
case ZIP_SOURCE_WRITE:
|
||||
return ctx->ops->write(ctx, data, len);
|
||||
return ctx->ops->write(ctx, data, len);
|
||||
|
||||
default:
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user