// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "contrib/libzip/wrapper/wrapper_zip.h" #include #include #include #include "absl/cleanup/cleanup.h" constexpr size_t kFileMaxSize = 1024 * 1024 * 1024; // 1GB void* zip_source_filefd(zip_t* archive, int fd, const char* mode, zip_uint64_t start, zip_int64_t len) { FILE* pfile; // The file stream is closed when the source is being freed, // usually by zip_close(3). pfile = fdopen(fd, mode); if (pfile == nullptr) { return nullptr; } return zip_source_filep(archive, pfile, start, len); } void* zip_source_filefd_create(int fd, const char* mode, zip_uint64_t start, zip_int64_t len, zip_error_t* ze) { FILE* pfile; pfile = fdopen(fd, mode); if (pfile == nullptr) { return nullptr; } return zip_source_filep_create(pfile, start, len, ze); } off_t FDGetSize(int fd) { off_t size = lseek(fd, 0, SEEK_END); if (size < 0) { return -1; } if (lseek(fd, 0, SEEK_SET) < 0) { return -1; } return size; } void* zip_read_fd_to_source(int fd, zip_error_t* ze) { off_t sizein = FDGetSize(fd); if (sizein > kFileMaxSize) { return nullptr; } int8_t* buf = reinterpret_cast(malloc(sizein)); if (buf == nullptr) { return nullptr; } if (read(fd, buf, sizein) != sizein) { free(buf); return nullptr; } zip_source_t* src = zip_source_buffer_create(buf, sizein, 1, ze); if (src == nullptr) { free(buf); return nullptr; } return src; } // This function is not atomic. Maybe it should be? bool zip_source_to_fd(zip_source_t* src, int fd) { if (lseek(fd, 0, SEEK_SET) < 0) { return false; } if (ftruncate(fd, 0) < 0) { return false; } if (zip_source_open(src) < 0) { return false; } absl::Cleanup src_cleanup = [&src] { zip_source_close(src); }; if (zip_source_seek(src, 0, SEEK_SET) < 0) { return false; } int8_t buf[4096]; size_t size; while (true) { size = zip_source_read(src, &buf, sizeof(buf)); if (size <= 0) { break; } if (write(fd, &buf, size) != size) { return false; } } return size == 0; }