Using PathView to pass paths to APIs #2

Merged
jeanlemotan merged 3 commits from cv_path_view into main 2024-09-05 16:52:53 +02:00
144 changed files with 16978 additions and 1330 deletions
Showing only changes of commit 56c367a3c4 - Show all commits
+2 -1
View File
@@ -50,7 +50,7 @@ if(NOT TARGET zlib)
endif()
endif()
file(GLOB_RECURSE SRC "src/*.cpp")
file(GLOB_RECURSE SRC "src/*.cpp" "src/*.c" "src/*.h")
file(GLOB_RECURSE HEADERS "include/*.h" "include/*.inl")
foreach(_source IN ITEMS ${HEADERS})
@@ -70,6 +70,7 @@ endforeach()
add_library(FS STATIC ${SRC} ${HEADERS})
target_include_directories(FS PUBLIC "include")
target_include_directories(FS PRIVATE "src")
target_include_directories(FS PRIVATE "src/libzip")
target_include_directories(FS PUBLIC "${PROJECT_SOURCE_DIR}/../Logger/include")
target_include_directories(FS PUBLIC "${PROJECT_SOURCE_DIR}/../cppcoro/include")
target_include_directories(FS PRIVATE "src/fast_io/include")
@@ -8,11 +8,11 @@
namespace fs
{
class FS_API StreamSourceToSourceAdapter final : public IMapSource
class FS_API StreamSourceToMapSourceAdapter final : public IMapSource
{
public:
explicit StreamSourceToSourceAdapter(tl::unique_ref<IStreamSource>&& i_srcSource);
~StreamSourceToSourceAdapter() override = default;
explicit StreamSourceToMapSourceAdapter(tl::unique_ref<IStreamSource> i_srcSource);
~StreamSourceToMapSourceAdapter() override = default;
tl::optional<Error> getLastError() const override;
-37
View File
@@ -1,37 +0,0 @@
#pragma once
#include "fs/AbsPath.h"
#include "fs/zip/ZipWriter.h"
#include "tl/ptr.h"
namespace fs
{
class IFilesystem;
//////////////////////////////////////////////////////////////////////////
class FS_API DeflateFileWriter
{
public:
//compression level: 0 to 9
DeflateFileWriter(AbsPathView filePath, tl::lent_ref<IFilesystem> filesystem, uint8_t compressionLevel);
DeflateFileWriter(const DeflateFileWriter&) = delete;
DeflateFileWriter& operator=(const DeflateFileWriter&) = delete;
DeflateFileWriter(DeflateFileWriter&&) = default;
DeflateFileWriter& operator=(DeflateFileWriter&&) = default;
ZipWriter::DataWriterResult operator()(IStreamSink& sink);
private:
AbsPath m_filePath;
tl::lent_ref<IFilesystem> m_filesystem;
uint8_t m_compressionLevel = 9;
};
//////////////////////////////////////////////////////////////////////////
}
-37
View File
@@ -1,37 +0,0 @@
#pragma once
#include "fs/IStreamSource.h"
#include "fs/zip/ZipWriter.h"
namespace fs
{
//////////////////////////////////////////////////////////////////////////
class ISource;
//////////////////////////////////////////////////////////////////////////
class FS_API DeflateSinkWriter
{
public:
//compression level: 0 to 9
DeflateSinkWriter(IStreamSource& source, uint8_t compressionLevel);
DeflateSinkWriter(tl::span<const uint8_t> data, uint8_t compressionLevel);
DeflateSinkWriter(const DeflateSinkWriter&) = delete;
DeflateSinkWriter& operator=(const DeflateSinkWriter&) = delete;
DeflateSinkWriter(DeflateSinkWriter&&) = default;
DeflateSinkWriter& operator=(DeflateSinkWriter&&) = default;
ZipWriter::DataWriterResult operator()(IStreamSink& sink);
private:
IStreamSource* m_source = nullptr;
tl::span<const uint8_t> m_data;
uint8_t m_compressionLevel = 9;
};
//////////////////////////////////////////////////////////////////////////
}
-35
View File
@@ -1,35 +0,0 @@
#pragma once
#include "fs/AbsPath.h"
#include "fs/zip/ZipWriter.h"
#include "tl/ptr.h"
namespace fs
{
class IFilesystem;
//////////////////////////////////////////////////////////////////////////
class FS_API StoreFileWriter
{
public:
StoreFileWriter(AbsPathView filePath, tl::lent_ref<IFilesystem> filesystem);
StoreFileWriter(const StoreFileWriter&) = delete;
StoreFileWriter& operator=(const StoreFileWriter&) = delete;
StoreFileWriter(StoreFileWriter&&) = default;
StoreFileWriter& operator=(StoreFileWriter&&) = default;
ZipWriter::DataWriterResult operator()(IStreamSink& sink);
private:
AbsPath m_filePath;
tl::lent_ref<IFilesystem> m_filesystem;
};
//////////////////////////////////////////////////////////////////////////
}
-32
View File
@@ -1,32 +0,0 @@
#pragma once
#include "fs/zip/ZipWriter.h"
namespace fs
{
//////////////////////////////////////////////////////////////////////////
class ISource;
//////////////////////////////////////////////////////////////////////////
class FS_API StoreSinkWriter
{
public:
explicit StoreSinkWriter(ISource& source);
StoreSinkWriter(const StoreSinkWriter&) = delete;
StoreSinkWriter& operator=(const StoreSinkWriter&) = delete;
StoreSinkWriter(StoreSinkWriter&&) = default;
StoreSinkWriter& operator=(StoreSinkWriter&&) = default;
ZipWriter::DataWriterResult operator()(IStreamSink& sink);
private:
tl::reference_wrapper<ISource> m_inSource;
};
//////////////////////////////////////////////////////////////////////////
}
-158
View File
@@ -1,158 +0,0 @@
#pragma once
#include "tl/flag_set.h"
#include "fs/Api.h"
namespace fs
{
class FS_API ZipBase
{
public:
enum class GeneralBitFlag : uint16_t
{
Encrypted = 1 << 0,
CompressionMethodSpecific1 = 1 << 1,
CompressionMethodSpecific2 = 1 << 2,
DataDescriptorNeeded = 1 << 3,
StrongEncryption = 1 << 6,
LanguageEncodingFlag = 1 << 11,
LocalHeaderFieldsMasked = 1 << 13,
};
typedef tl::flag_set<GeneralBitFlag> GeneralBitFlags;
enum class CompressionMethod : uint16_t
{
Store = 0,
Shrunk = 1,
Reduced1 = 2,
Reduced2 = 3,
Reduced3 = 4,
Reduced4 = 5,
Implode = 6,
//Reserved = 7,
Deflate = 8,
Deflate64 = 9,
PKWareImplode = 10,
//Reserved = 11,
BZip2 = 12,
//Reserved = 13,
LZMA = 14,
//Reserved = 15,
//Reserved = 16,
//Reserved = 17,
Terse = 18,
LZ77 = 19,
LZ4 = 20, // non-standard
ZStd = 21, // non-standard
WavPack = 97,
PPMd = 98,
};
protected:
//////////////////////////////////////////////////////////////////////////
//These structs follow pretty closely the https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT standard
#pragma pack(push, 1)
struct LocalFileHeader
{
static constexpr uint32_t k_signature = 0x04034b50u;
uint32_t signature = k_signature;
uint16_t versionNeededToExtract = 0;
uint16_t generalBitFlag = 0;
uint16_t compressionMethod = 0;
uint16_t lastModFileTime = 0;
uint16_t lastModFileDate = 0;
uint32_t crc32 = 0;
uint32_t compressedSize = 0;
uint32_t uncompressedSize = 0;
uint16_t filenameLength = 0;
uint16_t extraFieldLength = 0;
};
struct DataDescriptor
{
uint32_t crc32 = 0;
uint32_t compressedSize = 0;
uint32_t uncompressedSize = 0;
};
struct CentralDirectoryFileHeader
{
static constexpr uint32_t k_signature = 0x02014b50u;
uint32_t signature = k_signature;
uint16_t versionMadeBy = 0;
uint16_t versionNeededToExtract = 0;
uint16_t generalBitFlag = 0;
uint16_t compressionMethod = 0;
uint16_t lastModFileTime = 0;
uint16_t lastModFileDate = 0;
uint32_t crc32 = 0;
uint32_t compressedSize = 0;
uint32_t uncompressedSize = 0;
uint16_t filenameLength = 0;
uint16_t extraFieldLength = 0;
uint16_t fileCommentLength = 0;
uint16_t diskNumberStart = 0;
uint16_t internalFileAttributes = 0;
uint32_t externalFileAttributes = 0;
uint32_t localHeaderOffset = 0;
};
struct EndOfCentralDirectoryRecord
{
static constexpr uint32_t k_signature = 0x06054b50u;
uint32_t signature = k_signature;
uint16_t diskNumber = 0;
uint16_t centralDirectoryStartDiskNumber = 0;
uint16_t centralDirectoryRecordCountOnThisDisk = 0;
uint16_t centralDirectoryRecordCount = 0;
uint32_t centralDirectorySize = 0;
uint32_t centralDirectoryOffset = 0;
uint16_t zipFileCommentLength = 0;
};
struct ExtendedInformationExtraField64
{
static constexpr uint32_t k_tag = 0x0001;
uint16_t tag = k_tag;
uint16_t size = 0;
uint64_t originalSize = 0;
uint64_t compressedSize = 0;
uint64_t localHeaderOffset = 0;
uint32_t diskNumber = 0;
};
struct EndOfCentralDirectoryRecord64
{
static constexpr uint32_t k_signature = 0x06064b50u;
uint32_t signature = k_signature;
uint64_t endOfCentralDirectorySize = 0;
uint16_t versionMadeBy = 0;
uint16_t versionNeededToExtract = 0;
uint32_t diskNumber = 0;
uint32_t centralDirectoryStartDiskNumber = 0;
uint64_t centralDirectoryRecordCountOnThisDisk = 0;
uint64_t centralDirectoryRecordCount = 0;
uint64_t centralDirectorySize = 0;
uint64_t centralDirectoryOffset = 0;
};
struct EndOfCentralDirectoryLocator64
{
static constexpr uint32_t k_signature = 0x07064b50u;
uint32_t signature = k_signature;
uint32_t centralDirectoryStartDiskNumber = 0;
uint64_t endOfCentralDirectoryRecordOffset = 0;
uint32_t diskCount = 0;
};
#pragma pack(pop)
static void computeMsDosTime(time_t time, uint16_t& o_date, uint16_t& o_time);
static CentralDirectoryFileHeader computeCentralDirectoryFileHeader(const LocalFileHeader& header, bool zip64);
};
}
+50 -27
View File
@@ -3,18 +3,40 @@
#include "tl/result.h"
#include "tl/string.h"
#include "tl/vector_map.h"
#include "fs/IStreamSource.h"
#include "fs/IPack.h"
#include "fs/AbsPath.h"
#include "fs/zip/ZipReader.h"
#include "fs/Api.h"
struct zip;
struct zip_source;
struct zip_file;
namespace tl
{
template<> struct ptr_traits<zip>
{
static constexpr inline bool custom_deleter = true;
static constexpr inline bool requires_virtual_destructor_check = false;
};
//template<> struct ptr_traits<zip_source>
//{
// static constexpr inline bool custom_deleter = true;
// static constexpr inline bool requires_virtual_destructor_check = false;
//};
template<> struct ptr_traits<zip_file>
{
static constexpr inline bool custom_deleter = true;
static constexpr inline bool requires_virtual_destructor_check = false;
};
}
namespace fs
{
class MapSourceView;
class FS_API ZipPack final : virtual public IPack
class FS_API ZipPack final : public IPack
{
public:
ZipPack() = default;
@@ -22,10 +44,10 @@ public:
typedef tl::result<tl::unique_ref<ZipPack>, Error> CreateResult;
static CreateResult create(tl::unique_ref<IMapSource> zipFileSource);
static CreateResult create(tl::lent_ref<const IFilesystem> filesystem, AbsPathView zipFileLocation);
static CreateResult create(tl::unique_ref<IMapSource> source);
static CreateResult create(tl::lent_ref<const IFilesystem> filesystem, AbsPathView path);
virtual void setEncryptionData(const tl::string& key, uint32_t rounds);
void setEncryptionData(const tl::string& key, uint32_t rounds);
OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override;
OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override;
@@ -42,46 +64,51 @@ public:
tl::result<AbsPath, Error> convertToNativePath(AbsPathView path) const override;
struct ZipData
{
tl::unique_ptr<IMapSource> fsMapSource;
tl::lent_ptr<const IFilesystem> filesystem;
AbsPath path;
tl::unique_ptr<ISource> fsSource;
uint64_t cachedSize = uint64_t(-1);
//tl::unique_ptr<zip_source> zipSource;
tl::unique_ptr<zip> zipArchive;
};
protected:
struct File;
struct Folder;
struct EntryIndex;
ZipPack(tl::unique_ref<IMapSource> zipFileSource, ZipReader zipReader);
ZipPack(tl::lent_ref<const IFilesystem> filesystem, AbsPathView zipFileLocation, ZipReader zipReader);
ZipPack(tl::shared_ptr<ZipData> data);
OpenMapSourceResult openRawMapSource(const File& file, MapView mapView) const;
OpenSourceResult openRawSource(const File& file) const;
//OpenMapSourceResult openRawMapSource(const File& file, MapView mapView) const;
//OpenSourceResult openRawSource(const File& file) const;
OpenSourceResult openZipSource(const File& file) const;
OpenMapSourceResult openZipMapSource(const File& file) const;
OpenStreamSourceResult openZipStreamSource(const File& file) const;
OpenSourceResult _openSource(const File& file) const;
OpenMapSourceResult _openMapSource(const File& file) const;
OpenStreamSourceResult _openStreamSource(const File& file) const;
uint16_t getOrAddFolder(AbsPathView folderPath, tl::vector<tl::vector<EntryIndex>>& io_childrenIndices);
void createEntries(ZipReader zipReader);
void createEntries(zip& archive);
struct File
{
uint16_t zipIndex = 0; //index inside the zip archive
tl::string name;
uint8_t isCompressed : 1;
uint8_t uncompressedSizeH = 0;
uint8_t compressedSizeH = 0;
uint8_t dataOffsetH = 0;
uint16_t parentIndex = 0;
uint32_t lastModTimePoint = 0;
uint32_t uncompressedSizeL = 0;
uint32_t compressedSizeL = 0;
uint32_t dataOffsetL = 0;
};
static_assert(sizeof(File) <= sizeof(tl::string) + 40, "Check your sizes!!!");
struct Folder
{
uint16_t zipIndex = 0; //index inside the zip archive
tl::string name;
uint16_t parentIndex = 0;
uint16_t childrenStartIndex = 0; // this is an index inside m_childrenIndices
uint16_t childrenCount = 0;
uint32_t lastModTimePoint = 0;
};
static_assert(sizeof(Folder) <= sizeof(tl::string) + 20, "Check your sizes!!!");
@@ -99,12 +126,8 @@ protected:
static_assert(sizeof(EntryIndex) == 4, "Check your sizes!!!");
private:
tl::lent_ptr<const IFilesystem> m_filesystem;
mutable std::mutex m_zipMapSourceLock;
tl::unique_ptr<IMapSource> m_zipMapSource;
AbsPath m_zipFileLocation;
tl::shared_ptr<ZipData> m_zipData;
tl::string m_encryptionKey;
uint32_t m_encryptionRounds = 32;
-63
View File
@@ -1,63 +0,0 @@
#pragma once
#include "ZipBase.h"
#include "tl/memory_buffer.h"
#include "tl/result.h"
#include "tl/vector.h"
namespace fs
{
//////////////////////////////////////////////////////////////////////////
class ISource;
//////////////////////////////////////////////////////////////////////////
class ZipReader : public ZipBase
{
public:
enum class ErrorCode : uint8_t
{
InvalidStream,
BadSignature,
BadOffset,
CorruptedFile,
};
typedef tl::error<ErrorCode> Error;
typedef tl::result<ZipReader, Error> CreateResult;
static CreateResult create(ISource& source);
struct Entry
{
tl::string name;
CompressionMethod compressionMethod = CompressionMethod::Store;
GeneralBitFlags generalBitFlags;
uint64_t uncompressedSize = 0;
uint64_t compressedSize = 0;
uint32_t crc32 = 0;
uint64_t localHeaderOffset = 0;
uint64_t dataOffset = 0;
time_t lastModTimePoint = 0;
tl::memory_buffer comment;
};
size_t getEntryCount() const;
const Entry& getEntry(size_t index) const;
typedef tl::result<void, Error> SeekResult;
SeekResult seekSourceToEntryData(const Entry& entry, ISource& o_source) const;
private:
explicit ZipReader(tl::vector<Entry> entries);
typedef tl::result<tl::pair<uint64_t, uint64_t>, Error> CentralDirectoryResult;
static CentralDirectoryResult findCentralDirectoryBounds(ISource& source);
tl::vector<Entry> m_entries;
};
//////////////////////////////////////////////////////////////////////////
}
+2 -2
View File
@@ -13,7 +13,7 @@ FS_API UnzipResult unzipSource(IFilesystem& dstFilesystem, AbsPathView filePath,
FS_API UnzipResult unzipFile(IFilesystem& dstFilesystem, AbsPathView filePath, tl::lent_ref<const IFilesystem> filesystem, AbsPathView srcFilePath);
typedef tl::result<void, Error> ZipResult;
FS_API ZipResult zipToSink(ISink& sink, tl::lent_ref<IFilesystem> filesystem, AbsPathView path, uint8_t compressionLevel, size_t fileDataAlignment = 0);
FS_API ZipResult zipToFile(IFilesystem& dstFilesystem, AbsPathView dstFilePath, tl::lent_ref<IFilesystem> filesystem, AbsPathView path, uint8_t compressionLevel, size_t fileDataAlignment = 0);
FS_API ZipResult zipToSink(ISink& sink, tl::lent_ref<IFilesystem> filesystem, AbsPathView path, uint8_t compressionLevel);
FS_API ZipResult zipToFile(IFilesystem& dstFilesystem, AbsPathView dstFilePath, tl::lent_ref<IFilesystem> filesystem, AbsPathView path, uint8_t compressionLevel);
}
+29 -41
View File
@@ -1,77 +1,65 @@
#pragma once
#include "ZipBase.h"
#include "fs/Api.h"
#include <tl/memory_buffer.h>
#include <tl/span.h>
#include <tl/vector.h>
#include <tl/result.h>
#include <tl/optional.h>
#include "fs/zip/ZipPack.h"
namespace fs
{
//////////////////////////////////////////////////////////////////////////
class IStreamSource;
class ISource;
class IStreamSink;
class ISink;
//////////////////////////////////////////////////////////////////////////
class FS_API ZipWriter : public ZipBase
class FS_API ZipWriter
{
public:
struct DataWriterPayload
{
CompressionMethod compressionMethod;
uint32_t uncompressedCRC32 = 0; //mandatory!!!
uint64_t uncompressedSize = 0; //optional, will be set to the written size if == 0
};
//0 - no compression (Store)
//9 - max compression (Deflate)
using Compression = uint8_t;
using DataWriterError = tl::generic_error;
using DataWriterResult = tl::result<DataWriterPayload, DataWriterError>;
ZipWriter(ISink& sink);
~ZipWriter();
using DataWriter = tl::function<DataWriterResult(IStreamSink& sink)>;
ZipWriter(ISink& sink, size_t fileDataAlignment);
~ZipWriter() = default;
tl::result<void> addFile(tl::string name, const DataWriter& dataWriter);
tl::result<void> addFile(tl::string name, tl::optional<time_t> lastModificationTime, const DataWriter& dataWriter);
tl::result<void> addBuffer(tl::string name, Compression compression, tl::span<const uint8_t> buffer);
tl::result<void> addBuffer(tl::string name, time_t lastModificationTime, Compression compression, tl::span<const uint8_t> buffer);
tl::result<void> addBuffer(tl::string name,
tl::span<const uint8_t> comment,
tl::span<const uint8_t> extraField,
time_t lastModificationTime,
Compression compression,
tl::span<const uint8_t> buffer);
tl::result<void> addFile(tl::string name, Compression compression, ISource& source);
tl::result<void> addFile(tl::string name, time_t lastModificationTime, Compression compression, ISource& source);
tl::result<void> addFile(tl::string name,
tl::span<const uint8_t> comment,
tl::span<const uint8_t> extraField,
GeneralBitFlags generalBitFlags,
tl::optional<time_t> lastModificationTime,
const DataWriter& dataWriter);
time_t lastModificationTime,
Compression compression,
ISource& source);
void finish();
private:
uint64_t computePadding(uint64_t offset, const LocalFileHeader& header) const;
tl::result<uint64_t> _addSource(tl::string name,
tl::span<const uint8_t> comment,
tl::span<const uint8_t> extraField,
time_t lastModificationTime,
Compression compression,
zip_source* source);
ISink& m_sink;
size_t m_fileDataAlignment = 0;
struct CentralDirectoryRecord
{
uint64_t compressedSize = 0;
uint64_t uncompressedSize = 0;
uint64_t localHeaderOffset = 0;
CentralDirectoryFileHeader header;
tl::string name;
tl::memory_buffer comment;
tl::memory_buffer extraField;
bool zip64 = false;
};
tl::vector<CentralDirectoryRecord> m_records;
tl::memory_buffer m_buffer;
tl::unique_ptr<zip> m_zipArchive;
};
//////////////////////////////////////////////////////////////////////////
}
@@ -1,9 +1,10 @@
#include "StdAfx.h"
#include "fs/StreamSourceToSourceAdapter.h"
#include "fs/StreamSourceToMapSourceAdapter.h"
#include <algorithm>
#include "fs/ReadStream.h"
#include "tl/narrow_cast.h"
namespace fs
@@ -12,21 +13,21 @@ namespace fs
static constexpr size_t k_chunkSize = 10 * 1024;
StreamSourceToSourceAdapter::StreamSourceToSourceAdapter(tl::unique_ref<IStreamSource>&& srcSource)
StreamSourceToMapSourceAdapter::StreamSourceToMapSourceAdapter(tl::unique_ref<IStreamSource> srcSource)
: m_srcSource(std::move(srcSource))
{
}
//////////////////////////////////////////////////////////////////////////
tl::optional<Error> StreamSourceToSourceAdapter::getLastError() const
tl::optional<Error> StreamSourceToMapSourceAdapter::getLastError() const
{
return m_optLastError;
}
//////////////////////////////////////////////////////////////////////////
size_t StreamSourceToSourceAdapter::read(tl::span<uint8_t> data)
size_t StreamSourceToMapSourceAdapter::read(tl::span<uint8_t> data)
{
if (m_optLastError.has_value())
{
@@ -69,7 +70,7 @@ size_t StreamSourceToSourceAdapter::read(tl::span<uint8_t> data)
//////////////////////////////////////////////////////////////////////////
void StreamSourceToSourceAdapter::seekBeg(uint64_t offset)
void StreamSourceToMapSourceAdapter::seekBeg(uint64_t offset)
{
if (m_optLastError.has_value())
{
@@ -88,7 +89,7 @@ void StreamSourceToSourceAdapter::seekBeg(uint64_t offset)
//////////////////////////////////////////////////////////////////////////
void StreamSourceToSourceAdapter::seekRel(int64_t offset)
void StreamSourceToMapSourceAdapter::seekRel(int64_t offset)
{
if (m_optLastError.has_value())
{
@@ -107,7 +108,7 @@ void StreamSourceToSourceAdapter::seekRel(int64_t offset)
//////////////////////////////////////////////////////////////////////////
uint64_t StreamSourceToSourceAdapter::tell() const
uint64_t StreamSourceToMapSourceAdapter::tell() const
{
if (m_optLastError.has_value())
{
@@ -120,7 +121,7 @@ uint64_t StreamSourceToSourceAdapter::tell() const
//////////////////////////////////////////////////////////////////////////
uint64_t StreamSourceToSourceAdapter::getSize() const
uint64_t StreamSourceToMapSourceAdapter::getSize() const
{
if (m_optLastError.has_value())
{
@@ -137,7 +138,7 @@ uint64_t StreamSourceToSourceAdapter::getSize() const
//////////////////////////////////////////////////////////////////////////
bool StreamSourceToSourceAdapter::isEOS() const
bool StreamSourceToMapSourceAdapter::isEOS() const
{
if (m_optLastError.has_value())
{
@@ -156,14 +157,14 @@ bool StreamSourceToSourceAdapter::isEOS() const
//////////////////////////////////////////////////////////////////////////
size_t StreamSourceToSourceAdapter::getPreferredBufferSize() const
size_t StreamSourceToMapSourceAdapter::getPreferredBufferSize() const
{
return m_srcSource->getPreferredBufferSize();
}
//////////////////////////////////////////////////////////////////////////
tl::span<const uint8_t> StreamSourceToSourceAdapter::map(size_t size)
tl::span<const uint8_t> StreamSourceToMapSourceAdapter::map(size_t size)
{
if (m_optLastError.has_value())
{
@@ -189,33 +190,19 @@ tl::span<const uint8_t> StreamSourceToSourceAdapter::map(size_t size)
//////////////////////////////////////////////////////////////////////////
void StreamSourceToSourceAdapter::readAll() const
void StreamSourceToMapSourceAdapter::readAll() const
{
if (m_readAll)
return;
const size_t chunkSize = m_srcSource->getPreferredBufferSize() > 0 ? m_srcSource->getPreferredBufferSize() : k_chunkSize;
do
if (!m_readAll)
{
const size_t dataSize = m_data.size();
m_data.resize_uninitialized(dataSize + chunkSize);
const uint64_t read = m_srcSource->read({ m_data.data() + dataSize, chunkSize });
if (read < chunkSize || m_srcSource->isEOS())
{
m_data.resize_uninitialized(dataSize + tl::narrow<size_t>(read));
break;
}
m_optLastError = m_srcSource->getLastError();
if (m_optLastError != tl::nullopt)
if (auto readResult = fs::readStream(m_data, *m_srcSource); readResult.has_error())
{
m_optLastError = readResult.error();
m_data.clear();
break;
}
} while (true);
m_data.shrink_to_fit();
m_readAll = true;
}
}
//////////////////////////////////////////////////////////////////////////
+196
View File
@@ -0,0 +1,196 @@
include(CheckFunctionExists)
set(CMAKE_C_VISIBILITY_PRESET hidden)
add_library(zip
zip_add.c
zip_add_dir.c
zip_add_entry.c
zip_algorithm_deflate.c
zip_buffer.c
zip_close.c
zip_delete.c
zip_dir_add.c
zip_dirent.c
zip_discard.c
zip_entry.c
zip_error.c
zip_error_clear.c
zip_error_get.c
zip_error_get_sys_type.c
zip_error_strerror.c
zip_error_to_str.c
zip_extra_field.c
zip_extra_field_api.c
zip_fclose.c
zip_fdopen.c
zip_file_add.c
zip_file_error_clear.c
zip_file_error_get.c
zip_file_get_comment.c
zip_file_get_external_attributes.c
zip_file_get_offset.c
zip_file_rename.c
zip_file_replace.c
zip_file_set_comment.c
zip_file_set_encryption.c
zip_file_set_external_attributes.c
zip_file_set_mtime.c
zip_file_strerror.c
zip_fopen.c
zip_fopen_encrypted.c
zip_fopen_index.c
zip_fopen_index_encrypted.c
zip_fread.c
zip_fseek.c
zip_ftell.c
zip_get_archive_comment.c
zip_get_archive_flag.c
zip_get_encryption_implementation.c
zip_get_file_comment.c
zip_get_name.c
zip_get_num_entries.c
zip_get_num_files.c
zip_hash.c
zip_io_util.c
zip_libzip_version.c
zip_memdup.c
zip_name_locate.c
zip_new.c
zip_open.c
zip_pkware.c
zip_progress.c
zip_rename.c
zip_replace.c
zip_set_archive_comment.c
zip_set_archive_flag.c
zip_set_default_password.c
zip_set_file_comment.c
zip_set_file_compression.c
zip_set_name.c
zip_source_accept_empty.c
zip_source_begin_write.c
zip_source_begin_write_cloning.c
zip_source_buffer.c
zip_source_call.c
zip_source_close.c
zip_source_commit_write.c
zip_source_compress.c
zip_source_crc.c
zip_source_error.c
zip_source_file_common.c
zip_source_free.c
zip_source_function.c
zip_source_get_file_attributes.c
zip_source_is_deleted.c
zip_source_layered.c
zip_source_open.c
zip_source_pass_to_lower_layer.c
zip_source_pkware_decode.c
zip_source_pkware_encode.c
zip_source_read.c
zip_source_remove.c
zip_source_rollback_write.c
zip_source_seek.c
zip_source_seek_write.c
zip_source_stat.c
zip_source_supports.c
zip_source_tell.c
zip_source_tell_write.c
zip_source_window.c
zip_source_write.c
zip_source_zip.c
zip_source_zip_new.c
zip_stat.c
zip_stat_index.c
zip_stat_init.c
zip_strerror.c
zip_string.c
zip_unchange.c
zip_unchange_all.c
zip_unchange_archive.c
zip_unchange_data.c
zip_utf-8.c
${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
)
add_library(libzip::zip ALIAS zip)
if(WIN32)
if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore)
target_sources(zip PRIVATE zip_random_uwp.c)
else()
target_sources(zip PRIVATE zip_random_win32.c)
target_link_libraries(zip PRIVATE advapi32)
endif()
endif(WIN32)
if(HAVE_LIBBZ2)
target_sources(zip PRIVATE zip_algorithm_bzip2.c)
target_link_libraries(zip PRIVATE BZip2::BZip2)
endif()
if(HAVE_LIBLZMA)
target_sources(zip PRIVATE zip_algorithm_xz.c)
target_link_libraries(zip PRIVATE LibLZMA::LibLZMA)
endif()
if(HAVE_LIBZSTD)
target_sources(zip PRIVATE zip_algorithm_zstd.c)
target_link_libraries(zip PRIVATE ${zstd_TARGET})
endif()
if(HAVE_COMMONCRYPTO)
target_sources(zip PRIVATE zip_crypto_commoncrypto.c)
elseif(HAVE_WINDOWS_CRYPTO)
target_sources(zip PRIVATE zip_crypto_win.c)
target_link_libraries(zip PRIVATE bcrypt)
elseif(HAVE_GNUTLS)
target_sources(zip PRIVATE zip_crypto_gnutls.c)
target_link_libraries(zip PRIVATE GnuTLS::GnuTLS Nettle::Nettle)
elseif(HAVE_OPENSSL)
target_sources(zip PRIVATE zip_crypto_openssl.c)
target_link_libraries(zip PRIVATE OpenSSL::Crypto)
elseif(HAVE_MBEDTLS)
target_sources(zip PRIVATE zip_crypto_mbedtls.c)
target_link_libraries(zip PRIVATE MbedTLS::MbedTLS)
endif()
if(HAVE_CRYPTO)
target_sources(zip PRIVATE zip_winzip_aes.c zip_source_winzip_aes_decode.c zip_source_winzip_aes_encode.c)
endif()
if(SHARED_LIB_VERSIONNING)
set_target_properties(zip PROPERTIES VERSION 5.5 SOVERSION 5)
endif()
#target_link_libraries(zip PRIVATE ZLIB::ZLIB)
target_include_directories(zip
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if(LIBZIP_DO_INSTALL)
install(TARGETS zip
EXPORT ${PROJECT_NAME}-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()
# create zip_err_str.c from zip.h and zipint.h
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c
COMMAND "${CMAKE_COMMAND}"
"-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}"
"-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
"-P" "${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake"
DEPENDS
${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake
${PROJECT_SOURCE_DIR}/lib/zip.h
${PROJECT_SOURCE_DIR}/lib/zipint.h
COMMENT "Generating zip_err_str.c"
)
+239
View File
@@ -0,0 +1,239 @@
#ifndef _HAD_LIBZIP_COMPAT_H
#define _HAD_LIBZIP_COMPAT_H
/*
compat.h -- compatibility defines.
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 <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 "zipconf.h"
#include "config.h"
/* to have *_MAX definitions for all types when compiling with g++ */
#define __STDC_LIMIT_MACROS
/* to have ISO C secure library functions */
#define __STDC_WANT_LIB_EXT1__ 1
#define ZIP_STATIC
#define ZIP_EXTERN extern
#ifdef _WIN32
/* for dup(), close(), etc. */
#include <io.h>
#endif
#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#elif !defined(__BOOL_DEFINED)
typedef char bool;
#define true 1
#define false 0
#endif
#include <errno.h>
/* at least MinGW does not provide EOPNOTSUPP, see
* http://sourceforge.net/p/mingw/bugs/263/
*/
#ifndef EOPNOTSUPP
#define EOPNOTSUPP EINVAL
#endif
/* at least MinGW does not provide EOVERFLOW, see
* http://sourceforge.net/p/mingw/bugs/242/
*/
#ifndef EOVERFLOW
#define EOVERFLOW EFBIG
#endif
/* not supported on at least Windows */
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifdef _WIN32
#if defined(HAVE__CLOSE)
#define close _close
#endif
#if defined(HAVE__DUP)
#define dup _dup
#endif
/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */
#if defined(HAVE__FDOPEN)
#define fdopen _fdopen
#endif
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
#define fileno _fileno
#endif
#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
#define snprintf _snprintf
#endif
#if !defined(HAVE__SNWPRINTF_S)
#define _snwprintf_s(buf, bufsz, len, fmt, ...) (_snwprintf((buf), (len), (fmt), __VA_ARGS__))
#endif
#if defined(HAVE__STRDUP)
#if !defined(HAVE_STRDUP) || defined(_WIN32)
#undef strdup
#define strdup _strdup
#endif
#endif
#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE)
#define _setmode setmode
#endif
#if !defined(HAVE_STRTOLL) && defined(HAVE__STRTOI64)
#define strtoll _strtoi64
#endif
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
#define strtoull _strtoui64
#endif
#if defined(HAVE__UNLINK)
#define unlink _unlink
#endif
#endif
#ifndef HAVE_FSEEKO
#define fseeko(s, o, w) (fseek((s), (long int)(o), (w)))
#endif
#ifndef HAVE_FTELLO
#define ftello(s) ((long)ftell((s)))
#endif
#ifdef HAVE_LOCALTIME_S
#ifdef _WIN32
/* Windows is incompatible to the C11 standard, hurray! */
#define zip_localtime(t, tm) (localtime_s((tm), (t)) == 0 ? tm : NULL)
#else
#define zip_localtime localtime_s
#endif
#else
#ifdef HAVE_LOCALTIME_R
#define zip_localtime localtime_r
#else
#define zip_localtime(t, tm) (localtime(t))
#endif
#endif
#ifndef HAVE_MEMCPY_S
#define memcpy_s(dest, destsz, src, count) (memcpy((dest), (src), (count)) == NULL)
#endif
#ifndef HAVE_SNPRINTF_S
#ifdef HAVE__SNPRINTF_S
#define snprintf_s(buf, bufsz, fmt, ...) (_snprintf_s((buf), (bufsz), (bufsz), (fmt), __VA_ARGS__))
#else
#define snprintf_s snprintf
#endif
#endif
#if !defined(HAVE_STRCASECMP)
#if defined(HAVE__STRICMP)
#define strcasecmp _stricmp
#elif defined(HAVE_STRICMP)
#define strcasecmp stricmp
#endif
#endif
#ifndef HAVE_STRNCPY_S
#define strncpy_s(dest, destsz, src, count) (strncpy((dest), (src), (count)), 0)
#endif
#ifndef HAVE_STRERROR_S
#define strerrorlen_s(errnum) (strlen(strerror(errnum)))
#define strerror_s(buf, bufsz, errnum) ((void)strncpy_s((buf), (bufsz), strerror(errnum), (bufsz)), (buf)[(bufsz)-1] = '\0', strerrorlen_s(errnum) >= (bufsz))
#else
#ifndef HAVE_STRERRORLEN_S
#define strerrorlen_s(errnum) 8192
#endif
#endif
#if SIZEOF_OFF_T == 8
#define ZIP_OFF_MAX ZIP_INT64_MAX
#define ZIP_OFF_MIN ZIP_INT64_MIN
#elif SIZEOF_OFF_T == 4
#define ZIP_OFF_MAX ZIP_INT32_MAX
#define ZIP_OFF_MIN ZIP_INT32_MIN
#elif SIZEOF_OFF_T == 2
#define ZIP_OFF_MAX ZIP_INT16_MAX
#define ZIP_OFF_MIN ZIP_INT16_MIN
#else
#error unsupported size of off_t
#endif
#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO)
#define ZIP_FSEEK_MAX ZIP_OFF_MAX
#define ZIP_FSEEK_MIN ZIP_OFF_MIN
#else
#include <limits.h>
#define ZIP_FSEEK_MAX LONG_MAX
#define ZIP_FSEEK_MIN LONG_MIN
#endif
#ifndef SIZE_MAX
#if SIZEOF_SIZE_T == 8
#define SIZE_MAX ZIP_INT64_MAX
#elif SIZEOF_SIZE_T == 4
#define SIZE_MAX ZIP_INT32_MAX
#elif SIZEOF_SIZE_T == 2
#define SIZE_MAX ZIP_INT16_MAX
#else
#error unsupported size of size_t
#endif
#endif
#ifndef PRId64
#ifdef _MSC_VER
#define PRId64 "I64d"
#else
#define PRId64 "lld"
#endif
#endif
#ifndef PRIu64
#ifdef _MSC_VER
#define PRIu64 "I64u"
#else
#define PRIu64 "llu"
#endif
#endif
#ifndef S_ISDIR
#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISREG
#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
#endif
#endif /* compat.h */
+93
View File
@@ -0,0 +1,93 @@
#ifndef HAD_CONFIG_H
#define HAD_CONFIG_H
#ifndef _HAD_ZIPCONF_H
#include "zipconf.h"
#endif
/* BEGIN DEFINES */
#define ENABLE_FDOPEN
/* #undef HAVE___PROGNAME */
#define HAVE__CLOSE
#define HAVE__DUP
#define HAVE__FDOPEN
#define HAVE__FILENO
#define HAVE__SETMODE
#if defined(_MSC_VER) && _MSC_VER < 1900
#define HAVE__SNPRINTF
#else
/* #undef HAVE__SNPRINTF */
#endif
#define HAVE__SNPRINTF_S
#define HAVE__SNWPRINTF_S
#define HAVE__STRDUP
#define HAVE__STRICMP
#define HAVE__STRTOI64
#define HAVE__STRTOUI64
#define HAVE__UNLINK
/* #undef HAVE_ARC4RANDOM */
/* #undef HAVE_CLONEFILE */
/* #undef HAVE_COMMONCRYPTO */
#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 */
/* #undef HAVE_LIBLZMA */
/* #undef HAVE_LIBZSTD */
/* #undef HAVE_LOCALTIME_R */
#define HAVE_LOCALTIME_S
#define HAVE_MEMCPY_S
/* #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 */
#else
#define HAVE_SNPRINTF
#endif
/* #undef HAVE_SNPRINTF_S */
/* #undef HAVE_STRCASECMP */
#define HAVE_STRDUP
#define HAVE_STRERROR_S
/* #undef HAVE_STRERRORLEN_S */
#define HAVE_STRICMP
#define HAVE_STRNCPY_S
#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 HAVE_WINDOWS_CRYPTO
#define SIZEOF_OFF_T 4
#ifdef _WIN64
#define SIZEOF_SIZE_T 8
#else
#define SIZEOF_SIZE_T 4
#endif
/* #undef HAVE_DIRENT_H */
/* #undef HAVE_FTS_H */
/* #undef HAVE_NDIR_H */
/* #undef HAVE_SYS_DIR_H */
/* #undef HAVE_SYS_NDIR_H */
/* #undef WORDS_BIGENDIAN */
#define HAVE_SHARED
/* END DEFINES */
#define PACKAGE "libzip"
#define VERSION "1.10.1"
#endif /* HAD_CONFIG_H */
+498
View File
@@ -0,0 +1,498 @@
#ifndef _HAD_ZIP_H
#define _HAD_ZIP_H
/*
zip.h -- exported declarations.
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 <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.
*/
#ifdef __cplusplus
extern "C" {
#if 0
} /* fix autoindent */
#endif
#endif
#include <zipconf.h>
#define ZIP_STATIC
#define ZIP_EXTERN extern
#ifndef ZIP_DEPRECATED
#if defined(__GNUC__) || defined(__clang__)
#define ZIP_DEPRECATED(x) __attribute__((deprecated(x)))
#elif defined(_MSC_VER)
#define ZIP_DEPRECATED(x) __declspec(deprecated(x))
#else
#define ZIP_DEPRECATED(x)
#endif
#endif
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
/* flags for fs_zip_open */
#define ZIP_CREATE 1
#define ZIP_EXCL 2
#define ZIP_CHECKCONS 4
#define ZIP_TRUNCATE 8
#define ZIP_RDONLY 16
/* flags for fs_zip_name_locate, fs_zip_fopen, fs_zip_stat, ... */
#define ZIP_FL_NOCASE 1u /* ignore case on name lookup */
#define ZIP_FL_NODIR 2u /* ignore directory component */
#define ZIP_FL_COMPRESSED 4u /* read compressed data */
#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */
/* 16u was ZIP_FL_RECOMPRESS, which is deprecated */
#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */
#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */
#define ZIP_FL_ENC_RAW 64u /* get unmodified string */
#define ZIP_FL_ENC_STRICT 128u /* follow specification strictly */
#define ZIP_FL_LOCAL 256u /* in local header */
#define ZIP_FL_CENTRAL 512u /* in central directory */
/* 1024u reserved for internal use */
#define ZIP_FL_ENC_UTF_8 2048u /* string is UTF-8 encoded */
#define ZIP_FL_ENC_CP437 4096u /* string is CP437 encoded */
#define ZIP_FL_OVERWRITE 8192u /* fs_zip_file_add: if file with name exists, overwrite (replace) it */
/* archive global flags flags */
#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */
#define ZIP_AFL_IS_TORRENTZIP 4u /* current archive is torrentzipped */
#define ZIP_AFL_WANT_TORRENTZIP 8u /* write archive in torrentzip format */
#define ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE 16u /* don't remove file if archive is empty */
/* create a new extra field */
#define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX
#define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX
/* length parameter to various functions */
#define ZIP_LENGTH_TO_END 0
#define ZIP_LENGTH_UNCHECKED (-2) /* only supported by fs_zip_source_file and its variants */
/* libzip error codes */
#define ZIP_ER_OK 0 /* N No error */
#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */
#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */
#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */
#define ZIP_ER_SEEK 4 /* S Seek error */
#define ZIP_ER_READ 5 /* S Read error */
#define ZIP_ER_WRITE 6 /* S Write error */
#define ZIP_ER_CRC 7 /* N CRC error */
#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */
#define ZIP_ER_NOENT 9 /* N No such file */
#define ZIP_ER_EXISTS 10 /* N File already exists */
#define ZIP_ER_OPEN 11 /* S Can't open file */
#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */
#define ZIP_ER_ZLIB 13 /* Z Zlib error */
#define ZIP_ER_MEMORY 14 /* N Malloc failure */
#define ZIP_ER_CHANGED 15 /* N Entry has been changed */
#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */
#define ZIP_ER_EOF 17 /* N Premature end of file */
#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 /* 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 */
#define ZIP_ER_RDONLY 25 /* N Read-only archive */
#define ZIP_ER_NOPASSWD 26 /* N No password provided */
#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */
#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */
#define ZIP_ER_INUSE 29 /* N Resource still in use */
#define ZIP_ER_TELL 30 /* S Tell error */
#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */
#define ZIP_ER_CANCELLED 32 /* N Operation cancelled */
#define ZIP_ER_DATA_LENGTH 33 /* N Unexpected length of data */
#define ZIP_ER_NOT_ALLOWED 34 /* N Not allowed in torrentzip */
/* 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_LIBZIP 3 /* sys_err is libzip error code */
/* compression methods */
#define ZIP_CM_DEFAULT -1 /* better of deflate or store */
#define ZIP_CM_STORE 0 /* stored (uncompressed) */
#define ZIP_CM_SHRINK 1 /* shrunk */
#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */
#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */
#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */
#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */
#define ZIP_CM_IMPLODE 6 /* imploded */
/* 7 - Reserved for Tokenizing compression algorithm */
#define ZIP_CM_DEFLATE 8 /* deflated */
#define ZIP_CM_DEFLATE64 9 /* deflate64 */
#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */
/* 11 - Reserved by PKWARE */
#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */
/* 13 - Reserved by PKWARE */
#define ZIP_CM_LZMA 14 /* LZMA (EFS) */
/* 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 */
#define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */
/* encryption methods */
#define ZIP_EM_NONE 0 /* not encrypted */
#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */
#if 0 /* Strong Encryption Header not parsed yet */
#define ZIP_EM_DES 0x6601 /* strong encryption: DES */
#define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */
#define ZIP_EM_3DES_168 0x6603
#define ZIP_EM_3DES_112 0x6609
#define ZIP_EM_PKZIP_AES_128 0x660e
#define ZIP_EM_PKZIP_AES_192 0x660f
#define ZIP_EM_PKZIP_AES_256 0x6610
#define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */
#define ZIP_EM_RC4 0x6801
#endif
#define ZIP_EM_AES_128 0x0101 /* Winzip AES encryption */
#define ZIP_EM_AES_192 0x0102
#define ZIP_EM_AES_256 0x0103
#define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */
#define ZIP_OPSYS_DOS 0x00u
#define ZIP_OPSYS_AMIGA 0x01u
#define ZIP_OPSYS_OPENVMS 0x02u
#define ZIP_OPSYS_UNIX 0x03u
#define ZIP_OPSYS_VM_CMS 0x04u
#define ZIP_OPSYS_ATARI_ST 0x05u
#define ZIP_OPSYS_OS_2 0x06u
#define ZIP_OPSYS_MACINTOSH 0x07u
#define ZIP_OPSYS_Z_SYSTEM 0x08u
#define ZIP_OPSYS_CPM 0x09u
#define ZIP_OPSYS_WINDOWS_NTFS 0x0au
#define ZIP_OPSYS_MVS 0x0bu
#define ZIP_OPSYS_VSE 0x0cu
#define ZIP_OPSYS_ACORN_RISC 0x0du
#define ZIP_OPSYS_VFAT 0x0eu
#define ZIP_OPSYS_ALTERNATE_MVS 0x0fu
#define ZIP_OPSYS_BEOS 0x10u
#define ZIP_OPSYS_TANDEM 0x11u
#define ZIP_OPSYS_OS_400 0x12u
#define ZIP_OPSYS_OS_X 0x13u
#define ZIP_OPSYS_DEFAULT ZIP_OPSYS_UNIX
enum zip_source_cmd {
ZIP_SOURCE_OPEN, /* prepare for reading */
ZIP_SOURCE_READ, /* read data */
ZIP_SOURCE_CLOSE, /* reading is done */
ZIP_SOURCE_STAT, /* get meta information */
ZIP_SOURCE_ERROR, /* get error information */
ZIP_SOURCE_FREE, /* cleanup and free resources */
ZIP_SOURCE_SEEK, /* set position for reading */
ZIP_SOURCE_TELL, /* get read position */
ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */
ZIP_SOURCE_COMMIT_WRITE, /* writing is done */
ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */
ZIP_SOURCE_WRITE, /* write data */
ZIP_SOURCE_SEEK_WRITE, /* set position for writing */
ZIP_SOURCE_TELL_WRITE, /* get write position */
ZIP_SOURCE_SUPPORTS, /* check whether source supports command */
ZIP_SOURCE_REMOVE, /* remove file */
ZIP_SOURCE_RESERVED_1, /* previously used internally */
ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */
ZIP_SOURCE_GET_FILE_ATTRIBUTES, /* get additional file attributes */
ZIP_SOURCE_SUPPORTS_REOPEN /* allow reading from changed entry */
};
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) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_CLOSE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_STAT) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ERROR) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_FREE))
#define ZIP_SOURCE_SUPPORTS_SEEKABLE (ZIP_SOURCE_SUPPORTS_READABLE \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS))
#define ZIP_SOURCE_SUPPORTS_WRITABLE (ZIP_SOURCE_SUPPORTS_SEEKABLE \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_COMMIT_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ROLLBACK_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE))
/* clang-format on */
/* for use by sources */
struct zip_source_args_seek {
zip_int64_t offset;
int whence;
};
typedef struct zip_source_args_seek zip_source_args_seek_t;
#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), (type *)NULL : (type *)(data))
/* error information */
/* use zip_error_*() to access */
struct zip_error {
int zip_err; /* libzip error code (ZIP_ER_*) */
int sys_err; /* copy of errno (E*) or zlib error code */
char *_Nullable str; /* string representation or NULL */
};
#define ZIP_STAT_NAME 0x0001u
#define ZIP_STAT_INDEX 0x0002u
#define ZIP_STAT_SIZE 0x0004u
#define ZIP_STAT_COMP_SIZE 0x0008u
#define ZIP_STAT_MTIME 0x0010u
#define ZIP_STAT_CRC 0x0020u
#define ZIP_STAT_COMP_METHOD 0x0040u
#define ZIP_STAT_ENCRYPTION_METHOD 0x0080u
#define ZIP_STAT_FLAGS 0x0100u
struct fs_zip_stat {
zip_uint64_t valid; /* which fields have valid values */
const char *_Nullable name; /* name of the file */
zip_uint64_t index; /* index within archive */
zip_uint64_t size; /* size of file (uncompressed) */
zip_uint64_t comp_size; /* size of file (compressed) */
time_t mtime; /* modification time */
zip_uint32_t crc; /* crc of file data */
zip_uint16_t comp_method; /* compression method used */
zip_uint16_t encryption_method; /* encryption method used */
zip_uint32_t flags; /* reserved for future use */
};
struct zip_buffer_fragment {
zip_uint8_t *_Nonnull data;
zip_uint64_t length;
};
struct zip_file_attributes {
zip_uint64_t valid; /* which fields have valid values */
zip_uint8_t version; /* version of this struct, currently 1 */
zip_uint8_t host_system; /* host system on which file was created */
zip_uint8_t ascii; /* flag whether file is ASCII text */
zip_uint8_t version_needed; /* minimum version needed to extract file */
zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */
zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */
zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */
};
#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u
#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u
#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u
#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u
#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u
struct zip;
struct zip_file;
struct zip_source;
typedef struct zip zip_t;
typedef struct zip_error zip_error_t;
typedef struct zip_file zip_file_t;
typedef struct zip_file_attributes zip_file_attributes_t;
typedef struct zip_source zip_source_t;
typedef struct fs_zip_stat zip_stat_t;
typedef struct zip_buffer_fragment zip_buffer_fragment_t;
typedef zip_uint32_t zip_flags_t;
typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *_Nonnull, void *_Nullable, void *_Nullable, zip_uint64_t, enum zip_source_cmd);
typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable);
typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable);
#ifndef ZIP_DISABLE_DEPRECATED
#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */
typedef void (*zip_progress_callback_t)(double);
ZIP_DEPRECATED("use 'fs_zip_register_progress_callback_with_state' instead") ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable);
ZIP_DEPRECATED("use 'fs_zip_file_add' instead") ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull);
ZIP_DEPRECATED("use 'fs_zip_dir_add' instead") ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull);
ZIP_DEPRECATED("use 'fs_zip_file_get_comment' instead") ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int);
ZIP_DEPRECATED("use 'fs_zip_get_num_entries' instead") ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull);
ZIP_DEPRECATED("use 'fs_zip_file_rename' instead") ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull);
ZIP_DEPRECATED("use 'fs_zip_file_replace' instead") ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull);
ZIP_DEPRECATED("use 'fs_zip_file_set_comment' instead") ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int);
ZIP_DEPRECATED("use 'fs_zip_error_init_with_code' and 'zip_error_system_type' instead") ZIP_EXTERN int zip_error_get_sys_type(int);
ZIP_DEPRECATED("use 'fs_zip_get_error' instead") ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable);
ZIP_DEPRECATED("use 'zip_error_strerror' instead") ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int);
ZIP_DEPRECATED("use 'fs_zip_file_get_error' instead") ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable);
ZIP_DEPRECATED("use 'fs_zip_source_zip_file' instead") 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_DEPRECATED("use 'fs_zip_source_zip_file_create' instead") 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);
#endif
ZIP_EXTERN int fs_zip_close(zip_t *_Nonnull);
ZIP_EXTERN int fs_zip_delete(zip_t *_Nonnull, zip_uint64_t);
ZIP_EXTERN zip_int64_t fs_zip_dir_add(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
ZIP_EXTERN void fs_zip_discard(zip_t *_Nonnull);
ZIP_EXTERN zip_error_t *_Nonnull fs_zip_get_error(zip_t *_Nonnull);
ZIP_EXTERN void fs_zip_error_clear(zip_t *_Nonnull);
ZIP_EXTERN int fs_zip_error_code_zip(const zip_error_t *_Nonnull);
ZIP_EXTERN int fs_zip_error_code_system(const zip_error_t *_Nonnull);
ZIP_EXTERN void fs_zip_error_fini(zip_error_t *_Nonnull);
ZIP_EXTERN void fs_zip_error_init(zip_error_t *_Nonnull);
ZIP_EXTERN void fs_zip_error_init_with_code(zip_error_t *_Nonnull, int);
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int);
ZIP_EXTERN void zip_error_set_from_source(zip_error_t *_Nonnull, zip_source_t *_Nullable);
ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull);
ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull);
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t);
ZIP_EXTERN int fs_zip_fclose(zip_file_t *_Nonnull);
ZIP_EXTERN zip_t *_Nullable fs_zip_fdopen(int, int, int *_Nullable);
ZIP_EXTERN zip_int64_t fs_zip_file_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull, zip_flags_t);
ZIP_EXTERN void fs_zip_file_attributes_init(zip_file_attributes_t *_Nonnull);
ZIP_EXTERN void fs_zip_file_error_clear(zip_file_t *_Nonnull);
ZIP_EXTERN int fs_zip_file_extra_field_delete(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int fs_zip_file_extra_field_delete_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int fs_zip_file_extra_field_set(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *_Nullable, zip_uint16_t, zip_flags_t);
ZIP_EXTERN zip_int16_t fs_zip_file_extra_fields_count(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
ZIP_EXTERN zip_int16_t fs_zip_file_extra_fields_count_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t);
ZIP_EXTERN const zip_uint8_t *_Nullable fs_zip_file_extra_field_get(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_uint16_t *_Nullable, zip_flags_t);
ZIP_EXTERN const zip_uint8_t *_Nullable fs_zip_file_extra_field_get_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_flags_t);
ZIP_EXTERN const char *_Nullable fs_zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t);
ZIP_EXTERN zip_error_t *_Nonnull fs_zip_file_get_error(zip_file_t *_Nonnull);
ZIP_EXTERN int fs_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 fs_zip_file_is_seekable(zip_file_t *_Nonnull);
ZIP_EXTERN int fs_zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t);
ZIP_EXTERN int fs_zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t);
ZIP_EXTERN int fs_zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int fs_zip_file_set_dostime(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int fs_zip_file_set_encryption(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, const char *_Nullable);
ZIP_EXTERN int fs_zip_file_set_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
ZIP_EXTERN int fs_zip_file_set_mtime(zip_t *_Nonnull, zip_uint64_t, time_t, zip_flags_t);
ZIP_EXTERN const char *_Nonnull fs_zip_file_strerror(zip_file_t *_Nonnull);
ZIP_EXTERN zip_file_t *_Nullable fs_zip_fopen(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
ZIP_EXTERN zip_file_t *_Nullable fs_zip_fopen_encrypted(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, const char *_Nullable);
ZIP_EXTERN zip_file_t *_Nullable fs_zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
ZIP_EXTERN zip_file_t *_Nullable fs_zip_fopen_index_encrypted(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, const char *_Nullable);
ZIP_EXTERN zip_int64_t fs_zip_fread(zip_file_t *_Nonnull, void *_Nonnull, zip_uint64_t);
ZIP_EXTERN zip_int8_t fs_zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int);
ZIP_EXTERN zip_int64_t fs_zip_ftell(zip_file_t *_Nonnull);
ZIP_EXTERN const char *_Nullable fs_zip_get_archive_comment(zip_t *_Nonnull, int *_Nullable, zip_flags_t);
ZIP_EXTERN int fs_zip_get_archive_flag(zip_t *_Nonnull, zip_flags_t, zip_flags_t);
ZIP_EXTERN const char *_Nullable fs_zip_get_name(zip_t *_Nonnull, zip_uint64_t, zip_flags_t);
ZIP_EXTERN zip_int64_t fs_zip_get_num_entries(zip_t *_Nonnull, zip_flags_t);
ZIP_EXTERN const char *_Nonnull fs_zip_libzip_version(void);
ZIP_EXTERN zip_int64_t fs_zip_name_locate(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t);
ZIP_EXTERN zip_t *_Nullable fs_zip_open(const char *_Nonnull, int, int *_Nullable);
ZIP_EXTERN zip_t *_Nullable fs_zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable);
ZIP_EXTERN int fs_zip_register_progress_callback_with_state(zip_t *_Nonnull, double, zip_progress_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
ZIP_EXTERN int fs_zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable);
ZIP_EXTERN int fs_zip_set_archive_comment(zip_t *_Nonnull, const char *_Nullable, zip_uint16_t);
ZIP_EXTERN int fs_zip_set_archive_flag(zip_t *_Nonnull, zip_flags_t, int);
ZIP_EXTERN int fs_zip_set_default_password(zip_t *_Nonnull, const char *_Nullable);
ZIP_EXTERN int fs_zip_set_file_compression(zip_t *_Nonnull, zip_uint64_t, zip_int32_t, zip_uint32_t);
ZIP_EXTERN int fs_zip_source_begin_write(zip_source_t *_Nonnull);
ZIP_EXTERN int fs_zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_buffer(zip_t *_Nonnull, const void *_Nullable, zip_uint64_t, int);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_buffer_fragment(zip_t *_Nonnull, const zip_buffer_fragment_t *_Nonnull, zip_uint64_t, int);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable);
ZIP_EXTERN int fs_zip_source_close(zip_source_t *_Nonnull);
ZIP_EXTERN int fs_zip_source_commit_write(zip_source_t *_Nonnull);
ZIP_EXTERN zip_error_t *_Nonnull fs_zip_source_error(zip_source_t *_Nonnull);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_file(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_filep(zip_t *_Nonnull, FILE *_Nonnull, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_filep_create(FILE *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
ZIP_EXTERN int fs_zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull);
ZIP_EXTERN int fs_zip_source_is_deleted(zip_source_t *_Nonnull);
ZIP_EXTERN int fs_zip_source_is_seekable(zip_source_t *_Nonnull);
ZIP_EXTERN void fs_zip_source_keep(zip_source_t *_Nonnull);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_layered(zip_t *_Nullable, zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_layered_create(zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable);
ZIP_EXTERN zip_int64_t fs_zip_source_make_command_bitmap(zip_source_cmd_t, ...);
ZIP_EXTERN int fs_zip_source_open(zip_source_t *_Nonnull);
ZIP_EXTERN zip_int64_t fs_zip_source_pass_to_lower_layer(zip_source_t *_Nonnull, void *_Nullable, zip_uint64_t, zip_source_cmd_t);
ZIP_EXTERN zip_int64_t fs_zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t);
ZIP_EXTERN void fs_zip_source_rollback_write(zip_source_t *_Nonnull);
ZIP_EXTERN int fs_zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int);
ZIP_EXTERN zip_int64_t fs_zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable);
ZIP_EXTERN int fs_zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int);
ZIP_EXTERN int fs_zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull);
ZIP_EXTERN zip_int64_t fs_zip_source_tell(zip_source_t *_Nonnull);
ZIP_EXTERN zip_int64_t fs_zip_source_tell_write(zip_source_t *_Nonnull);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_window_create(zip_source_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
ZIP_EXTERN zip_int64_t fs_zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_zip_file(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable);
ZIP_EXTERN zip_source_t *_Nullable fs_zip_source_zip_file_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable, zip_error_t *_Nullable);
ZIP_EXTERN int fs_zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull);
ZIP_EXTERN int fs_zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull);
ZIP_EXTERN void fs_zip_stat_init(zip_stat_t *_Nonnull);
ZIP_EXTERN const char *_Nonnull fs_zip_strerror(zip_t *_Nonnull);
ZIP_EXTERN int fs_zip_unchange(zip_t *_Nonnull, zip_uint64_t);
ZIP_EXTERN int fs_zip_unchange_all(zip_t *_Nonnull);
ZIP_EXTERN int fs_zip_unchange_archive(zip_t *_Nonnull);
ZIP_EXTERN int fs_zip_compression_method_supported(zip_int32_t method, int compress);
ZIP_EXTERN int fs_zip_encryption_method_supported(zip_uint16_t method, int encode);
#ifdef __cplusplus
}
#endif
#endif /* _HAD_ZIP_H */
+49
View File
@@ -0,0 +1,49 @@
/*
zip_add.c -- add file via callback function
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
/*
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.
*/
ZIP_EXTERN zip_int64_t
zip_add(zip_t *za, const char *name, zip_source_t *source) {
return fs_zip_file_add(za, name, source, 0);
}
+44
View File
@@ -0,0 +1,44 @@
/*
zip_add_dir.c -- add directory
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
ZIP_EXTERN zip_int64_t
zip_add_dir(zip_t *za, const char *name) {
return fs_zip_dir_add(za, name, 0);
}
+80
View File
@@ -0,0 +1,80 @@
/*
zip_add_entry.c -- create and init struct zip_entry
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 <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"
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
zip_int64_t
_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;
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;
}
idx = za->nentry++;
_zip_entry_init(za->entry + idx);
return (zip_int64_t)idx;
}
+276
View File
@@ -0,0 +1,276 @@
/*
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 <stdlib.h>
#include <zlib-ng.h>
struct ctx {
zip_error_t *error;
bool compress;
int level;
int mem_level;
bool end_of_input;
zng_stream zstr;
};
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, zip_uint32_t 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;
}
ctx->error = error;
ctx->compress = compress;
if (compression_flags >= 1 && compression_flags <= 9) {
ctx->level = (int)compression_flags;
}
else {
ctx->level = Z_BEST_COMPRESSION;
}
ctx->mem_level = compression_flags == TORRENTZIP_COMPRESSION_FLAGS ? TORRENTZIP_MEM_LEVEL : MAX_MEM_LEVEL;
ctx->end_of_input = false;
ctx->zstr.zalloc = Z_NULL;
ctx->zstr.zfree = Z_NULL;
ctx->zstr.opaque = NULL;
return ctx;
}
static void *
compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
return allocate(true, compression_flags, error);
}
static void *
decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
(void)method;
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;
if (!ctx->compress) {
return 0;
}
if (ctx->level < 3) {
return 2 << 1;
}
else if (ctx->level > 7) {
return 1 << 1;
}
return 0;
}
static bool
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
int ret;
(void)st;
(void)attributes;
ctx->zstr.avail_in = 0;
ctx->zstr.next_in = NULL;
ctx->zstr.avail_out = 0;
ctx->zstr.next_out = NULL;
if (ctx->compress) {
/* negative value to tell zlib not to write a header */
ret = zng_deflateInit2(&ctx->zstr, ctx->level, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY);
}
else {
ret = zng_inflateInit2(&ctx->zstr, -MAX_WBITS);
}
if (ret != Z_OK) {
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
return false;
}
return true;
}
static bool
end(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
int err;
if (ctx->compress) {
err = zng_deflateEnd(&ctx->zstr);
}
else {
err = zng_inflateEnd(&ctx->zstr);
}
if (err != Z_OK) {
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
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 = (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;
uInt avail_out;
int ret;
avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
ctx->zstr.avail_out = avail_out;
ctx->zstr.next_out = (Bytef *)data;
if (ctx->compress) {
ret = zng_deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
}
else {
ret = zng_inflate(&ctx->zstr, Z_SYNC_FLUSH);
}
*length = avail_out - ctx->zstr.avail_out;
switch (ret) {
case Z_OK:
return ZIP_COMPRESSION_OK;
case Z_STREAM_END:
return ZIP_COMPRESSION_END;
case Z_BUF_ERROR:
if (ctx->zstr.avail_in == 0) {
return ZIP_COMPRESSION_NEED_DATA;
}
/* fallthrough */
default:
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,
20,
start,
end,
input,
end_of_input,
process
};
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
maximum_compressed_size,
decompress_allocate,
deallocate,
general_purpose_bit_flags,
20,
start,
end,
input,
end_of_input,
process
};
/* clang-format on */
+337
View File
@@ -0,0 +1,337 @@
/*
zip_buffer.c -- bounds checked access to memory buffer
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 <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 <string.h>
#include "zipint.h"
zip_uint8_t *
_zip_buffer_data(zip_buffer_t *buffer) {
return buffer->data;
}
void
_zip_buffer_free(zip_buffer_t *buffer) {
if (buffer == NULL) {
return;
}
if (buffer->free_data) {
free(buffer->data);
}
free(buffer);
}
bool
_zip_buffer_eof(zip_buffer_t *buffer) {
return buffer->ok && buffer->offset == buffer->size;
}
zip_uint8_t *
_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
zip_uint8_t *data;
data = _zip_buffer_peek(buffer, length);
if (data != NULL) {
buffer->offset += length;
}
return data;
}
zip_uint16_t
_zip_buffer_get_16(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
if (data == NULL) {
return 0;
}
return (zip_uint16_t)(data[0] + (data[1] << 8));
}
zip_uint32_t
_zip_buffer_get_32(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
if (data == NULL) {
return 0;
}
return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
}
zip_uint64_t
_zip_buffer_get_64(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
if (data == NULL) {
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];
}
zip_uint8_t
_zip_buffer_get_8(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
if (data == NULL) {
return 0;
}
return data[0];
}
zip_uint64_t
_zip_buffer_left(zip_buffer_t *buffer) {
return buffer->ok ? buffer->size - buffer->offset : 0;
}
zip_uint64_t
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
zip_uint64_t copied;
if (_zip_buffer_left(buffer) < length) {
length = _zip_buffer_left(buffer);
}
copied = 0;
while (copied < length) {
size_t n = ZIP_MIN(length - copied, SIZE_MAX);
(void)memcpy_s(data + copied, n, _zip_buffer_get(buffer, n), n);
copied += n;
}
return copied;
}
zip_buffer_t *
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
bool free_data = (data == NULL);
zip_buffer_t *buffer;
#if ZIP_UINT64_MAX > SIZE_MAX
if (size > SIZE_MAX) {
return NULL;
}
#endif
if (data == NULL) {
if ((data = (zip_uint8_t *)malloc((size_t)size)) == NULL) {
return NULL;
}
}
if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
if (free_data) {
free(data);
}
return NULL;
}
buffer->ok = true;
buffer->data = data;
buffer->size = size;
buffer->offset = 0;
buffer->free_data = free_data;
return buffer;
}
zip_buffer_t *
_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) {
zip_buffer_t *buffer;
if ((buffer = _zip_buffer_new(buf, size)) == 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;
}
return buffer;
}
zip_uint64_t
_zip_buffer_offset(zip_buffer_t *buffer) {
return buffer->ok ? buffer->offset : 0;
}
bool
_zip_buffer_ok(zip_buffer_t *buffer) {
return buffer->ok;
}
zip_uint8_t *
_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;
}
data = buffer->data + buffer->offset;
return data;
}
int
_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;
}
(void)memcpy_s(dst, length, src, length);
return 0;
}
int
_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;
}
data[0] = (zip_uint8_t)(i & 0xff);
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
return 0;
}
int
_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;
}
data[0] = (zip_uint8_t)(i & 0xff);
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
data[2] = (zip_uint8_t)((i >> 16) & 0xff);
data[3] = (zip_uint8_t)((i >> 24) & 0xff);
return 0;
}
int
_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;
}
data[0] = (zip_uint8_t)(i & 0xff);
data[1] = (zip_uint8_t)((i >> 8) & 0xff);
data[2] = (zip_uint8_t)((i >> 16) & 0xff);
data[3] = (zip_uint8_t)((i >> 24) & 0xff);
data[4] = (zip_uint8_t)((i >> 32) & 0xff);
data[5] = (zip_uint8_t)((i >> 40) & 0xff);
data[6] = (zip_uint8_t)((i >> 48) & 0xff);
data[7] = (zip_uint8_t)((i >> 56) & 0xff);
return 0;
}
int
_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;
}
data[0] = i;
return 0;
}
int
_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
if (offset > buffer->size) {
buffer->ok = false;
return -1;
}
buffer->ok = true;
buffer->offset = offset;
return 0;
}
int
_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;
}
return _zip_buffer_set_offset(buffer, offset);
}
zip_uint64_t
_zip_buffer_size(zip_buffer_t *buffer) {
return buffer->size;
}
+745
View File
@@ -0,0 +1,745 @@
/*
fs_zip_close.c -- close zip archive and update changes
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 <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 <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t);
static int copy_data(zip_t *, zip_uint64_t);
static int copy_source(zip_t *, zip_source_t *, zip_int64_t);
static int torrentzip_compare_names(const void *a, const void *b);
static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t);
static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64);
ZIP_EXTERN int
fs_zip_close(zip_t *za) {
zip_uint64_t i, j, survivors, unchanged_offset;
zip_int64_t off;
int error;
zip_filelist_t *filelist;
int changed;
if (za == NULL)
return -1;
changed = _zip_changed(za, &survivors);
if (survivors == 0 && !(za->ch_flags & ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE)) {
/* don't create zip files with no entries */
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
if (zip_source_remove(za->src) < 0) {
if (!((fs_zip_error_code_zip(fs_zip_source_error(za->src)) == ZIP_ER_REMOVE) && (fs_zip_error_code_system(fs_zip_source_error(za->src)) == ENOENT))) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
}
}
fs_zip_discard(za);
return 0;
}
/* Always write empty archive if we are told to keep it, otherwise it wouldn't be created if the file doesn't already exist. */
if (!changed && survivors > 0) {
fs_zip_discard(za);
return 0;
}
if (survivors > za->nentry) {
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;
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 (j >= survivors) {
free(filelist);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
filelist[j].idx = i;
filelist[j].name = fs_zip_get_name(za, i, 0);
j++;
}
if (j < survivors) {
free(filelist);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
qsort(filelist, (size_t)survivors, sizeof(filelist[0]), torrentzip_compare_names);
}
if (ZIP_WANT_TORRENTZIP(za) || (zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 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;
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 (fs_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 (fs_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);
fs_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;
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;
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)) || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za));
/* 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 (ZIP_WANT_TORRENTZIP(za)) {
zip_dirent_torrentzip_normalize(entry->changes);
}
if ((off = fs_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 = fs_zip_source_zip_file_create(za, i, ZIP_FL_UNCHANGED, 0, -1, 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 (fs_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;
}
free(filelist);
if (!error) {
if (fs_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) {
fs_zip_source_rollback_write(za->src);
return -1;
}
fs_zip_discard(za);
return 0;
}
static int
add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
zip_int64_t offstart, offdata, offend, data_length;
zip_stat_t st;
zip_file_attributes_t attributes;
zip_source_t *src_final, *src_tmp;
int ret;
int is_zip64;
zip_flags_t flags;
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
if (fs_zip_source_stat(src, &st) < 0) {
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;
}
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
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;
}
else {
/* 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;
}
flags = ZIP_EF_LOCAL;
if ((st.valid & ZIP_STAT_SIZE) == 0) {
/* TODO: not valid for torrentzip */
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;
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);
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);
}
}
if (max_compressed_size > 0xffffffffu) {
/* TODO: not valid for torrentzip */
flags |= ZIP_FL_FORCE_ZIP64;
}
}
else {
de->comp_size = st.comp_size;
data_length = (zip_int64_t)st.comp_size;
}
}
if ((offstart = fs_zip_source_tell_write(za->src)) < 0) {
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;
}
needs_recompress = ZIP_WANT_TORRENTZIP(za) || 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);
needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method);
needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE);
needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE);
src_final = src;
fs_zip_source_keep(src_final);
if (!needs_decrypt && st.encryption_method == ZIP_EM_TRAD_PKWARE && (de->changed & ZIP_DIRENT_LAST_MOD)) {
/* PKWare encryption uses the last modification time for password verification, therefore we can't change it without re-encrypting. Ignoring the requested modification time change seems more sensible than failing to close the archive. */
de->changed &= ~ZIP_DIRENT_LAST_MOD;
}
if (needs_decrypt) {
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;
}
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;
}
src_final = src_tmp;
}
if (needs_crc) {
if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
zip_source_free(src_final);
return -1;
}
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;
}
src_final = src_tmp;
}
if (needs_encrypt) {
zip_encryption_implementation impl;
const char *password = NULL;
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 (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;
fs_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, 0, NULL, NULL, 0, true, &za->error)) == NULL) {
zip_source_free(src_final);
return -1;
}
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;
}
src_final = src_tmp;
}
if ((offdata = fs_zip_source_tell_write(za->src)) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
ret = copy_source(za, src_final, data_length);
if (fs_zip_source_stat(src_final, &st) < 0) {
zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
if (fs_zip_source_get_file_attributes(src_final, &attributes) != 0) {
zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
zip_source_free(src_final);
if (ret < 0) {
return -1;
}
if ((offend = fs_zip_source_tell_write(za->src)) < 0) {
zip_error_set_from_source(&za->error, za->src);
return -1;
}
if (fs_zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
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;
}
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
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;
de->uncomp_size = st.size;
de->comp_size = (zip_uint64_t)(offend - offdata);
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
if (ZIP_WANT_TORRENTZIP(za)) {
zip_dirent_torrentzip_normalize(de);
}
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
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;
}
if (fs_zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
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;
}
}
return 0;
}
static int
copy_data(zip_t *za, zip_uint64_t len) {
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
double total = (double)len;
if (!byte_array_init(buf, BUFSIZE)) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
while (len > 0) {
zip_uint64_t n = ZIP_MIN(len, BUFSIZE);
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;
}
len -= n;
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);
return 0;
}
static int
copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
zip_int64_t n, current;
int ret;
if (fs_zip_source_open(src) < 0) {
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;
}
ret = 0;
current = 0;
while ((n = fs_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 (n < 0) {
zip_error_set_from_source(&za->error, src);
ret = -1;
}
byte_array_fini(buf);
fs_zip_source_close(src);
return ret;
}
static int
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
if (fs_zip_source_tell_write(za->src) < 0) {
return -1;
}
if (_zip_cdir_write(za, filelist, survivors) < 0) {
return -1;
}
if (fs_zip_source_tell_write(za->src) < 0) {
return -1;
}
return 0;
}
int
_zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
int changed;
zip_uint64_t i, survivors;
changed = 0;
survivors = 0;
if (za->comment_changed || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za))) {
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 (survivorsp) {
*survivorsp = survivors;
}
return changed;
}
static int
write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH);
int ret = 0;
if (buffer == NULL) {
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);
}
else {
_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;
}
else {
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
}
_zip_buffer_free(buffer);
return ret;
}
static int torrentzip_compare_names(const void *a, const void *b) {
const char *aname = ((const zip_filelist_t *)a)->name;
const char *bname = ((const zip_filelist_t *)b)->name;
if (aname == NULL) {
return (bname != NULL) * -1;
}
else if (bname == NULL) {
return 1;
}
return strcasecmp(aname, bname);
}
+54
View 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 */
+53
View 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 */
+68
View 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 */
+56
View 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 */
+73
View File
@@ -0,0 +1,73 @@
/*
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>
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
#define USE_OPENSSL_1_0_API
#elif OPENSSL_VERSION_NUMBER < 0x3000000fL
#define USE_OPENSSL_1_1_API
#else
#define USE_OPENSSL_3_API
#endif
#define _zip_crypto_aes_t EVP_CIPHER_CTX
#ifdef USE_OPENSSL_3_API
struct _zip_crypto_hmac_t {
EVP_MAC *mac;
EVP_MAC_CTX *ctx;
};
typedef struct _zip_crypto_hmac_t _zip_crypto_hmac_t;
#define _zip_crypto_hmac(hmac, data, length) (EVP_MAC_update((hmac->ctx), (data), (length)) == 1)
#else
#define _zip_crypto_hmac_t HMAC_CTX
#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1)
#endif
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);
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 */
+53
View 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 */
+68
View File
@@ -0,0 +1,68 @@
/*
fs_zip_delete.c -- delete file from zip archive
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 <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 int
fs_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;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
return -1;
}
if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
return -1;
}
/* allow duplicate file names, because the file will
* be removed directly afterwards */
if (_zip_unchange(za, idx, 1) != 0)
return -1;
za->entry[idx].deleted = 1;
return 0;
}
+92
View File
@@ -0,0 +1,92 @@
/*
fs_zip_dir_add.c -- add directory
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 <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 <string.h>
#include "zipint.h"
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
ZIP_EXTERN zip_int64_t
fs_zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
size_t len;
zip_int64_t idx;
char *s;
zip_source_t *source;
if (ZIP_IS_RDONLY(za)) {
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;
}
s = NULL;
len = strlen(name);
if (name[len - 1] != '/') {
if (len > SIZE_MAX - 2 || (s = (char *)malloc(len + 2)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
(void)strncpy_s(s, len + 2, name, len);
s[len] = '/';
s[len + 1] = '\0';
}
if ((source = fs_zip_source_buffer(za, NULL, 0, 0)) == NULL) {
free(s);
return -1;
}
idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
free(s);
if (idx < 0)
zip_source_free(source);
else {
if (fs_zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
fs_zip_delete(za, (zip_uint64_t)idx);
return -1;
}
}
return idx;
}
File diff suppressed because it is too large Load Diff
+80
View File
@@ -0,0 +1,80 @@
/*
fs_zip_discard.c -- discard and free struct zip
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 <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"
/* fs_zip_discard:
frees the space allocated to a zipfile struct, and closes the
corresponding file. */
void
fs_zip_discard(zip_t *za) {
zip_uint64_t i;
if (za == NULL)
return;
if (za->src) {
fs_zip_source_close(za->src);
zip_source_free(za->src);
}
free(za->default_password);
_zip_string_free(za->comment_orig);
_zip_string_free(za->comment_changes);
_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->nopen_source; i++) {
_zip_source_invalidate(za->open_source[i]);
}
free(za->open_source);
_zip_progress_free(za->progress);
fs_zip_error_fini(&za->error);
free(za);
return;
}
+51
View File
@@ -0,0 +1,51 @@
/*
zip_entry.c -- struct zip_entry helper functions
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 <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"
void
_zip_entry_finalize(zip_entry_t *e) {
_zip_unchange_data(e);
_zip_dirent_free(e->orig);
_zip_dirent_free(e->changes);
}
void
_zip_entry_init(zip_entry_t *e) {
e->orig = NULL;
e->changes = NULL;
e->source = NULL;
e->deleted = 0;
}
+79
View File
@@ -0,0 +1,79 @@
/*
This file was generated automatically by CMake
from zip.h and zipint.h; make changes there.
*/
#include "zipint.h"
#define L ZIP_ET_LIBZIP
#define N ZIP_ET_NONE
#define S ZIP_ET_SYS
#define Z ZIP_ET_ZLIB
#define E ZIP_DETAIL_ET_ENTRY
#define G ZIP_DETAIL_ET_GLOBAL
const struct _zip_err_info _zip_err_str[] = {
{ N, "No error" },
{ N, "Multi-disk zip archives not supported" },
{ S, "Renaming temporary file failed" },
{ S, "Closing zip archive failed" },
{ S, "Seek error" },
{ S, "Read error" },
{ S, "Write error" },
{ N, "CRC error" },
{ N, "Containing zip archive was closed" },
{ N, "No such file" },
{ N, "File already exists" },
{ S, "Can't open file" },
{ S, "Failure to create temporary file" },
{ Z, "Zlib error" },
{ N, "Malloc failure" },
{ N, "Entry has been changed" },
{ N, "Compression method not supported" },
{ N, "Premature end of file" },
{ N, "Invalid argument" },
{ N, "Not a zip archive" },
{ N, "Internal error" },
{ L, "Zip archive inconsistent" },
{ S, "Can't remove file" },
{ N, "Entry has been deleted" },
{ N, "Encryption method not supported" },
{ N, "Read-only archive" },
{ N, "No password provided" },
{ N, "Wrong password provided" },
{ N, "Operation not supported" },
{ N, "Resource still in use" },
{ S, "Tell error" },
{ N, "Compressed data invalid" },
{ N, "Operation cancelled" },
{ N, "Unexpected length of data" },
{ N, "Not allowed in torrentzip" },
};
const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]);
const struct _zip_err_info _zip_err_details[] = {
{ G, "no detail" },
{ G, "central directory overlaps EOCD, or there is space between them" },
{ G, "archive comment length incorrect" },
{ G, "central directory length invalid" },
{ E, "central header invalid" },
{ G, "central directory count of entries is incorrect" },
{ E, "local and central headers do not match" },
{ G, "wrong EOCD length" },
{ G, "EOCD64 overlaps EOCD, or there is space between them" },
{ G, "EOCD64 magic incorrect" },
{ G, "EOCD64 and EOCD do not match" },
{ G, "invalid value in central directory" },
{ E, "variable size fields overflow header" },
{ E, "invalid UTF-8 in filename" },
{ E, "invalid UTF-8 in comment" },
{ E, "invalid Zip64 extra field" },
{ E, "invalid WinZip AES extra field" },
{ E, "garbage at end of extra fields" },
{ E, "extra field length is invalid" },
{ E, "file length in header doesn't match actual file length" },
};
const int _zip_err_details_count = sizeof(_zip_err_details)/sizeof(_zip_err_details[0]);
+156
View File
@@ -0,0 +1,156 @@
/*
zip_error.c -- zip_error_t helper functions
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 <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"
ZIP_EXTERN int
fs_zip_error_code_system(const zip_error_t *error) {
return error->sys_err;
}
ZIP_EXTERN int
fs_zip_error_code_zip(const zip_error_t *error) {
return error->zip_err;
}
ZIP_EXTERN void
fs_zip_error_fini(zip_error_t *err) {
free(err->str);
err->str = NULL;
}
ZIP_EXTERN void
fs_zip_error_init(zip_error_t *err) {
err->zip_err = ZIP_ER_OK;
err->sys_err = 0;
err->str = NULL;
}
ZIP_EXTERN void
fs_zip_error_init_with_code(zip_error_t *error, int ze) {
fs_zip_error_init(error);
error->zip_err = ze;
switch (zip_error_system_type(error)) {
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_err_str_count)
return ZIP_ET_NONE;
return _zip_err_str[error->zip_err].type;
}
void
_zip_error_clear(zip_error_t *err) {
if (err == NULL)
return;
err->zip_err = ZIP_ER_OK;
err->sys_err = 0;
}
void
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
if (dst == NULL) {
return;
}
dst->zip_err = src->zip_err;
dst->sys_err = src->sys_err;
}
void
_zip_error_get(const zip_error_t *err, int *zep, int *sep) {
if (zep)
*zep = err->zip_err;
if (sep) {
if (zip_error_system_type(err) != ZIP_ET_NONE)
*sep = err->sys_err;
else
*sep = 0;
}
}
void
zip_error_set(zip_error_t *err, int ze, int se) {
if (err) {
err->zip_err = ze;
err->sys_err = se;
}
}
void
zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
if (src == NULL) {
zip_error_set(err, ZIP_ER_INVAL, 0);
return;
}
_zip_error_copy(err, fs_zip_source_error(src));
}
zip_int64_t
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;
}
e[0] = fs_zip_error_code_zip(error);
e[1] = fs_zip_error_code_system(error);
return sizeof(int) * 2;
}
+44
View File
@@ -0,0 +1,44 @@
/*
fs_zip_error_clear.c -- clear zip error
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 <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 void
fs_zip_error_clear(zip_t *za) {
if (za == NULL)
return;
_zip_error_clear(&za->error);
}
+54
View File
@@ -0,0 +1,54 @@
/*
zip_error_get.c -- get zip error
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN void
zip_error_get(zip_t *za, int *zep, int *sep) {
_zip_error_get(&za->error, zep, sep);
}
ZIP_EXTERN zip_error_t *
fs_zip_get_error(zip_t *za) {
return &za->error;
}
ZIP_EXTERN zip_error_t *
fs_zip_file_get_error(zip_file_t *f) {
return &f->error;
}
+45
View File
@@ -0,0 +1,45 @@
/*
zip_error_get_sys_type.c -- return type of system error code
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN int
zip_error_get_sys_type(int ze) {
if (ze < 0 || ze >= _zip_err_str_count) {
return 0;
}
return _zip_err_str[ze].type;
}
+128
View File
@@ -0,0 +1,128 @@
/*
zip_error_sterror.c -- get string representation of struct zip_error
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 <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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib-ng.h>
#include "zipint.h"
ZIP_EXTERN const char *
zip_error_strerror(zip_error_t *err) {
const char *zip_error_string, *system_error_string;
char *s;
char *system_error_buffer = NULL;
fs_zip_error_fini(err);
if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) {
system_error_buffer = (char *)malloc(128);
snprintf_s(system_error_buffer, 128, "Unknown error %d", err->zip_err);
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
zip_error_string = NULL;
system_error_string = system_error_buffer;
}
else {
zip_error_string = _zip_err_str[err->zip_err].description;
switch (_zip_err_str[err->zip_err].type) {
case ZIP_ET_SYS: {
size_t len = strerrorlen_s(err->sys_err) + 1;
system_error_buffer = malloc(len);
strerror_s(system_error_buffer, len, err->sys_err);
system_error_string = system_error_buffer;
break;
}
case ZIP_ET_ZLIB:
system_error_string = zng_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) {
system_error_buffer = (char *)malloc(128);
snprintf_s(system_error_buffer, 128, "invalid detail error %u", error);
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
system_error_string = system_error_buffer;
}
else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) {
system_error_buffer = (char *)malloc(128);
snprintf_s(system_error_buffer, 128, "entry %d: %s", index, _zip_err_details[error].description);
system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */
system_error_string = system_error_buffer;
}
else {
system_error_string = _zip_err_details[error].description;
}
break;
}
default:
system_error_string = NULL;
}
}
if (system_error_string == NULL) {
free(system_error_buffer);
return zip_error_string;
}
else {
size_t length = strlen(system_error_string);
if (zip_error_string) {
size_t length_error = strlen(zip_error_string);
if (length + length_error + 2 < length) {
free(system_error_buffer);
return _zip_err_str[ZIP_ER_MEMORY].description;
}
length += length_error + 2;
}
if (length == SIZE_MAX || (s = (char *)malloc(length + 1)) == NULL) {
free(system_error_buffer);
return _zip_err_str[ZIP_ER_MEMORY].description;
}
snprintf_s(s, length + 1, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
err->str = s;
free(system_error_buffer);
return s;
}
}
+58
View File
@@ -0,0 +1,58 @@
/*
zip_error_to_str.c -- get string representation of zip error code
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 <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 <stdio.h>
#include <string.h>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN int
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
zip_error_t error;
const char *error_string;
int ret;
fs_zip_error_init(&error);
zip_error_set(&error, ze, se);
error_string = zip_error_strerror(&error);
ret = snprintf_s(buf, ZIP_MIN(len, SIZE_MAX), error_string, strlen(error_string));
fs_zip_error_fini(&error);
return ret;
}
+427
View File
@@ -0,0 +1,427 @@
/*
zip_extra_field.c -- manipulate extra fields
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 <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 <string.h>
#include "zipint.h"
zip_extra_field_t *
_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
zip_extra_field_t *head, *prev, *def;
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 (head == NULL)
head = def;
if (prev)
prev->next = def;
prev = def;
ef = ef->next;
}
return head;
}
zip_extra_field_t *
_zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) {
zip_extra_field_t *head, *prev;
int i;
i = 0;
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 (id_idx == ZIP_EXTRA_FIELD_ALL)
continue;
}
}
i++;
if (i > id_idx)
break;
}
prev = ef;
}
return head;
}
void
_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;
}
}
const zip_uint8_t *
_zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) {
static const zip_uint8_t empty[1] = {'\0'};
int i;
i = 0;
for (; ef; ef = ef->next) {
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;
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
return NULL;
}
zip_extra_field_t *
_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
zip_extra_field_t *ef2, *tt, *tail;
int duplicate;
if (to == NULL)
return from;
for (tail = to; tail->next; tail = tail->next)
;
for (; from; from = ef2) {
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;
}
}
from->next = NULL;
if (duplicate)
_zip_ef_free(from);
else
tail = tail->next = from;
}
return to;
}
zip_extra_field_t *
_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) {
zip_extra_field_t *ef;
if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == 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;
}
}
else
ef->data = NULL;
return ef;
}
bool
_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) {
zip_buffer_t *buffer;
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;
}
ef_head = ef = NULL;
while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
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);
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 (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 */
/* buffer is at most 64k long, so this can't overflow. */
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", (size_t)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;
}
else {
_zip_ef_free(ef_head);
}
return true;
}
zip_extra_field_t *
_zip_ef_remove_internal(zip_extra_field_t *ef) {
zip_extra_field_t *ef_head;
zip_extra_field_t *prev, *next;
ef_head = 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;
}
}
return ef_head;
}
zip_uint16_t
_zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
zip_uint16_t size;
size = 0;
for (; ef; ef = ef->next) {
if (ef->flags & flags & ZIP_EF_BOTH)
size = (zip_uint16_t)(size + 4 + ef->size);
}
return size;
}
int
_zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
zip_uint8_t b[4];
zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
if (buffer == NULL) {
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;
}
}
}
}
_zip_buffer_free(buffer);
return 0;
}
int
_zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
zip_entry_t *e;
unsigned char b[4];
zip_buffer_t *buffer;
zip_uint16_t fname_len, ef_len;
if (idx >= za->nentry) {
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;
if (e->orig->offset + 26 > ZIP_INT64_MAX) {
zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
return -1;
}
if (fs_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;
}
if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
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);
if (ef_len > 0) {
zip_extra_field_t *ef;
zip_uint8_t *ef_raw;
if (fs_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);
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 (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;
}
return 0;
}
+367
View File
@@ -0,0 +1,367 @@
/*
zip_extra_field_api.c -- public extra fields API functions
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 <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 int
fs_zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) {
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
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;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
de = za->entry[idx].changes;
de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags);
return 0;
}
ZIP_EXTERN int
fs_zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) {
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
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;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
de = za->entry[idx].changes;
de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags);
return 0;
}
ZIP_EXTERN const zip_uint8_t *
fs_zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) {
static const zip_uint8_t empty[1] = {'\0'};
zip_dirent_t *de;
zip_extra_field_t *ef;
int i;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return NULL;
if (flags & ZIP_FL_LOCAL)
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 (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);
return NULL;
}
ZIP_EXTERN const zip_uint8_t *
fs_zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) {
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return NULL;
if (flags & ZIP_FL_LOCAL)
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);
}
ZIP_EXTERN zip_int16_t
fs_zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
zip_dirent_t *de;
zip_extra_field_t *ef;
zip_uint16_t n;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return -1;
if (flags & ZIP_FL_LOCAL)
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++;
return (zip_int16_t)n;
}
ZIP_EXTERN zip_int16_t
fs_zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) {
zip_dirent_t *de;
zip_extra_field_t *ef;
zip_uint16_t n;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return -1;
if (flags & ZIP_FL_LOCAL)
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++;
return (zip_int16_t)n;
}
ZIP_EXTERN int
fs_zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) {
zip_dirent_t *de;
zip_uint16_t ls, cs;
zip_extra_field_t *ef, *ef_prev, *ef_new;
int i, found, new_len;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (ZIP_EF_IS_INTERNAL(ef_id)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
de = za->entry[idx].changes;
ef = de->extra_fields;
ef_prev = NULL;
i = 0;
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 (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
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);
else
ls = 0;
if (flags & ZIP_EF_CENTRAL)
cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
else
cs = 0;
new_len = ls > cs ? ls : cs;
if (found)
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;
}
if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) {
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;
}
}
else if (ef_prev) {
ef_new->next = ef_prev->next;
ef_prev->next = ef_new;
}
else
de->extra_fields = ef_new;
return 0;
}
int
_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;
}
e = za->entry + idx;
if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
return 0;
if (e->orig) {
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->orig && e->orig->extra_fields) {
if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
return -1;
}
e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
return 0;
}
+54
View File
@@ -0,0 +1,54 @@
/*
fs_zip_fclose.c -- close file in zip archive
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 <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"
ZIP_EXTERN int
fs_zip_fclose(zip_file_t *zf) {
int ret;
if (zf->src)
zip_source_free(zf->src);
ret = 0;
if (zf->error.zip_err)
ret = zf->error.zip_err;
fs_zip_error_fini(&zf->error);
free(zf);
return ret;
}
+91
View File
@@ -0,0 +1,91 @@
/*
fs_zip_fdopen.c -- open read-only archive from file descriptor
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 <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_UNISTD_H
#include <unistd.h>
#endif
ZIP_EXTERN zip_t *
fs_zip_fdopen(int fd_orig, int _flags, int *zep) {
int fd;
FILE *fp;
zip_t *za;
zip_source_t *src;
struct zip_error error;
if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
return NULL;
}
#ifndef ENABLE_FDOPEN
_zip_set_open_error(zep, NULL, ZIP_ER_OPNOTSUPP);
return NULL;
#else
/* 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;
}
if ((fp = fdopen(fd, "rb")) == NULL) {
close(fd);
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
return NULL;
}
fs_zip_error_init(&error);
if ((src = fs_zip_source_filep_create(fp, 0, -1, &error)) == NULL) {
fclose(fp);
_zip_set_open_error(zep, &error, 0);
fs_zip_error_fini(&error);
return NULL;
}
if ((za = fs_zip_open_from_source(src, _flags, &error)) == NULL) {
zip_source_free(src);
_zip_set_open_error(zep, &error, 0);
fs_zip_error_fini(&error);
return NULL;
}
fs_zip_error_fini(&error);
close(fd_orig);
return za;
#endif
}
+52
View File
@@ -0,0 +1,52 @@
/*
fs_zip_file_add.c -- add file via callback function
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 <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"
/*
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.
*/
ZIP_EXTERN zip_int64_t
fs_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;
}
return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);
}
+44
View File
@@ -0,0 +1,44 @@
/*
fs_zip_file_error_clear.c -- clear zip file error
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 <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 void
fs_zip_file_error_clear(zip_file_t *zf) {
if (zf == NULL)
return;
_zip_error_clear(&zf->error);
}
+41
View File
@@ -0,0 +1,41 @@
/*
zip_file_error_get.c -- get zip file error
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN void
zip_file_error_get(zip_file_t *zf, int *zep, int *sep) {
_zip_error_get(&zf->error, zep, sep);
}
+55
View File
@@ -0,0 +1,55 @@
/*
fs_zip_file_get_comment.c -- get file comment
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 <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"
/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */
ZIP_EXTERN const char *
fs_zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) {
zip_dirent_t *de;
zip_uint32_t len;
const zip_uint8_t *str;
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
return NULL;
if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
return NULL;
if (lenp)
*lenp = len;
return (const char *)str;
}
@@ -0,0 +1,50 @@
/*
fs_zip_file_get_external_attributes.c -- get opsys/external attributes
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 <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"
int
fs_zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes) {
zip_dirent_t *de;
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
return -1;
if (opsys)
*opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
if (attributes)
*attributes = de->ext_attrib;
return 0;
}
+117
View File
@@ -0,0 +1,117 @@
/*
zip_file_get_offset.c -- get offset of file data in archive.
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 <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 <stdio.h>
#include <string.h>
#include "zipint.h"
/* _zip_file_get_offset(za, ze):
Returns the offset of the file data for entry ze.
On error, fills in za->error and returns 0.
*/
zip_uint64_t
_zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
zip_uint64_t offset;
zip_int32_t size;
if (za->entry[idx].orig == NULL) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return 0;
}
offset = za->entry[idx].orig->offset;
if (fs_zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 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;
if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
}
return offset + (zip_uint32_t)size;
}
zip_uint64_t
_zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
zip_uint64_t offset;
zip_dirent_t *entry;
if ((offset = _zip_file_get_offset(za, index, error)) == 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;
}
offset += entry->comp_size;
if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
zip_uint8_t buf[4];
if (fs_zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
zip_error_set_from_source(error, za->src);
return 0;
}
if (fs_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;
}
+67
View File
@@ -0,0 +1,67 @@
/*
fs_zip_file_rename.c -- rename file in zip archive
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 <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 <string.h>
#include "zipint.h"
ZIP_EXTERN int
fs_zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) {
const char *old_name;
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;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if ((old_name = fs_zip_get_name(za, idx, 0)) == NULL)
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;
}
return _zip_set_name(za, idx, name, flags);
}
+105
View File
@@ -0,0 +1,105 @@
/*
fs_zip_file_replace.c -- replace file via callback function
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 <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 int
fs_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;
}
if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
return -1;
return 0;
}
/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */
zip_int64_t
_zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *source, zip_flags_t flags) {
zip_uint64_t za_nentry_prev;
if (ZIP_IS_RDONLY(za)) {
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;
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 (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;
}
/* does not change any name related data, so we can do it here;
* needed for a double add of the same file name */
_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;
}
}
za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
}
za->entry[idx].source = source;
return (zip_int64_t)idx;
}
+105
View File
@@ -0,0 +1,105 @@
/*
fs_zip_file_set_comment.c -- set comment for file in archive
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 <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"
ZIP_EXTERN int
fs_zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint16_t len, zip_flags_t flags) {
zip_entry_t *e;
zip_string_t *cstr;
int changed;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (len > 0 && comment == NULL) {
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;
}
else
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;
}
if (e->orig && e->orig->comment)
changed = !_zip_string_equal(e->orig->comment, cstr);
else
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;
}
else {
_zip_string_free(cstr);
if (e->changes && e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
}
return 0;
}
+120
View File
@@ -0,0 +1,120 @@
/*
fs_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
fs_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 (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 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;
}
@@ -0,0 +1,86 @@
/*
fs_zip_file_set_external_attributes.c -- set external attributes for entry
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 <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 int
fs_zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes) {
zip_entry_t *e;
int changed;
zip_uint8_t unchanged_opsys;
zip_uint32_t unchanged_attributes;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
e = za->entry + idx;
unchanged_opsys = (e->orig ? (zip_uint8_t)(e->orig->version_madeby >> 8) : (zip_uint8_t)ZIP_OPSYS_DEFAULT);
unchanged_attributes = e->orig ? e->orig->ext_attrib : ZIP_EXT_ATTRIB_DEFAULT;
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;
}
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;
}
}
return 0;
}
+77
View File
@@ -0,0 +1,77 @@
/*
fs_zip_file_set_mtime.c -- set modification time of entry.
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 <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 int
fs_zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) {
time_t mtime;
mtime = _zip_d2u_time(dtime, ddate);
return fs_zip_file_set_mtime(za, idx, mtime, flags);
}
ZIP_EXTERN int
fs_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;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 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;
}
}
e->changes->last_mod = mtime;
e->changes->changed |= ZIP_DIRENT_LAST_MOD;
return 0;
}
+41
View File
@@ -0,0 +1,41 @@
/*
zip_file_sterror.c -- get string representation of zip file error
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 <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 *
fs_zip_file_strerror(zip_file_t *zf) {
return zip_error_strerror(&zf->error);
}
+46
View File
@@ -0,0 +1,46 @@
/*
fs_zip_fopen.c -- open file in zip archive for reading
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 <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_file_t *
fs_zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) {
zip_int64_t idx;
if ((idx = fs_zip_name_locate(za, fname, flags)) < 0)
return NULL;
return fs_zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
}
+46
View File
@@ -0,0 +1,46 @@
/*
fs_zip_fopen_encrypted.c -- open file for reading with password
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 <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_file_t *
fs_zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password) {
zip_int64_t idx;
if ((idx = fs_zip_name_locate(za, fname, flags)) < 0)
return NULL;
return fs_zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
}
+41
View File
@@ -0,0 +1,41 @@
/*
fs_zip_fopen_index.c -- open file in zip archive for reading by index
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 <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_file_t *
fs_zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags) {
return fs_zip_fopen_index_encrypted(za, index, flags, za->default_password);
}
+85
View File
@@ -0,0 +1,85 @@
/*
fs_zip_fopen_index_encrypted.c -- open file for reading by index w/ password
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 <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 <stdio.h>
#include <stdlib.h>
#include "zipint.h"
static zip_file_t *_zip_file_new(zip_t *za);
ZIP_EXTERN zip_file_t *
fs_zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, const char *password) {
zip_file_t *zf;
zip_source_t *src;
if (password != NULL && password[0] == '\0') {
password = NULL;
}
if ((src = fs_zip_source_zip_file_create(za, index, flags, 0, -1, password, &za->error)) == NULL)
return NULL;
if (fs_zip_source_open(src) < 0) {
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;
}
zf->src = src;
return zf;
}
static zip_file_t *
_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;
}
fs_zip_error_init(&zf->error);
zf->src = NULL;
return zf;
}
+63
View File
@@ -0,0 +1,63 @@
/*
fs_zip_fread.c -- read from file
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 <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
fs_zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
zip_int64_t n;
if (!zf)
return -1;
if (zf->error.zip_err != 0)
return -1;
if (toread > ZIP_INT64_MAX) {
zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
return -1;
}
if (toread == 0) {
return 0;
}
if ((n = fs_zip_source_read(zf->src, outbuf, toread)) < 0) {
zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
return n;
}
+61
View File
@@ -0,0 +1,61 @@
/*
fs_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
fs_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 (fs_zip_source_seek(zf->src, offset, whence) < 0) {
zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
return 0;
}
ZIP_EXTERN int
fs_zip_file_is_seekable(zip_file_t *zfile) {
if (!zfile) {
return -1;
}
return fs_zip_source_is_seekable(zfile->src);
}
+54
View File
@@ -0,0 +1,54 @@
/*
fs_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
fs_zip_ftell(zip_file_t *zf) {
zip_int64_t res;
if (!zf)
return -1;
if (zf->error.zip_err != 0)
return -1;
res = fs_zip_source_tell(zf->src);
if (res < 0) {
zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
return res;
}
+58
View File
@@ -0,0 +1,58 @@
/*
fs_zip_get_archive_comment.c -- get archive comment
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 <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 <string.h>
#include "zipint.h"
ZIP_EXTERN const char *
fs_zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
zip_string_t *comment;
zip_uint32_t len;
const zip_uint8_t *str;
if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
comment = za->comment_orig;
else
comment = za->comment_changes;
if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
return NULL;
if (lenp)
*lenp = (int)len;
return (const char *)str;
}
+45
View File
@@ -0,0 +1,45 @@
/*
fs_zip_get_archive_flag.c -- get archive global flag
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 <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 int
fs_zip_get_archive_flag(zip_t *za, zip_flags_t flag, zip_flags_t flags) {
unsigned int fl;
fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags;
return (fl & flag) ? 1 : 0;
}
@@ -0,0 +1,62 @@
/*
zip_get_encryption_implementation.c -- get encryption implementation
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 <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_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;
#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;
#endif
default:
return NULL;
}
}
ZIP_EXTERN int
fs_zip_encryption_method_supported(zip_uint16_t method, int encode) {
if (method == ZIP_EM_NONE) {
return 1;
}
return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL;
}
+50
View File
@@ -0,0 +1,50 @@
/*
zip_get_file_comment.c -- get file comment
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN const char *
zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) {
zip_uint32_t len;
const char *s;
if ((s = fs_zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
if (lenp)
*lenp = (int)len;
}
return s;
}
+58
View File
@@ -0,0 +1,58 @@
/*
fs_zip_get_name.c -- get filename for a file in zip file
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 <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 <string.h>
#include "zipint.h"
ZIP_EXTERN const char *
fs_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
return _zip_get_name(za, idx, flags, &za->error);
}
const char *
_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) {
zip_dirent_t *de;
const zip_uint8_t *str;
if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
return NULL;
if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
return NULL;
return (const char *)str;
}
+52
View File
@@ -0,0 +1,52 @@
/*
fs_zip_get_num_entries.c -- get number of entries in archive
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 <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
fs_zip_get_num_entries(zip_t *za, zip_flags_t flags) {
zip_uint64_t n;
if (za == NULL)
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;
}
return (zip_int64_t)za->nentry;
}
+51
View File
@@ -0,0 +1,51 @@
/*
zip_get_num_files.c -- get number of files in archive
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
#include <limits.h>
ZIP_EXTERN int
zip_get_num_files(zip_t *za) {
if (za == NULL)
return -1;
if (za->nentry > INT_MAX) {
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
return (int)za->nentry;
}
+410
View File
@@ -0,0 +1,410 @@
/*
zip_hash.c -- hash table string -> uint64
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 <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>
/* parameter for the string hash function */
#define HASH_MULTIPLIER 33
#define HASH_START 5381
/* hash table's fill ratio is kept between these by doubling/halfing its size as necessary */
#define HASH_MAX_FILL .75
#define HASH_MIN_FILL .01
/* but hash table size is kept between these */
#define HASH_MIN_SIZE 256
#define HASH_MAX_SIZE 0x80000000ul
struct zip_hash_entry {
const zip_uint8_t *name;
zip_int64_t orig_index;
zip_int64_t current_index;
struct zip_hash_entry *next;
zip_uint32_t hash_value;
};
typedef struct zip_hash_entry zip_hash_entry_t;
struct zip_hash {
zip_uint32_t table_size;
zip_uint64_t nentries;
zip_hash_entry_t **table;
};
/* free list of entries */
static void
free_list(zip_hash_entry_t *entry) {
while (entry != NULL) {
zip_hash_entry_t *next = entry->next;
free(entry);
entry = next;
}
}
/* compute hash of string, full 32 bit value */
static zip_uint32_t
hash_string(const zip_uint8_t *name) {
zip_uint64_t value = HASH_START;
if (name == NULL) {
return 0;
}
while (*name != 0) {
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
name++;
}
return (zip_uint32_t)value;
}
/* resize hash table; new_size must be a power of 2, can be larger or smaller than current size */
static bool
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;
}
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;
}
if (hash->nentries > 0) {
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;
zip_uint32_t new_index = entry->hash_value % new_size;
entry->next = new_table[new_index];
new_table[new_index] = entry;
entry = next;
}
}
}
free(hash->table);
hash->table = new_table;
hash->table_size = new_size;
return true;
}
static zip_uint32_t
size_for_capacity(zip_uint64_t capacity) {
double needed_size = capacity / HASH_MAX_FILL;
zip_uint32_t v;
if (needed_size > ZIP_UINT32_MAX) {
v = ZIP_UINT32_MAX;
}
else {
v = (zip_uint32_t)needed_size;
}
if (v > HASH_MAX_SIZE) {
return HASH_MAX_SIZE;
}
/* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
(http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2). */
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
zip_hash_t *
_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;
}
hash->table_size = 0;
hash->nentries = 0;
hash->table = NULL;
return hash;
}
void
_zip_hash_free(zip_hash_t *hash) {
zip_uint32_t i;
if (hash == NULL) {
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);
}
free(hash);
}
/* insert into hash, return error on existence or memory issues */
bool
_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error) {
zip_uint32_t hash_value, table_index;
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
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;
}
}
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 == 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 (flags & ZIP_FL_UNCHANGED) {
entry->orig_index = (zip_int64_t)index;
}
entry->current_index = (zip_int64_t)index;
return true;
}
/* remove entry from hash, error if not found */
bool
_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) {
zip_uint32_t hash_value, index;
zip_hash_entry_t *entry, *previous;
if (hash == NULL || name == NULL) {
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;
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
return false;
}
/* find value for entry in hash, -1 if not found */
zip_int64_t
_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) {
zip_uint32_t hash_value, index;
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL) {
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;
}
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
return -1;
}
bool
_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error) {
zip_uint32_t new_size;
if (capacity == 0) {
return true;
}
new_size = size_for_capacity(capacity);
if (new_size <= hash->table_size) {
return true;
}
if (!hash_resize(hash, new_size, error)) {
return false;
}
return true;
}
bool
_zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
zip_uint32_t i;
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;
}
}
}
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;
}
}
return true;
}
+146
View File
@@ -0,0 +1,146 @@
/*
zip_io_util.c -- I/O helper functions
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 <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 <limits.h>
#include <stdlib.h>
#include <string.h>
#include <zlib-ng.h>
#include "zipint.h"
int
_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error) {
zip_int64_t n;
if (length > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((n = fs_zip_source_read(src, b, length)) < 0) {
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;
}
return 0;
}
zip_uint8_t *
_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error) {
zip_uint8_t *r;
if (length == 0 && !nulp) {
return NULL;
}
r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
if (!r) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if (buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, length);
if (data == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
free(r);
return NULL;
}
(void)memcpy_s(r, length, data, length);
}
else {
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 = ' ';
}
return r;
}
zip_string_t *
_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool nulp, zip_error_t *error) {
zip_uint8_t *raw;
zip_string_t *s;
if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
return NULL;
s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
free(raw);
return s;
}
int
_zip_write(zip_t *za, const void *data, zip_uint64_t length) {
zip_int64_t n;
if ((n = fs_zip_source_write(za->src, data, length)) < 0) {
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;
}
if (za->write_crc != NULL) {
zip_uint64_t position = 0;
while (position < length) {
zip_uint64_t nn = ZIP_MIN(UINT_MAX, length - position);
*za->write_crc = (zip_uint32_t)zng_crc32(*za->write_crc, (const Bytef *)data + position, (uInt)nn);
position += nn;
}
}
return 0;
}
+41
View File
@@ -0,0 +1,41 @@
/*
fs_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 *
fs_zip_libzip_version(void) {
return LIBZIP_VERSION;
}
+56
View File
@@ -0,0 +1,56 @@
/*
zip_memdup.c -- internal zip function, "strdup" with len
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 <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 <string.h>
#include "zipint.h"
void *
_zip_memdup(const void *mem, size_t len, zip_error_t *error) {
void *ret;
if (len == 0)
return NULL;
ret = malloc(len);
if (!ret) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
(void)memcpy_s(ret, len, mem, len);
return ret;
}
+116
View File
@@ -0,0 +1,116 @@
/*
fs_zip_name_locate.c -- get index by name
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 <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 <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "zipint.h"
ZIP_EXTERN zip_int64_t
fs_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) {
return _zip_name_locate(za, fname, flags, &za->error);
}
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 *);
size_t fname_length;
zip_string_t *str = NULL;
const char *fn, *p;
zip_uint64_t i;
if (za == NULL) {
return -1;
}
if (fname == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
fname_length = strlen(fname);
if (fname_length > ZIP_UINT16_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
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, (zip_uint16_t)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;
}
}
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;
for (i = 0; i < za->nentry; i++) {
fn = _zip_get_name(za, i, flags, error);
/* newly added (partially filled) entry or error */
if (fn == NULL)
continue;
if (flags & ZIP_FL_NODIR) {
p = strrchr(fn, '/');
if (p)
fn = p + 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 {
zip_int64_t ret = _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
_zip_string_free(str);
return ret;
}
}
+73
View File
@@ -0,0 +1,73 @@
/*
zip_new.c -- create and init struct zip
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 <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"
/* _zip_new:
creates a new zipfile struct, and sets the contents to zero; returns
the new struct. */
zip_t *
_zip_new(zip_error_t *error) {
zip_t *za;
za = (zip_t *)malloc(sizeof(struct zip));
if (!za) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if ((za->names = _zip_hash_new(error)) == NULL) {
free(za);
return NULL;
}
za->src = NULL;
za->open_flags = 0;
fs_zip_error_init(&za->error);
za->flags = za->ch_flags = 0;
za->default_password = NULL;
za->comment_orig = za->comment_changes = NULL;
za->comment_changed = 0;
za->nentry = za->nentry_alloc = 0;
za->entry = NULL;
za->nopen_source = za->nopen_source_alloc = 0;
za->open_source = NULL;
za->progress = NULL;
return za;
}
+967
View File
@@ -0,0 +1,967 @@
/*
fs_zip_open.c -- open zip archive by name
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 <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 <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zipint.h"
typedef enum { EXISTS_ERROR = -1, EXISTS_NOT = 0, EXISTS_OK } exists_t;
static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir);
static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len);
static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error);
static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *);
static const unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t);
static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error);
static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
//ZIP_EXTERN zip_t *
//fs_zip_open(const char *fn, int _flags, int *zep) {
// zip_t *za;
// zip_source_t *src;
// struct zip_error error;
//
// fs_zip_error_init(&error);
// if ((src = fs_zip_source_file_create(fn, 0, -1, &error)) == NULL) {
// _zip_set_open_error(zep, &error, 0);
// fs_zip_error_fini(&error);
// return NULL;
// }
//
// if ((za = fs_zip_open_from_source(src, _flags, &error)) == NULL) {
// zip_source_free(src);
// _zip_set_open_error(zep, &error, 0);
// fs_zip_error_fini(&error);
// return NULL;
// }
//
// fs_zip_error_fini(&error);
// return za;
//}
ZIP_EXTERN zip_t *
fs_zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) {
unsigned int flags;
zip_int64_t supported;
exists_t exists;
if (_flags < 0 || src == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
flags = (unsigned int)_flags;
supported = zip_source_supports(src);
if ((supported & ZIP_SOURCE_SUPPORTS_SEEKABLE) != ZIP_SOURCE_SUPPORTS_SEEKABLE) {
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
return NULL;
}
if ((supported & ZIP_SOURCE_SUPPORTS_WRITABLE) != ZIP_SOURCE_SUPPORTS_WRITABLE) {
flags |= ZIP_RDONLY;
}
if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) {
zip_error_set(error, ZIP_ER_RDONLY, 0);
return NULL;
}
exists = _zip_file_exists(src, error);
switch (exists) {
case EXISTS_ERROR:
return NULL;
case EXISTS_NOT:
if ((flags & ZIP_CREATE) == 0) {
zip_error_set(error, ZIP_ER_NOENT, 0);
return NULL;
}
return _zip_allocate_new(src, flags, error);
default: {
zip_t *za;
if (flags & ZIP_EXCL) {
zip_error_set(error, ZIP_ER_EXISTS, 0);
return NULL;
}
if (fs_zip_source_open(src) < 0) {
zip_error_set_from_source(error, src);
return NULL;
}
if (flags & ZIP_TRUNCATE) {
za = _zip_allocate_new(src, flags, error);
}
else {
/* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
za = _zip_open(src, flags, error);
}
if (za == NULL) {
fs_zip_source_close(src);
return NULL;
}
return za;
}
}
}
zip_t *
_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
zip_t *za;
zip_cdir_t *cdir;
struct fs_zip_stat st;
zip_uint64_t len, idx;
fs_zip_stat_init(&st);
if (fs_zip_source_stat(src, &st) < 0) {
zip_error_set_from_source(error, src);
return NULL;
}
if ((st.valid & ZIP_STAT_SIZE) == 0) {
zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
return NULL;
}
len = st.size;
if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
return NULL;
}
/* treat empty files as empty archives */
if (len == 0 && zip_source_accept_empty(src)) {
return za;
}
if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
_zip_error_copy(error, &za->error);
/* keep src so discard does not get rid of it */
fs_zip_source_keep(src);
fs_zip_discard(za);
return NULL;
}
za->entry = cdir->entry;
za->nentry = cdir->nentry;
za->nentry_alloc = cdir->nentry_alloc;
zip_check_torrentzip(za, cdir);
if (ZIP_IS_TORRENTZIP(za)) {
/* Torrentzip uses the archive comment to detect changes by tools that are not torrentzip aware. */
_zip_string_free(cdir->comment);
}
else {
za->comment_orig = cdir->comment;
}
free(cdir);
_zip_hash_reserve_capacity(za->names, za->nentry, &za->error);
for (idx = 0; idx < za->nentry; idx++) {
const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
if (name == NULL) {
/* keep src so discard does not get rid of it */
fs_zip_source_keep(src);
fs_zip_discard(za);
return NULL;
}
if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
_zip_error_copy(error, &za->error);
/* keep src so discard does not get rid of it */
fs_zip_source_keep(src);
fs_zip_discard(za);
return NULL;
}
}
}
za->ch_flags = za->flags;
return za;
}
void
_zip_set_open_error(int *zep, const zip_error_t *err, int ze) {
if (err) {
ze = fs_zip_error_code_zip(err);
switch (zip_error_system_type(err)) {
case ZIP_ET_SYS:
case ZIP_ET_LIBZIP:
errno = fs_zip_error_code_system(err);
break;
default:
break;
}
}
if (zep)
*zep = ze;
}
/* _zip_readcdir:
tries to find a valid end-of-central-directory at the beginning of
buf, and then the corresponding central directory entries.
Returns a struct zip_cdir which contains the central directory
entries, or NULL if unsuccessful. */
static zip_cdir_t *
_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error) {
zip_cdir_t *cd;
zip_uint16_t comment_len;
zip_uint64_t i, left;
zip_uint64_t eocd_offset = _zip_buffer_offset(buffer);
zip_buffer_t *cd_buffer;
if (_zip_buffer_left(buffer) < EOCDLEN) {
/* not enough bytes left for comment */
zip_error_set(error, ZIP_ER_NOZIP, 0);
return NULL;
}
/* check for end-of-central-dir magic */
if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) {
zip_error_set(error, ZIP_ER_NOZIP, 0);
return NULL;
}
if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
_zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
}
else {
_zip_buffer_set_offset(buffer, eocd_offset);
cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
}
if (cd == NULL)
return NULL;
_zip_buffer_set_offset(buffer, eocd_offset + 20);
comment_len = _zip_buffer_get_16(buffer);
if (cd->offset + cd->size > buf_offset + eocd_offset) {
/* cdir spans past EOCD record */
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
_zip_cdir_free(cd);
return NULL;
}
if (comment_len || (za->open_flags & ZIP_CHECKCONS)) {
zip_uint64_t tail_len;
_zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
tail_len = _zip_buffer_left(buffer);
if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID);
_zip_cdir_free(cd);
return NULL;
}
if (comment_len) {
if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
_zip_cdir_free(cd);
return NULL;
}
}
}
if (cd->offset >= buf_offset) {
zip_uint8_t *data;
/* if buffer already read in, use it */
_zip_buffer_set_offset(buffer, cd->offset - buf_offset);
if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
_zip_cdir_free(cd);
return NULL;
}
if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
_zip_cdir_free(cd);
return NULL;
}
}
else {
cd_buffer = NULL;
if (fs_zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
zip_error_set_from_source(error, za->src);
_zip_cdir_free(cd);
return NULL;
}
/* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */
if (fs_zip_source_tell(za->src) != (zip_int64_t)cd->offset) {
zip_error_set(error, ZIP_ER_NOZIP, 0);
_zip_cdir_free(cd);
return NULL;
}
}
left = (zip_uint64_t)cd->size;
i = 0;
while (left > 0) {
bool grown = false;
zip_int64_t entry_size;
if (i == cd->nentry) {
/* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */
/* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */
if (cd->is_zip64 || left < CDENTRYSIZE) {
break;
}
if (!_zip_cdir_grow(cd, 0x10000, error)) {
_zip_cdir_free(cd);
_zip_buffer_free(cd_buffer);
return NULL;
}
grown = true;
}
if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
if (fs_zip_error_code_zip(error) == ZIP_ER_INCONS) {
zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(fs_zip_error_code_system(error), i));
}
else if (grown && fs_zip_error_code_zip(error) == ZIP_ER_NOZIP) {
zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, i));
}
_zip_cdir_free(cd);
_zip_buffer_free(cd_buffer);
return NULL;
}
i++;
left -= (zip_uint64_t)entry_size;
}
if (i != cd->nentry || left > 0) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT);
_zip_buffer_free(cd_buffer);
_zip_cdir_free(cd);
return NULL;
}
if (za->open_flags & ZIP_CHECKCONS) {
bool ok;
if (cd_buffer) {
ok = _zip_buffer_eof(cd_buffer);
}
else {
zip_int64_t offset = fs_zip_source_tell(za->src);
if (offset < 0) {
zip_error_set_from_source(error, za->src);
_zip_cdir_free(cd);
return NULL;
}
ok = ((zip_uint64_t)offset == cd->offset + cd->size);
}
if (!ok) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
_zip_buffer_free(cd_buffer);
_zip_cdir_free(cd);
return NULL;
}
}
_zip_buffer_free(cd_buffer);
return cd;
}
/* _zip_checkcons:
Checks the consistency of the central directory by comparing central
directory entries with local headers and checking for plausible
file and header offsets. Returns -1 if not plausible, else the
difference between the lowest and the highest fileposition reached */
static zip_int64_t
_zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) {
zip_uint64_t i;
zip_uint64_t min, max, j;
struct zip_dirent temp;
_zip_dirent_init(&temp);
if (cd->nentry) {
max = cd->entry[0].orig->offset;
min = cd->entry[0].orig->offset;
}
else
min = max = 0;
for (i = 0; i < cd->nentry; i++) {
if (cd->entry[i].orig->offset < min)
min = cd->entry[i].orig->offset;
if (min > (zip_uint64_t)cd->offset) {
zip_error_set(error, ZIP_ER_NOZIP, 0);
return -1;
}
j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
if (j > max)
max = j;
if (max > (zip_uint64_t)cd->offset) {
zip_error_set(error, ZIP_ER_NOZIP, 0);
return -1;
}
if (fs_zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) {
zip_error_set_from_source(error, za->src);
return -1;
}
if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) {
if (fs_zip_error_code_zip(error) == ZIP_ER_INCONS) {
zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(fs_zip_error_code_system(error), i));
}
_zip_dirent_finalize(&temp);
return -1;
}
if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH, i));
_zip_dirent_finalize(&temp);
return -1;
}
cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
cd->entry[i].orig->local_extra_fields_read = 1;
temp.extra_fields = NULL;
_zip_dirent_finalize(&temp);
}
return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX;
}
/* _zip_headercomp:
compares a central directory entry and a local file header
Return 0 if they are consistent, -1 if not. */
static int
_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) {
if ((central->version_needed < local->version_needed)
#if 0
/* some zip-files have different values in local
and global headers for the bitflags */
|| (central->bitflags != local->bitflags)
#endif
|| (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename))
return -1;
if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) {
/* InfoZip stores valid values in local header even when data descriptor is used.
This is in violation of the appnote.
macOS Archive sets the compressed size even when data descriptor is used ( but not the others),
also in violation of the appnote.
*/
/* if data descriptor is not used, the values must match */
if ((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0) {
return -1;
}
/* when using a data descriptor, the local header value must be zero or match */
if ((local->crc != 0 && central->crc != local->crc) ||
(local->comp_size != 0 && central->comp_size != local->comp_size) ||
(local->uncomp_size != 0 && central->uncomp_size != local->uncomp_size)) {
return -1;
}
}
return 0;
}
static zip_t *
_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) {
zip_t *za;
if ((za = _zip_new(error)) == NULL) {
return NULL;
}
za->src = src;
za->open_flags = flags;
za->flags = 0;
za->ch_flags = 0;
za->write_crc = NULL;
if (flags & ZIP_RDONLY) {
za->flags |= ZIP_AFL_RDONLY;
za->ch_flags |= ZIP_AFL_RDONLY;
}
return za;
}
/*
* tests for file existence
*/
static exists_t
_zip_file_exists(zip_source_t *src, zip_error_t *error) {
struct fs_zip_stat st;
fs_zip_stat_init(&st);
if (fs_zip_source_stat(src, &st) != 0) {
zip_error_t *src_error = fs_zip_source_error(src);
if (fs_zip_error_code_zip(src_error) == ZIP_ER_READ && fs_zip_error_code_system(src_error) == ENOENT) {
return EXISTS_NOT;
}
_zip_error_copy(error, src_error);
return EXISTS_ERROR;
}
return EXISTS_OK;
}
static zip_cdir_t *
_zip_find_central_dir(zip_t *za, zip_uint64_t len) {
zip_cdir_t *cdir, *cdirnew;
const zip_uint8_t *match;
zip_int64_t buf_offset;
zip_uint64_t buflen;
zip_int64_t a;
zip_int64_t best;
zip_error_t error;
zip_buffer_t *buffer;
if (len < EOCDLEN) {
zip_error_set(&za->error, ZIP_ER_NOZIP, 0);
return NULL;
}
buflen = (len < CDBUFSIZE ? len : CDBUFSIZE);
if (fs_zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) {
zip_error_t *src_error = fs_zip_source_error(za->src);
if (fs_zip_error_code_zip(src_error) != ZIP_ER_SEEK || fs_zip_error_code_system(src_error) != EFBIG) {
/* seek before start of file on my machine */
_zip_error_copy(&za->error, src_error);
return NULL;
}
}
if ((buf_offset = fs_zip_source_tell(za->src)) < 0) {
zip_error_set_from_source(&za->error, za->src);
return NULL;
}
if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) {
return NULL;
}
best = -1;
cdir = NULL;
if (buflen >= CDBUFSIZE) {
/* EOCD64 locator is before EOCD, so leave place for it */
_zip_buffer_set_offset(buffer, EOCD64LOCLEN);
}
zip_error_set(&error, ZIP_ER_NOZIP, 0);
match = _zip_buffer_get(buffer, 0);
/* The size of buffer never greater than CDBUFSIZE. */
while (_zip_buffer_left(buffer) >= EOCDLEN && (match = _zip_memmem(match, (size_t)_zip_buffer_left(buffer) - (EOCDLEN - 4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) {
_zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) {
if (cdir) {
if (best <= 0) {
best = _zip_checkcons(za, cdir, &error);
}
a = _zip_checkcons(za, cdirnew, &error);
if (best < a) {
_zip_cdir_free(cdir);
cdir = cdirnew;
best = a;
}
else {
_zip_cdir_free(cdirnew);
}
}
else {
cdir = cdirnew;
if (za->open_flags & ZIP_CHECKCONS)
best = _zip_checkcons(za, cdir, &error);
else {
best = 0;
}
}
cdirnew = NULL;
}
match++;
_zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
}
_zip_buffer_free(buffer);
if (best < 0) {
_zip_error_copy(&za->error, &error);
_zip_cdir_free(cdir);
return NULL;
}
return cdir;
}
static const unsigned char *_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) {
const unsigned char *p;
if (littlelen == 0) {
return big;
}
if (biglen < littlelen) {
return NULL;
}
p = big;
while (true) {
p = (const unsigned char *)memchr(p, little[0], biglen - (littlelen - 1) - (size_t)(p - big));
if (p == NULL) {
return NULL;
}
if (memcmp(p + 1, little + 1, littlelen - 1) == 0) {
return p;
}
p += 1;
}
}
static zip_cdir_t *
_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
zip_cdir_t *cd;
zip_uint64_t i, nentry, size, offset, eocd_offset;
if (_zip_buffer_left(buffer) < EOCDLEN) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID);
return NULL;
}
eocd_offset = _zip_buffer_offset(buffer);
_zip_buffer_get(buffer, 4); /* magic already verified */
if (_zip_buffer_get_32(buffer) != 0) {
zip_error_set(error, ZIP_ER_MULTIDISK, 0);
return NULL;
}
/* number of cdir-entries on this disk */
i = _zip_buffer_get_16(buffer);
/* number of cdir-entries */
nentry = _zip_buffer_get_16(buffer);
if (nentry != i) {
zip_error_set(error, ZIP_ER_NOZIP, 0);
return NULL;
}
size = _zip_buffer_get_32(buffer);
offset = _zip_buffer_get_32(buffer);
if (offset + size < offset) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
}
if (offset + size > buf_offset + eocd_offset) {
/* cdir spans past EOCD record */
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
return NULL;
}
if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID);
return NULL;
}
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
return NULL;
cd->is_zip64 = false;
cd->size = size;
cd->offset = offset;
return cd;
}
static zip_cdir_t *
_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
zip_cdir_t *cd;
zip_uint64_t offset;
zip_uint8_t eocd[EOCD64LEN];
zip_uint64_t eocd_offset;
zip_uint64_t size, nentry, i, eocdloc_offset;
bool free_buffer;
zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
eocdloc_offset = _zip_buffer_offset(buffer);
_zip_buffer_get(buffer, 4); /* magic already verified */
num_disks = _zip_buffer_get_16(buffer);
eocd_disk = _zip_buffer_get_16(buffer);
eocd_offset = _zip_buffer_get_64(buffer);
/* valid seek value for start of EOCD */
if (eocd_offset > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
}
/* does EOCD fit before EOCD locator? */
if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD);
return NULL;
}
/* make sure current position of buffer is beginning of EOCD */
if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) {
_zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
free_buffer = false;
}
else {
if (fs_zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
zip_error_set_from_source(error, src);
return NULL;
}
if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) {
return NULL;
}
free_buffer = true;
}
if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC);
if (free_buffer) {
_zip_buffer_free(buffer);
}
return NULL;
}
/* size of EOCD */
size = _zip_buffer_get_64(buffer);
/* is there a hole between EOCD and EOCD locator, or do they overlap? */
if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD);
if (free_buffer) {
_zip_buffer_free(buffer);
}
return NULL;
}
_zip_buffer_get(buffer, 4); /* skip version made by/needed */
num_disks64 = _zip_buffer_get_32(buffer);
eocd_disk64 = _zip_buffer_get_32(buffer);
/* if eocd values are 0xffff, we have to use eocd64 values.
otherwise, if the values are not the same, it's inconsistent;
in any case, if the value is not 0, we don't support it */
if (num_disks == 0xffff) {
num_disks = num_disks64;
}
if (eocd_disk == 0xffff) {
eocd_disk = eocd_disk64;
}
if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_MISMATCH);
if (free_buffer) {
_zip_buffer_free(buffer);
}
return NULL;
}
if (num_disks != 0 || eocd_disk != 0) {
zip_error_set(error, ZIP_ER_MULTIDISK, 0);
if (free_buffer) {
_zip_buffer_free(buffer);
}
return NULL;
}
nentry = _zip_buffer_get_64(buffer);
i = _zip_buffer_get_64(buffer);
if (nentry != i) {
zip_error_set(error, ZIP_ER_MULTIDISK, 0);
if (free_buffer) {
_zip_buffer_free(buffer);
}
return NULL;
}
size = _zip_buffer_get_64(buffer);
offset = _zip_buffer_get_64(buffer);
/* did we read past the end of the buffer? */
if (!_zip_buffer_ok(buffer)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
if (free_buffer) {
_zip_buffer_free(buffer);
}
return NULL;
}
if (free_buffer) {
_zip_buffer_free(buffer);
}
if (offset > ZIP_INT64_MAX || offset + size < offset) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return NULL;
}
if (offset + size > buf_offset + eocd_offset) {
/* cdir spans past EOCD record */
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
return NULL;
}
if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD);
return NULL;
}
if (nentry > size / CDENTRYSIZE) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_INVALID);
return NULL;
}
if ((cd = _zip_cdir_new(nentry, error)) == NULL)
return NULL;
cd->is_zip64 = true;
cd->size = size;
cd->offset = offset;
return cd;
}
static int decode_hex(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
}
else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
else {
return -1;
}
}
/* _zip_check_torrentzip:
check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */
static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir) {
zip_uint32_t crc_should;
char buf[8+1];
size_t i;
if (cdir == NULL) {
return;
}
if (_zip_string_length(cdir->comment) != TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH
|| strncmp((const char *)cdir->comment->raw, TORRENTZIP_SIGNATURE, TORRENTZIP_SIGNATURE_LENGTH) != 0)
return;
memcpy(buf, cdir->comment->raw + TORRENTZIP_SIGNATURE_LENGTH, TORRENTZIP_CRC_LENGTH);
buf[TORRENTZIP_CRC_LENGTH] = '\0';
crc_should = 0;
for (i = 0; i < TORRENTZIP_CRC_LENGTH; i += 2) {
int low, high;
high = decode_hex((buf[i]));
low = decode_hex(buf[i + 1]);
if (high < 0 || low < 0) {
return;
}
crc_should = (crc_should << 8) + (high << 4) + low;
}
{
zip_stat_t st;
zip_source_t* src_window;
zip_source_t* src_crc;
zip_uint8_t buffer[512];
zip_int64_t ret;
fs_zip_stat_init(&st);
st.valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC;
st.size = cdir->size;
st.crc = crc_should;
if ((src_window = _zip_source_window_new(za->src, cdir->offset, cdir->size, &st, 0, NULL, NULL, 0, false, NULL)) == NULL) {
return;
}
if ((src_crc = zip_source_crc_create(src_window, 1, NULL)) == NULL) {
zip_source_free(src_window);
return;
}
if (fs_zip_source_open(src_crc) != 0) {
zip_source_free(src_crc);
return;
}
while ((ret = fs_zip_source_read(src_crc, buffer, sizeof(buffer))) > 0) {
}
zip_source_free(src_crc);
if (ret < 0) {
return;
}
}
/* TODO: if check consistency, check cdir entries for valid values */
za->flags |= ZIP_AFL_IS_TORRENTZIP;
}
+293
View File
@@ -0,0 +1,293 @@
/*
zip_progress.c -- progress reporting
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 <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>
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
struct zip_progress {
zip_t *za;
zip_progress_callback callback_progress;
void (*ud_progress_free)(void *);
void *ud_progress;
zip_cancel_callback callback_cancel;
void (*ud_cancel_free)(void *);
void *ud_cancel;
double precision;
/* state */
double last_update; /* last value callback function was called with */
double start; /* start of sub-progress section */
double end; /* end of sub-progress section */
};
static void _zip_progress_free_cancel_callback(zip_progress_t *progress);
static void _zip_progress_free_progress_callback(zip_progress_t *progress);
static zip_progress_t *_zip_progress_new(zip_t *za);
static void _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud);
static void _zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
void
_zip_progress_end(zip_progress_t *progress) {
_zip_progress_update(progress, 1.0);
}
void
_zip_progress_free(zip_progress_t *progress) {
if (progress == NULL) {
return;
}
_zip_progress_free_progress_callback(progress);
_zip_progress_free_cancel_callback(progress);
free(progress);
}
static zip_progress_t *
_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;
}
progress->za = za;
progress->callback_progress = NULL;
progress->ud_progress_free = NULL;
progress->ud_progress = NULL;
progress->precision = 0.0;
progress->callback_cancel = NULL;
progress->ud_cancel_free = NULL;
progress->ud_cancel = NULL;
return progress;
}
static void
_zip_progress_free_progress_callback(zip_progress_t *progress) {
if (progress->ud_progress_free) {
progress->ud_progress_free(progress->ud_progress);
}
progress->callback_progress = NULL;
progress->ud_progress = NULL;
progress->ud_progress_free = NULL;
}
static void
_zip_progress_free_cancel_callback(zip_progress_t *progress) {
if (progress->ud_cancel_free) {
progress->ud_cancel_free(progress->ud_cancel);
}
progress->callback_cancel = NULL;
progress->ud_cancel = NULL;
progress->ud_cancel_free = NULL;
}
static void
_zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
_zip_progress_free_progress_callback(progress);
progress->callback_progress = callback;
progress->ud_progress_free = ud_free;
progress->ud_progress = ud;
progress->precision = precision;
}
void
_zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
_zip_progress_free_cancel_callback(progress);
progress->callback_cancel = callback;
progress->ud_cancel_free = ud_free;
progress->ud_cancel = ud;
}
int
_zip_progress_start(zip_progress_t *progress) {
if (progress == NULL) {
return 0;
}
if (progress->callback_progress != NULL) {
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;
}
}
return 0;
}
int
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
if (progress == NULL) {
return 0;
}
progress->start = start;
progress->end = end;
return _zip_progress_update(progress, 0.0);
}
int
_zip_progress_update(zip_progress_t *progress, double sub_current) {
double current;
if (progress == NULL) {
return 0;
}
if (progress->callback_progress != NULL) {
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 (progress->callback_cancel != NULL) {
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
return -1;
}
}
return 0;
}
ZIP_EXTERN int
fs_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;
}
}
_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);
}
}
}
return 0;
}
ZIP_EXTERN int
fs_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;
}
}
_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);
}
}
}
return 0;
}
struct legacy_ud {
zip_progress_callback_t callback;
};
static void
_zip_legacy_progress_callback(zip_t *za, double progress, void *vud) {
struct legacy_ud *ud = (struct legacy_ud *)vud;
ud->callback(progress);
}
ZIP_EXTERN void
zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) {
struct legacy_ud *ud;
if (progress_callback == NULL) {
fs_zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
}
if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
return;
}
ud->callback = progress_callback;
if (fs_zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
free(ud);
}
}
+42
View File
@@ -0,0 +1,42 @@
/*
zip_rename.c -- rename file in zip archive
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN int
zip_rename(zip_t *za, zip_uint64_t idx, const char *name) {
return fs_zip_file_rename(za, idx, name, 0);
}
+42
View File
@@ -0,0 +1,42 @@
/*
zip_replace.c -- replace file via callback function
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
ZIP_EXTERN int
zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source) {
return fs_zip_file_replace(za, idx, source, 0);
}
+84
View File
@@ -0,0 +1,84 @@
/*
fs_zip_set_archive_comment.c -- set archive comment
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 <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"
ZIP_EXTERN int
fs_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;
}
if (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (len > 0 && comment == NULL) {
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 (_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;
_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;
}
else {
za->comment_changes = cstr;
za->comment_changed = 1;
}
return 0;
}
+76
View File
@@ -0,0 +1,76 @@
/*
fs_zip_get_archive_flag.c -- set archive global flag
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 <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 int
fs_zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) {
unsigned int new_flags;
if (flag == ZIP_AFL_IS_TORRENTZIP) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
/* TODO: when setting ZIP_AFL_WANT_TORRENTZIP, we should error out if any changes have been made that are not allowed for torrentzip. */
if (value) {
new_flags = za->ch_flags | flag;
}
else {
new_flags = za->ch_flags & ~flag;
}
if (new_flags == za->ch_flags) {
return 0;
}
/* Allow removing ZIP_AFL_RDONLY if manually set, not if archive was opened read-only. */
if (za->flags & ZIP_AFL_RDONLY) {
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;
}
}
za->ch_flags = new_flags;
return 0;
}
+58
View File
@@ -0,0 +1,58 @@
/*
fs_zip_set_default_password.c -- set default password for decryption
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 <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 <string.h>
#include "zipint.h"
ZIP_EXTERN int
fs_zip_set_default_password(zip_t *za, const char *passwd) {
if (za == NULL)
return -1;
free(za->default_password);
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;
return 0;
}
+46
View File
@@ -0,0 +1,46 @@
/*
zip_set_file_comment.c -- set comment for file in archive
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 <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.
*/
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
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;
}
return fs_zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
}
+95
View File
@@ -0,0 +1,95 @@
/*
fs_zip_set_file_compression.c -- set compression for file in archive
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 <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 int
fs_zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags) {
zip_entry_t *e;
zip_int32_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 (ZIP_WANT_TORRENTZIP(za)) {
zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0);
return -1;
}
if (!fs_zip_compression_method_supported(method, true)) {
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
return -1;
}
e = za->entry + idx;
old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method);
/* TODO: do we want to recompress if level is set? Only if it's
* different than what bit flags tell us, but those are not
* defined for all compression methods, or not directly mappable
* 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;
}
}
}
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;
}
}
e->changes->comp_method = method;
e->changes->compression_level = (zip_uint16_t)flags;
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
}
return 0;
}
+157
View File
@@ -0,0 +1,157 @@
/*
zip_set_name.c -- rename helper function
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 <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 <string.h>
#include "zipint.h"
int
_zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) {
zip_entry_t *e;
zip_string_t *str;
bool same_as_orig;
zip_int64_t i;
const zip_uint8_t *old_name, *new_name;
zip_string_t *old_str;
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 (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;
}
else
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;
}
/* no effective name change */
if (i >= 0 && (zip_uint64_t)i == idx) {
_zip_string_free(str);
return 0;
}
e = za->entry + idx;
if (e->orig)
same_as_orig = _zip_string_equal(e->orig->filename, str);
else
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 ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
_zip_string_free(str);
return -1;
}
if (e->changes) {
old_str = e->changes->filename;
}
else if (e->orig) {
old_str = e->orig->filename;
}
else {
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;
}
}
else {
old_name = NULL;
}
if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
_zip_string_free(str);
return -1;
}
if (old_name) {
_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);
}
else {
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;
}
+52
View File
@@ -0,0 +1,52 @@
/*
zip_source_accept_empty.c -- if empty source is a valid archive
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 <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"
bool
zip_source_accept_empty(zip_source_t *src) {
zip_int64_t 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;
}
ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
return ret != 0;
}
+57
View File
@@ -0,0 +1,57 @@
/*
fs_zip_source_begin_write.c -- start a new file for writing
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 <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 int
fs_zip_source_begin_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
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;
}
src->write_state = ZIP_SOURCE_WRITE_OPEN;
return 0;
}
@@ -0,0 +1,57 @@
/*
fs_zip_source_begin_write_cloning.c -- clone part of file for writing
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 int
fs_zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
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;
}
src->write_state = ZIP_SOURCE_WRITE_OPEN;
return 0;
}
+643
View File
@@ -0,0 +1,643 @@
/*
fs_zip_source_buffer.c -- create zip data source from buffer
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 <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 <string.h>
#include "zipint.h"
#ifndef WRITE_FRAGMENT_SIZE
#define WRITE_FRAGMENT_SIZE (64 * 1024)
#endif
struct buffer {
zip_buffer_fragment_t *fragments; /* fragments */
zip_uint64_t *fragment_offsets; /* offset of each fragment from start of buffer, nfragments+1 entries */
zip_uint64_t nfragments; /* number of allocated fragments */
zip_uint64_t fragments_capacity; /* size of fragments (number of pointers) */
zip_uint64_t first_owned_fragment; /* first fragment to free data from */
zip_uint64_t shared_fragments; /* number of shared fragments */
struct buffer *shared_buffer; /* buffer fragments are shared with */
zip_uint64_t size; /* size of buffer */
zip_uint64_t offset; /* current offset in buffer */
zip_uint64_t current_fragment; /* fragment current offset is in */
};
typedef struct buffer buffer_t;
struct read_data {
zip_error_t error;
time_t mtime;
zip_file_attributes_t attributes;
buffer_t *in;
buffer_t *out;
};
#define buffer_capacity(buffer) ((buffer)->fragment_offsets[(buffer)->nfragments])
#define buffer_size(buffer) ((buffer)->size)
static buffer_t *buffer_clone(buffer_t *buffer, zip_uint64_t length, zip_error_t *error);
static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset);
static void buffer_free(buffer_t *buffer);
static bool buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error);
static buffer_t *buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error);
static zip_int64_t buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length);
static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error);
static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *);
static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t);
zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error);
ZIP_EXTERN zip_source_t *
fs_zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
if (za == NULL)
return NULL;
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
}
ZIP_EXTERN zip_source_t *
fs_zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) {
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, error);
}
zip_source_t *
zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
zip_buffer_fragment_t fragment;
if (data == 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);
}
fragment.data = (zip_uint8_t *)data;
fragment.length = len;
return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error);
}
ZIP_EXTERN zip_source_t *
fs_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 zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
}
ZIP_EXTERN zip_source_t *
fs_zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) {
return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error);
}
zip_source_t *
zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error) {
struct read_data *ctx;
zip_source_t *zs;
buffer_t *buffer;
if (fragments == NULL && nfragments > 0) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((buffer = buffer_new(fragments, nfragments, freep, error)) == 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;
}
ctx->in = buffer;
ctx->out = NULL;
ctx->mtime = time(NULL);
if (attributes) {
(void)memcpy_s(&ctx->attributes, sizeof(ctx->attributes), attributes, sizeof(ctx->attributes));
}
else {
fs_zip_file_attributes_init(&ctx->attributes);
}
fs_zip_error_init(&ctx->error);
if ((zs = fs_zip_source_function_create(read_data, ctx, error)) == NULL) {
buffer_free(ctx->in);
free(ctx);
return NULL;
}
return zs;
}
zip_source_t *
zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes) {
return zip_source_buffer_with_attributes_create(data, len, freep, attributes, &za->error);
}
static zip_int64_t
read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
struct read_data *ctx = (struct read_data *)state;
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;
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;
case ZIP_SOURCE_CLOSE:
return 0;
case ZIP_SOURCE_COMMIT_WRITE:
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);
case ZIP_SOURCE_FREE:
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;
}
(void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes));
return sizeof(ctx->attributes);
}
case ZIP_SOURCE_OPEN:
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);
case ZIP_SOURCE_REMOVE: {
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
if (empty == NULL) {
return -1;
}
buffer_free(ctx->in);
ctx->in = empty;
return 0;
}
case ZIP_SOURCE_ROLLBACK_WRITE:
buffer_free(ctx->out);
ctx->out = NULL;
return 0;
case ZIP_SOURCE_SEEK:
return buffer_seek(ctx->in, data, len, &ctx->error);
case ZIP_SOURCE_SEEK_WRITE:
return buffer_seek(ctx->out, data, len, &ctx->error);
case ZIP_SOURCE_STAT: {
zip_stat_t *st;
if (len < sizeof(*st)) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
st = (zip_stat_t *)data;
fs_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);
}
case ZIP_SOURCE_SUPPORTS:
return fs_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, ZIP_SOURCE_SUPPORTS_REOPEN, -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;
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;
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);
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
}
static buffer_t *
buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
zip_uint64_t fragment, fragment_offset, waste;
buffer_t *clone;
if (offset == 0) {
return buffer_new(NULL, 0, 1, error);
}
if (offset > buffer->size) {
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;
}
fragment = buffer_find_fragment(buffer, offset);
fragment_offset = offset - buffer->fragment_offsets[fragment];
if (fragment_offset == 0) {
fragment--;
fragment_offset = buffer->fragments[fragment].length;
}
/* TODO: This should also consider the length of the fully shared fragments */
waste = buffer->fragments[fragment].length - fragment_offset;
if (waste > offset) {
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
return NULL;
}
if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
return NULL;
}
#ifndef __clang_analyzer__
/* clone->fragments can't be null, since it was created with at least one fragment */
clone->fragments[fragment].length = fragment_offset;
#endif
clone->fragment_offsets[clone->nfragments] = offset;
clone->size = offset;
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments);
buffer->shared_buffer = clone;
clone->shared_buffer = buffer;
buffer->shared_fragments = fragment + 1;
clone->shared_fragments = fragment + 1;
return clone;
}
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;
}
}
return low;
}
static void
buffer_free(buffer_t *buffer) {
zip_uint64_t i;
if (buffer == NULL) {
return;
}
if (buffer->shared_buffer != NULL) {
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);
}
for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
free(buffer->fragments[i].data);
}
free(buffer->fragments);
free(buffer->fragment_offsets);
free(buffer);
}
static bool
buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) {
zip_buffer_fragment_t *fragments;
zip_uint64_t *offsets;
if (capacity < buffer->fragments_capacity) {
return true;
}
zip_uint64_t fragments_size = sizeof(buffer->fragments[0]) * capacity;
zip_uint64_t offsets_size = sizeof(buffer->fragment_offsets[0]) * (capacity + 1);
if (capacity == ZIP_UINT64_MAX || fragments_size < capacity || fragments_size > SIZE_MAX|| offsets_size < capacity || offsets_size > SIZE_MAX) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
if ((fragments = realloc(buffer->fragments, (size_t)fragments_size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
buffer->fragments = fragments;
if ((offsets = realloc(buffer->fragment_offsets, (size_t)offsets_size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
buffer->fragment_offsets = offsets;
buffer->fragments_capacity = capacity;
return true;
}
static buffer_t *
buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error) {
buffer_t *buffer;
if ((buffer = malloc(sizeof(*buffer))) == NULL) {
return NULL;
}
buffer->offset = 0;
buffer->first_owned_fragment = 0;
buffer->size = 0;
buffer->fragments = NULL;
buffer->fragment_offsets = NULL;
buffer->nfragments = 0;
buffer->fragments_capacity = 0;
buffer->shared_buffer = NULL;
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;
}
else {
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;
}
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;
/* TODO: overflow */
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;
}
static zip_int64_t
buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
zip_uint64_t n, i, fragment_offset;
length = ZIP_MIN(length, buffer->size - buffer->offset);
if (length == 0) {
return 0;
}
if (length > ZIP_INT64_MAX) {
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);
#if ZIP_UINT64_MAX > SIZE_MAX
left = ZIP_MIN(left, SIZE_MAX);
#endif
(void)memcpy_s(data + n, (size_t)left, buffer->fragments[i].data + fragment_offset, (size_t)left);
if (left == buffer->fragments[i].length - fragment_offset) {
i++;
}
n += left;
fragment_offset = 0;
}
buffer->offset += n;
buffer->current_fragment = i;
return (zip_int64_t)n;
}
static int
buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error) {
zip_int64_t new_offset = fs_zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error);
if (new_offset < 0) {
return -1;
}
buffer->offset = (zip_uint64_t)new_offset;
buffer->current_fragment = buffer_find_fragment(buffer, buffer->offset);
return 0;
}
static zip_int64_t
buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) {
zip_uint64_t copied, i, fragment_offset, capacity;
if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
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;
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 (!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;
}
}
i = buffer->current_fragment;
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
copied = 0;
while (copied < length) {
zip_uint64_t n = ZIP_MIN(ZIP_MIN(length - copied, buffer->fragments[i].length - fragment_offset), SIZE_MAX);
#if ZIP_UINT64_MAX > SIZE_MAX
n = ZIP_MIN(n, SIZE_MAX);
#endif
(void)memcpy_s(buffer->fragments[i].data + fragment_offset, (size_t)n, data + copied, (size_t)n);
if (n == buffer->fragments[i].length - fragment_offset) {
i++;
fragment_offset = 0;
}
else {
fragment_offset += n;
}
copied += n;
}
buffer->offset += copied;
buffer->current_fragment = i;
if (buffer->offset > buffer->size) {
buffer->size = buffer->offset;
}
return (zip_int64_t)copied;
}
+68
View File
@@ -0,0 +1,68 @@
/*
zip_source_call.c -- invoke callback command on zip_source
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 <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_int64_t
_zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) {
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;
}
if (src->src == NULL) {
ret = src->cb.f(src->ud, data, length, command);
}
else {
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 (_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;
}
+57
View File
@@ -0,0 +1,57 @@
/*
fs_zip_source_close.c -- close zip_source (stop reading)
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 <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"
int
fs_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;
}
src->open_count--;
if (src->open_count == 0) {
_zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
if (ZIP_SOURCE_IS_LAYERED(src)) {
if (fs_zip_source_close(src->src) < 0) {
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
}
}
}
return 0;
}
+68
View File
@@ -0,0 +1,68 @@
/*
fs_zip_source_commit_write.c -- commit changes to file
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 <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 int
fs_zip_source_commit_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
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;
}
else if (ZIP_SOURCE_IS_OPEN_READING(src)) {
if (fs_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_CLOSED;
return 0;
}
+398
View File
@@ -0,0 +1,398 @@
/*
zip_source_compress.c -- (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 <stdlib.h>
#include <string.h>
#include "zipint.h"
struct context {
zip_error_t error;
bool end_of_input;
bool end_of_stream;
bool can_store;
bool is_stored; /* only valid if end_of_stream is true */
bool compress;
zip_int32_t method;
zip_uint64_t size;
zip_int64_t first_read;
zip_uint8_t buffer[BUFSIZE];
zip_compression_algorithm_t *algorithm;
void *ud;
};
struct implementation {
zip_uint16_t method;
zip_compression_algorithm_t *compress;
zip_compression_algorithm_t *decompress;
};
static struct implementation implementations[] = {
{ZIP_CM_DEFLATE, &zip_algorithm_deflate_compress, &zip_algorithm_deflate_decompress},
#if defined(HAVE_LIBBZ2)
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
#endif
#if defined(HAVE_LIBLZMA)
{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_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
};
static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]);
static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags);
static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
static void context_free(struct context *ctx);
static struct context *context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm);
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
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;
}
}
}
return NULL;
}
ZIP_EXTERN int
fs_zip_compression_method_supported(zip_int32_t method, int compress) {
if (method == ZIP_CM_STORE) {
return 1;
}
return _zip_get_compression_algorithm(method, compress) != NULL;
}
zip_source_t *
zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, zip_uint32_t compression_flags) {
return compression_source_new(za, src, method, true, compression_flags);
}
zip_source_t *
zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) {
return compression_source_new(za, src, method, false, 0);
}
static zip_source_t *
compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags) {
struct context *ctx;
zip_source_t *s2;
zip_compression_algorithm_t *algorithm = NULL;
if (src == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 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;
}
if ((s2 = fs_zip_source_layered(za, src, compress_callback, ctx)) == NULL) {
context_free(ctx);
return NULL;
}
return s2;
}
static struct context *
context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm) {
struct context *ctx;
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
return NULL;
}
fs_zip_error_init(&ctx->error);
ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
ctx->algorithm = algorithm;
ctx->method = method;
ctx->compress = compress;
ctx->end_of_input = false;
ctx->end_of_stream = false;
ctx->is_stored = false;
if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
fs_zip_error_fini(&ctx->error);
free(ctx);
return NULL;
}
return ctx;
}
static void
context_free(struct context *ctx) {
if (ctx == NULL) {
return;
}
ctx->algorithm->deallocate(ctx->ud);
fs_zip_error_fini(&ctx->error);
free(ctx);
}
static zip_int64_t
compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t len) {
zip_compression_status_t ret;
bool end;
zip_int64_t n;
zip_uint64_t out_offset;
zip_uint64_t out_len;
if (fs_zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
return -1;
}
if (len == 0 || ctx->end_of_stream) {
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);
if (ret != ZIP_COMPRESSION_ERROR) {
out_offset += out_len;
}
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->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;
(void)memcpy_s(data, ctx->size, ctx->buffer, ctx->size);
return (zip_int64_t)ctx->size;
}
end = true;
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;
}
if ((n = fs_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;
case ZIP_COMPRESSION_ERROR:
/* error set by algorithm */
if (fs_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;
}
return (fs_zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
}
static zip_int64_t
compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
struct context *ctx;
ctx = (struct context *)ud;
switch (cmd) {
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 (fs_zip_source_stat(src, &st) < 0 || fs_zip_source_get_file_attributes(src, &attributes) < 0) {
zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (!ctx->algorithm->start(ctx->ud, &st, &attributes)) {
return -1;
}
return 0;
}
case ZIP_SOURCE_READ:
return compress_read(src, ctx, data, len);
case ZIP_SOURCE_CLOSE:
if (!ctx->algorithm->end(ctx->ud)) {
return -1;
}
return 0;
case ZIP_SOURCE_STAT: {
zip_stat_t *st;
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;
st->valid &= ~ZIP_STAT_COMP_SIZE;
if (ctx->end_of_stream) {
st->size = ctx->size;
st->valid |= ZIP_STAT_SIZE;
}
}
}
return 0;
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
context_free(ctx);
return 0;
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
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;
}
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);
}
case ZIP_SOURCE_SUPPORTS:
return ZIP_SOURCE_SUPPORTS_READABLE | fs_zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
default:
return fs_zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}
+203
View File
@@ -0,0 +1,203 @@
/*
zip_source_crc.c -- pass-through source that calculates CRC32 and size
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 <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 <limits.h>
#include <stdlib.h>
#include <zlib-ng.h>
#include "zipint.h"
struct crc_context {
int validate; /* whether to check CRC on EOF and return error on mismatch */
int crc_complete; /* whether CRC was computed for complete file */
zip_error_t error;
zip_uint64_t size;
zip_uint64_t position; /* current reading position */
zip_uint64_t crc_position; /* how far we've computed the CRC */
zip_uint32_t crc;
};
static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
zip_source_t *
zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) {
struct crc_context *ctx;
if (src == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
fs_zip_error_init(&ctx->error);
ctx->validate = validate;
ctx->crc_complete = 0;
ctx->crc_position = 0;
ctx->crc = (zip_uint32_t)zng_crc32(0, NULL, 0);
ctx->size = 0;
return fs_zip_source_layered_create(src, crc_read, ctx, error);
}
static zip_int64_t
crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
struct crc_context *ctx;
zip_int64_t n;
ctx = (struct crc_context *)_ctx;
switch (cmd) {
case ZIP_SOURCE_OPEN:
ctx->position = 0;
return 0;
case ZIP_SOURCE_READ:
if ((n = fs_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 (ctx->validate) {
struct fs_zip_stat st;
if (fs_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) {
/* 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);
ctx->crc = (zip_uint32_t)zng_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;
case ZIP_SOURCE_STAT: {
zip_stat_t *st;
st = (zip_stat_t *)data;
if (ctx->crc_complete) {
if ((st->valid & ZIP_STAT_SIZE) && st->size != ctx->size) {
zip_error_set(&ctx->error, ZIP_ER_DATA_LENGTH, 0);
return -1;
}
/* 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);
case ZIP_SOURCE_FREE:
free(ctx);
return 0;
case ZIP_SOURCE_SUPPORTS: {
zip_int64_t mask = zip_source_supports(src);
if (mask < 0) {
zip_error_set_from_source(&ctx->error, src);
return -1;
}
mask &= ~fs_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);
mask |= fs_zip_source_make_command_bitmap(ZIP_SOURCE_FREE, -1);
return mask;
}
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);
if (args == NULL) {
return -1;
}
if (fs_zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = fs_zip_source_tell(src)) < 0) {
zip_error_set_from_source(&ctx->error, src);
return -1;
}
ctx->position = (zip_uint64_t)new_position;
return 0;
}
case ZIP_SOURCE_TELL:
return (zip_int64_t)ctx->position;
default:
return fs_zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}
+46
View File
@@ -0,0 +1,46 @@
/*
fs_zip_source_error.c -- get last error from zip_source
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 <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_error_t *
fs_zip_source_error(zip_source_t *src) {
return &src->error;
}
bool
_zip_source_had_error(zip_source_t *src) {
return fs_zip_source_error(src)->zip_err != ZIP_ER_OK;
}
+90
View File
@@ -0,0 +1,90 @@
/*
fs_zip_source_file.h -- header for common file operations
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 <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.
*/
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 valid */
bool regular_file; /* must always be valid */
};
typedef struct zip_source_file_context zip_source_file_context_t;
typedef struct zip_source_file_operations zip_source_file_operations_t;
typedef struct zip_source_file_stat zip_source_file_stat_t;
struct zip_source_file_context {
zip_error_t error; /* last error information */
zip_int64_t supports;
/* reading */
char *fname; /* name of file to read from */
void *f; /* file to read from */
zip_stat_t st; /* stat information passed in */
zip_file_attributes_t attributes; /* additional file attributes */
zip_error_t stat_error; /* error returned for stat */
zip_uint64_t start; /* start offset of data to read */
zip_uint64_t len; /* length of the file, 0 for up to EOF */
zip_uint64_t offset; /* current offset relative to start (0 is beginning of part we read) */
/* writing */
char *tmpname;
void *fout;
zip_source_file_operations_t *ops;
void *ops_userdata;
};
/* The following methods must be implemented to support each feature:
- close, read, seek, and stat must always be implemented.
- To support specifying the file by name, open, and strdup must be implemented.
- For write support, the file must be specified by name and close, commit_write, create_temp_output, remove, rollback_write, and tell must be implemented.
- create_temp_output_cloning is always optional. */
struct zip_source_file_operations {
void (*close)(zip_source_file_context_t *ctx);
zip_int64_t (*commit_write)(zip_source_file_context_t *ctx);
zip_int64_t (*create_temp_output)(zip_source_file_context_t *ctx);
zip_int64_t (*create_temp_output_cloning)(zip_source_file_context_t *ctx, zip_uint64_t len);
bool (*open)(zip_source_file_context_t *ctx);
zip_int64_t (*read)(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len);
zip_int64_t (*remove)(zip_source_file_context_t *ctx);
void (*rollback_write)(zip_source_file_context_t *ctx);
bool (*seek)(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence);
bool (*stat)(zip_source_file_context_t *ctx, zip_source_file_stat_t *st);
char *(*string_duplicate)(zip_source_file_context_t *ctx, const char *);
zip_int64_t (*tell)(zip_source_file_context_t *ctx, void *f);
zip_int64_t (*write)(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len);
};
zip_source_t *zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error);
+388
View File
@@ -0,0 +1,388 @@
/*
zip_source_file_common.c -- create data source from file
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 <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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zipint.h"
#include "zip_source_file.h"
static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
static void
zip_source_file_stat_init(zip_source_file_stat_t *st) {
st->size = 0;
st->mtime = time(NULL);
st->exists = false;
st->regular_file = false;
}
zip_source_t *
zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error) {
zip_source_file_context_t *ctx;
zip_source_t *zs;
zip_source_file_stat_t sb;
zip_uint64_t length;
if (ops == 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;
}
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;
}
if (fname != 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;
}
if (len < 0) {
if (len == -1) {
len = ZIP_LENGTH_TO_END;
}
// TODO: return ZIP_ER_INVAL if len != ZIP_LENGTH_UNCHECKED?
length = 0;
}
else {
length = (zip_uint64_t)len;
}
if (start > ZIP_INT64_MAX || start + length < start) {
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;
}
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;
}
}
ctx->f = file;
ctx->start = start;
ctx->len = length;
if (st) {
(void)memcpy_s(&ctx->st, sizeof(ctx->st), st, sizeof(*st));
ctx->st.name = NULL;
ctx->st.valid &= ~ZIP_STAT_NAME;
}
else {
fs_zip_stat_init(&ctx->st);
}
if (ctx->len > 0) {
ctx->st.size = ctx->len;
ctx->st.valid |= ZIP_STAT_SIZE;
}
fs_zip_error_init(&ctx->stat_error);
ctx->tmpname = NULL;
ctx->fout = NULL;
fs_zip_error_init(&ctx->error);
fs_zip_file_attributes_init(&ctx->attributes);
ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | fs_zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
zip_source_file_stat_init(&sb);
if (!ops->stat(ctx, &sb)) {
_zip_error_copy(error, &ctx->error);
free(ctx->fname);
free(ctx);
return NULL;
}
if (!sb.exists) {
if (ctx->fname && ctx->start == 0 && ctx->len == 0 && ops->write != NULL) {
ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
/* fs_zip_open_from_source checks for this to detect non-existing files */
zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT);
}
else {
zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT);
free(ctx->fname);
free(ctx);
return NULL;
}
}
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->start + ctx->len > sb.size) {
zip_error_set(error, ZIP_ER_INVAL, 0);
free(ctx->fname);
free(ctx);
return NULL;
}
if (ctx->len == 0) {
if (len != ZIP_LENGTH_UNCHECKED) {
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;
}
}
}
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 ((zs = fs_zip_source_function_create(read_file, ctx, error)) == NULL) {
free(ctx->fname);
free(ctx);
return NULL;
}
return zs;
}
static zip_int64_t
read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
zip_source_file_context_t *ctx;
char *buf;
ctx = (zip_source_file_context_t *)state;
buf = (char *)data;
switch (cmd) {
case ZIP_SOURCE_ACCEPT_EMPTY:
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);
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);
case ZIP_SOURCE_CLOSE:
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;
}
case ZIP_SOURCE_ERROR:
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;
case ZIP_SOURCE_GET_FILE_ATTRIBUTES:
if (len < sizeof(ctx->attributes)) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
(void)memcpy_s(data, sizeof(ctx->attributes), &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->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;
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;
return i;
}
case ZIP_SOURCE_REMOVE:
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;
case ZIP_SOURCE_SEEK: {
zip_int64_t new_offset = fs_zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
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;
}
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;
}
case ZIP_SOURCE_SEEK_WRITE: {
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;
}
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 (fs_zip_error_code_zip(&ctx->stat_error) != 0) {
zip_error_set(&ctx->error, fs_zip_error_code_zip(&ctx->stat_error), fs_zip_error_code_system(&ctx->stat_error));
return -1;
}
(void)memcpy_s(data, sizeof(ctx->st), &ctx->st, sizeof(ctx->st));
return sizeof(ctx->st);
}
case ZIP_SOURCE_SUPPORTS:
return ctx->supports;
case ZIP_SOURCE_TELL:
return (zip_int64_t)ctx->offset;
case ZIP_SOURCE_TELL_WRITE:
return ctx->ops->tell(ctx, ctx->fout);
case ZIP_SOURCE_WRITE:
return ctx->ops->write(ctx, data, len);
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
}
+71
View File
@@ -0,0 +1,71 @@
/*
zip_source_free.c -- free zip data source
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 <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"
ZIP_EXTERN void
zip_source_free(zip_source_t *src) {
if (src == NULL)
return;
if (src->refcount > 0) {
src->refcount--;
}
if (src->refcount > 0) {
return;
}
if (ZIP_SOURCE_IS_OPEN_READING(src)) {
src->open_count = 1; /* force close */
fs_zip_source_close(src);
}
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
fs_zip_source_rollback_write(src);
}
if (src->source_archive && !src->source_closed) {
_zip_deregister_source(src->source_archive, src);
}
(void)_zip_source_call(src, NULL, 0, ZIP_SOURCE_FREE);
if (src->src) {
zip_source_free(src->src);
}
free(src);
}

Some files were not shown because too many files have changed in this diff Show More