diff options
Diffstat (limited to 'src/Common/libzip/zip_source_win32handle.c')
-rw-r--r-- | src/Common/libzip/zip_source_win32handle.c | 602 |
1 files changed, 0 insertions, 602 deletions
diff --git a/src/Common/libzip/zip_source_win32handle.c b/src/Common/libzip/zip_source_win32handle.c deleted file mode 100644 index 8746cdd1..00000000 --- a/src/Common/libzip/zip_source_win32handle.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - zip_source_win32file.c -- create data source from HANDLE (Win32) - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - 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 <aclapi.h> -#include <stdlib.h> -#include <string.h> -#include <wchar.h> - -#include "zipint.h" -#include "zipwin32.h" - -static zip_int64_t _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd); -static int _win32_create_temp_file(_zip_source_win32_read_file_t *ctx); -static int _zip_filetime_to_time_t(FILETIME ft, time_t *t); -static int _zip_seek_win32_u(void *h, zip_uint64_t offset, int whence, zip_error_t *error); -static int _zip_seek_win32(void *h, zip_int64_t offset, int whence, zip_error_t *error); -static int _zip_win32_error_to_errno(unsigned long win32err); -static int _zip_stat_win32(void *h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx); - -ZIP_EXTERN zip_source_t * -zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - - return zip_source_win32handle_create(h, start, len, &za->error); -} - - -ZIP_EXTERN zip_source_t * -zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (h == INVALID_HANDLE_VALUE || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - return _zip_source_win32_handle_or_name(NULL, h, start, length, 1, NULL, NULL, error); -} - - -zip_source_t * -_zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start, zip_int64_t len, int closep, const zip_stat_t *st, _zip_source_win32_file_ops_t *ops, zip_error_t *error) { - _zip_source_win32_read_file_t *ctx; - zip_source_t *zs; - - if (h == INVALID_HANDLE_VALUE && fname == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - if ((ctx = (_zip_source_win32_read_file_t *)malloc(sizeof(_zip_source_win32_read_file_t))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; - } - - ctx->fname = NULL; - if (fname) { - if ((ctx->fname = ops->op_strdup(fname)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; - } - } - - ctx->ops = ops; - ctx->h = h; - ctx->start = start; - ctx->end = (len < 0 ? 0 : start + (zip_uint64_t)len); - ctx->closep = ctx->fname ? 1 : closep; - if (st) { - memcpy(&ctx->st, st, sizeof(ctx->st)); - ctx->st.name = NULL; - ctx->st.valid &= ~ZIP_STAT_NAME; - } - else { - zip_stat_init(&ctx->st); - } - - ctx->tmpname = NULL; - ctx->hout = INVALID_HANDLE_VALUE; - - zip_error_init(&ctx->error); - - ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1); - if (ctx->fname) { - HANDLE th; - - th = ops->op_open(ctx); - if (th == INVALID_HANDLE_VALUE || GetFileType(th) == FILE_TYPE_DISK) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; - } - if (th != INVALID_HANDLE_VALUE) { - CloseHandle(th); - } - } - else if (GetFileType(ctx->h) == FILE_TYPE_DISK) { - ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; - } - - ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY); - - if ((zs = zip_source_function_create(_win32_read_file, ctx, error)) == NULL) { - free(ctx->fname); - free(ctx); - return NULL; - } - - return zs; -} - - -static zip_int64_t -_win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { - _zip_source_win32_read_file_t *ctx; - char *buf; - zip_uint64_t n; - DWORD i; - - ctx = (_zip_source_win32_read_file_t *)state; - buf = (char *)data; - - switch (cmd) { - case ZIP_SOURCE_ACCEPT_EMPTY: - return 0; - - case ZIP_SOURCE_BEGIN_WRITE: - if (ctx->fname == NULL) { - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } - return _win32_create_temp_file(ctx); - - case ZIP_SOURCE_COMMIT_WRITE: { - if (!CloseHandle(ctx->hout)) { - ctx->hout = INVALID_HANDLE_VALUE; - zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); - } - ctx->hout = INVALID_HANDLE_VALUE; - if (ctx->ops->op_rename_temp(ctx) < 0) { - zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; - } - - case ZIP_SOURCE_CLOSE: - if (ctx->fname) { - CloseHandle(ctx->h); - ctx->h = INVALID_HANDLE_VALUE; - } - return 0; - - 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->closep && ctx->h != INVALID_HANDLE_VALUE) - CloseHandle(ctx->h); - free(ctx); - return 0; - - case ZIP_SOURCE_OPEN: - if (ctx->fname) { - if ((ctx->h = ctx->ops->op_open(ctx)) == INVALID_HANDLE_VALUE) { - zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - } - - if (ctx->closep && ctx->start > 0) { - if (_zip_seek_win32_u(ctx->h, ctx->start, SEEK_SET, &ctx->error) < 0) { - return -1; - } - } - ctx->current = ctx->start; - return 0; - - case ZIP_SOURCE_READ: - if (ctx->end > 0) { - n = ctx->end - ctx->current; - if (n > len) { - n = len; - } - } - else { - n = len; - } - - if (n > SIZE_MAX) - n = SIZE_MAX; - - if (!ctx->closep) { - if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) { - return -1; - } - } - - if (!ReadFile(ctx->h, buf, (DWORD)n, &i, NULL)) { - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - ctx->current += i; - - return (zip_int64_t)i; - - case ZIP_SOURCE_REMOVE: - if (ctx->ops->op_remove(ctx->fname) < 0) { - zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - return 0; - - case ZIP_SOURCE_ROLLBACK_WRITE: - if (ctx->hout) { - CloseHandle(ctx->hout); - ctx->hout = INVALID_HANDLE_VALUE; - } - ctx->ops->op_remove(ctx->tmpname); - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; - - case ZIP_SOURCE_SEEK: { - zip_int64_t new_current; - int need_seek; - zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - - if (args == NULL) - return -1; - - need_seek = ctx->closep; - - switch (args->whence) { - case SEEK_SET: - new_current = args->offset + ctx->start; - break; - - case SEEK_END: - if (ctx->end == 0) { - LARGE_INTEGER zero; - LARGE_INTEGER new_offset; - - if (_zip_seek_win32(ctx->h, args->offset, SEEK_END, &ctx->error) < 0) { - return -1; - } - zero.QuadPart = 0; - if (!SetFilePointerEx(ctx->h, zero, &new_offset, FILE_CURRENT)) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - new_current = new_offset.QuadPart; - need_seek = 0; - } - else { - new_current = (zip_int64_t)ctx->end + args->offset; - } - break; - case SEEK_CUR: - new_current = (zip_int64_t)ctx->current + args->offset; - break; - - default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (new_current < 0 || (zip_uint64_t)new_current < ctx->start || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - - ctx->current = (zip_uint64_t)new_current; - - if (need_seek) { - if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) { - 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 (_zip_seek_win32(ctx->hout, args->offset, args->whence, &ctx->error) < 0) { - return -1; - } - return 0; - } - - case ZIP_SOURCE_STAT: { - if (len < sizeof(ctx->st)) - return -1; - - if (ctx->st.valid != 0) - memcpy(data, &ctx->st, sizeof(ctx->st)); - else { - DWORD win32err; - zip_stat_t *st; - HANDLE h; - int success; - - st = (zip_stat_t *)data; - - if (ctx->h != INVALID_HANDLE_VALUE) { - h = ctx->h; - } - else { - h = ctx->ops->op_open(ctx); - if (h == INVALID_HANDLE_VALUE) { - win32err = GetLastError(); - if (win32err == ERROR_FILE_NOT_FOUND || win32err == ERROR_PATH_NOT_FOUND) { - zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT); - return -1; - } - } - } - - success = _zip_stat_win32(h, st, ctx); - win32err = GetLastError(); - - /* We're done with the handle, so close it if we just opened it. */ - if (h != ctx->h) { - CloseHandle(h); - } - - if (success < 0) { - /* TODO: Is this the correct error to return in all cases? */ - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(win32err)); - return -1; - } - } - return sizeof(ctx->st); - } - - case ZIP_SOURCE_SUPPORTS: - return ctx->supports; - - case ZIP_SOURCE_TELL: - return (zip_int64_t)ctx->current; - - case ZIP_SOURCE_TELL_WRITE: { - LARGE_INTEGER zero; - LARGE_INTEGER offset; - - zero.QuadPart = 0; - if (!SetFilePointerEx(ctx->hout, zero, &offset, FILE_CURRENT)) { - zip_error_set(&ctx->error, ZIP_ER_TELL, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - return offset.QuadPart; - } - - case ZIP_SOURCE_WRITE: { - DWORD ret; - if (!WriteFile(ctx->hout, data, (DWORD)len, &ret, NULL) || ret != len) { - zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - return (zip_int64_t)ret; - } - - default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } -} - - -static int -_win32_create_temp_file(_zip_source_win32_read_file_t *ctx) { - zip_uint32_t value; - /* - Windows has GetTempFileName(), but it closes the file after - creation, leaving it open to a horrible race condition. So - we reinvent the wheel. - */ - int i; - HANDLE th = INVALID_HANDLE_VALUE; - void *temp = NULL; - PSECURITY_DESCRIPTOR psd = NULL; - PSECURITY_ATTRIBUTES psa = NULL; - SECURITY_ATTRIBUTES sa; - SECURITY_INFORMATION si; - DWORD success; - PACL dacl = NULL; - - /* - Read the DACL from the original file, so we can copy it to the temp file. - If there is no original file, or if we can't read the DACL, we'll use the - default security descriptor. - */ - if (ctx->h != INVALID_HANDLE_VALUE && GetFileType(ctx->h) == FILE_TYPE_DISK) { - si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION; - success = GetSecurityInfo(ctx->h, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd); - if (success == ERROR_SUCCESS) { - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = FALSE; - sa.lpSecurityDescriptor = psd; - psa = &sa; - } - } - - -#ifndef MS_UWP - value = GetTickCount(); -#else - value = (zip_uint32_t)GetTickCount64(); -#endif - - for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) { - th = ctx->ops->op_create_temp(ctx, &temp, value + i, psa); - if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS) - break; - } - - if (th == INVALID_HANDLE_VALUE) { - free(temp); - LocalFree(psd); - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - LocalFree(psd); - ctx->hout = th; - ctx->tmpname = temp; - - return 0; -} - - -static int -_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error) { - if (offset > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW); - return -1; - } - return _zip_seek_win32(h, (zip_int64_t)offset, whence, error); -} - - -static int -_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error) { - LARGE_INTEGER li; - DWORD method; - - switch (whence) { - case SEEK_SET: - method = FILE_BEGIN; - break; - case SEEK_END: - method = FILE_END; - break; - case SEEK_CUR: - method = FILE_CURRENT; - break; - default: - zip_error_set(error, ZIP_ER_SEEK, EINVAL); - return -1; - } - - li.QuadPart = (LONGLONG)offset; - if (!SetFilePointerEx(h, li, NULL, method)) { - zip_error_set(error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - return 0; -} - - -static int -_zip_win32_error_to_errno(DWORD win32err) { - /* - Note: This list isn't exhaustive, but should cover common cases. - */ - switch (win32err) { - case ERROR_INVALID_PARAMETER: - return EINVAL; - case ERROR_FILE_NOT_FOUND: - return ENOENT; - case ERROR_INVALID_HANDLE: - return EBADF; - case ERROR_ACCESS_DENIED: - return EACCES; - case ERROR_FILE_EXISTS: - return EEXIST; - case ERROR_TOO_MANY_OPEN_FILES: - return EMFILE; - case ERROR_DISK_FULL: - return ENOSPC; - default: - return 0; - } -} - - -static int -_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx) { - FILETIME mtimeft; - time_t mtime; - LARGE_INTEGER size; - int regularp; - - if (!GetFileTime(h, NULL, NULL, &mtimeft)) { - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) { - zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); - return -1; - } - - regularp = 0; - if (GetFileType(h) == FILE_TYPE_DISK) { - regularp = 1; - } - - if (!GetFileSizeEx(h, &size)) { - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - zip_stat_init(st); - st->mtime = mtime; - st->valid |= ZIP_STAT_MTIME; - if (ctx->end != 0) { - st->size = ctx->end - ctx->start; - st->valid |= ZIP_STAT_SIZE; - } - else if (regularp) { - st->size = (zip_uint64_t)size.QuadPart; - st->valid |= ZIP_STAT_SIZE; - } - - return 0; -} - - -static int -_zip_filetime_to_time_t(FILETIME ft, time_t *t) { - /* - Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux - */ - const zip_int64_t WINDOWS_TICK = 10000000LL; - const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL; - ULARGE_INTEGER li; - zip_int64_t secs; - time_t temp; - - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); - - temp = (time_t)secs; - if (secs != (zip_int64_t)temp) - return -1; - - *t = temp; - return 0; -} |