diff --git a/CMakeLists.txt b/CMakeLists.txt index bd1b9500d..fa8e9de5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,10 @@ check_function_exists(_close HAVE__CLOSE) check_function_exists(_dup HAVE__DUP) check_function_exists(_fdopen HAVE__FDOPEN) check_function_exists(_fileno HAVE__FILENO) +check_function_exists(_fseeki64 HAVE__FSEEKI64) +check_function_exists(_fstat64 HAVE__FSTAT64) check_function_exists(_setmode HAVE__SETMODE) +check_function_exists(_stat64 HAVE__STAT64) check_symbol_exists(_snprintf stdio.h HAVE__SNPRINTF) check_symbol_exists(_snprintf_s stdio.h HAVE__SNPRINTF_S) check_symbol_exists(_snwprintf_s stdio.h HAVE__SNWPRINTF_S) @@ -463,8 +466,8 @@ else() endif() # write out config file -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in ${PROJECT_BINARY_DIR}/config.h) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-zipconf.h.in ${PROJECT_BINARY_DIR}/zipconf.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${PROJECT_BINARY_DIR}/config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zipconf.h.in ${PROJECT_BINARY_DIR}/zipconf.h) # for tests diff --git a/cmake-config.h.in b/config.h.in similarity index 96% rename from cmake-config.h.in rename to config.h.in index 630ed23f6..90a324285 100644 --- a/cmake-config.h.in +++ b/config.h.in @@ -10,10 +10,13 @@ #cmakedefine HAVE__DUP #cmakedefine HAVE__FDOPEN #cmakedefine HAVE__FILENO +#cmakedefine HAVE__FSEEKI64 +#cmakedefine HAVE__FSTAT64 #cmakedefine HAVE__SETMODE #cmakedefine HAVE__SNPRINTF #cmakedefine HAVE__SNPRINTF_S #cmakedefine HAVE__SNWPRINTF_S +#cmakedefine HAVE__STAT64 #cmakedefine HAVE__STRDUP #cmakedefine HAVE__STRICMP #cmakedefine HAVE__STRTOI64 diff --git a/lib/compat.h b/lib/compat.h index d8eaab1d4..489eae6f2 100644 --- a/lib/compat.h +++ b/lib/compat.h @@ -63,6 +63,7 @@ typedef char bool; #endif #include +#include /* at least MinGW does not provide EOPNOTSUPP, see * http://sourceforge.net/p/mingw/bugs/263/ @@ -123,14 +124,64 @@ typedef char bool; #endif #endif -#ifndef HAVE_FSEEKO -#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) + +#if defined(HAVE__FSEEKI64) && defined(HAVE__FSTAT64) && defined(HAVE__SEEK64) +/* Windows API using int64 */ +typedef zip_int64_t zip_off_t; +typedef struct _stat64 zip_os_stat_t; +#define zip_os_stat _stat64 +#define zip_os_fstat _fstat64 +#define zip_os_seek _fseeki64 +#define ZIP_FSEEK_MAX ZIP_INT64_MAX +#define ZIP_FSEEK_MIN ZIP_INT64_MIN +#else + +/* Normal API */ +#include +typedef struct stat zip_os_stat_t; +#define zip_os_fstat fstat +#define zip_os_stat stat + +#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO) +/* Using off_t */ +typedef off_t zip_off_t; +#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 + +#define ZIP_FSEEK_MAX ZIP_OFF_MAX +#define ZIP_FSEEK_MIN ZIP_OFF_MIN + +#define zip_os_fseek fseeko +#define zip_os_ftell ftello +#else + +/* Using long */ +typedef long zip_off_t; +#include +#define ZIP_FSEEK_MAX LONG_MAX +#define ZIP_FSEEK_MIN LONG_MIN + +#define zip_os_fseek fseek +#define zip_os_ftell ftell +#endif + #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! */ @@ -179,27 +230,6 @@ typedef char bool; #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 -#define ZIP_FSEEK_MAX LONG_MAX -#define ZIP_FSEEK_MIN LONG_MIN -#endif #ifndef SIZE_MAX #if SIZEOF_SIZE_T == 8 diff --git a/lib/zip_source_file_stdio.c b/lib/zip_source_file_stdio.c index f467a87f5..0fb858f12 100644 --- a/lib/zip_source_file_stdio.c +++ b/lib/zip_source_file_stdio.c @@ -39,7 +39,6 @@ #include #include #include -#include #ifdef _WIN32 #ifndef S_IWUSR @@ -120,7 +119,7 @@ _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, } #endif - if (fseeko((FILE *)f, (off_t)offset, whence) < 0) { + if (zip_os_fseek((FILE *)f, (zip_off_t)offset, whence) < 0) { zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); return false; } @@ -130,15 +129,15 @@ _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, bool _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { - struct stat sb; + zip_os_stat_t sb; int ret; if (ctx->fname) { - ret = stat(ctx->fname, &sb); + ret = zip_os_stat(ctx->fname, &sb); } else { - ret = fstat(fileno((FILE *)ctx->f), &sb); + ret = zip_os_fstat(fileno((FILE *)ctx->f), &sb); } if (ret < 0) { @@ -168,7 +167,7 @@ _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { zip_int64_t _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) { - off_t offset = ftello((FILE *)f); + zip_off_t offset = zip_os_ftell((FILE *)f); if (offset < 0) { zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); diff --git a/lib/zip_source_file_stdio_named.c b/lib/zip_source_file_stdio_named.c index 4a9e5f02c..1a5ca2260 100644 --- a/lib/zip_source_file_stdio_named.c +++ b/lib/zip_source_file_stdio_named.c @@ -178,9 +178,9 @@ _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uin { int fd; struct file_clone_range range; - struct stat st; + zip_os_stat_t st; - if (fstat(fileno(ctx->f), &st) < 0) { + if (zip_os_fstat(fileno(ctx->f), &st) < 0) { zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); return -1; } @@ -223,7 +223,7 @@ _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uin ctx->tmpname = NULL; return -1; } - if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) { + if (zip_os_fseek(tfp, (zip_off_t)offset, SEEK_SET) < 0) { zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); (void)fclose(tfp); (void)remove(ctx->tmpname); @@ -290,11 +290,11 @@ _zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64 static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) { char *temp; int mode; - struct stat st; + zip_os_stat_t st; int fd = 0; char *start, *end; - if (stat(ctx->fname, &st) == 0) { + if (zip_os_stat(ctx->fname, &st) == 0) { mode = st.st_mode; } else { @@ -344,7 +344,7 @@ static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) { } } else { - if (stat(temp, &st) < 0) { + if (zip_os_stat(temp, &st) < 0) { if (errno == ENOENT) { break; } diff --git a/cmake-zipconf.h.in b/zipconf.h.in similarity index 100% rename from cmake-zipconf.h.in rename to zipconf.h.in