From ae7c0827f288918815ba447205c0196e171768dd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 20 Nov 2013 19:38:23 +0100 Subject: [PATCH] Hack unicode support into libzip --- ext/libzip/config.h | 4 ++- ext/libzip/mkstemp.c | 20 ++++++++++-- ext/libzip/zip.h | 4 +++ ext/libzip/zip_close.c | 71 +++++++++++++++++++++++++++++++++++------- ext/libzip/zip_open.c | 49 +++++++++++++++++++++++------ ext/libzip/zipint.h | 12 +++++-- native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++ 8 files changed, 143 insertions(+), 25 deletions(-) diff --git a/ext/libzip/config.h b/ext/libzip/config.h index e202a3d91..5cdc6c194 100644 --- a/ext/libzip/config.h +++ b/ext/libzip/config.h @@ -27,7 +27,9 @@ #endif /* Define to 1 if you have the `MoveFileExA' function. */ -/* #undef HAVE_MOVEFILEEXA */ +#ifdef _WIN32 +#define HAVE_MOVEFILEEXA 1 +#endif /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 diff --git a/ext/libzip/mkstemp.c b/ext/libzip/mkstemp.c index e8a749fce..54dc759b6 100644 --- a/ext/libzip/mkstemp.c +++ b/ext/libzip/mkstemp.c @@ -52,21 +52,33 @@ typedef int pid_t; #define O_BINARY 0 #endif - - int +#ifdef UNICODE +_zip_mkstemp(wchar_t *path) +#else _zip_mkstemp(char *path) +#endif { int fd; +#ifdef UNICODE + wchar_t *start, *trv; + struct _stat sbuf; +#else char *start, *trv; struct stat sbuf; +#endif + pid_t pid; /* To guarantee multiple calls generate unique names even if the file is not created. 676 different possibilities with 7 or more X's, 26 with 6 or less. */ // Urgh, not threadsafe at all. +#ifdef UNICODE + static wchar_t xtra[3] = L"aa"; +#else static char xtra[3] = "aa"; +#endif int xcnt = 0; pid = getpid(); @@ -110,7 +122,11 @@ _zip_mkstemp(char *path) break; if (*trv == '/') { *trv = '\0'; +#ifdef UNICODE + if (_wstat(path, &sbuf)) +#else if (stat(path, &sbuf)) +#endif return (0); #ifndef _WIN32 if (!S_ISDIR(sbuf.st_mode)) { diff --git a/ext/libzip/zip.h b/ext/libzip/zip.h index 1798051de..6a10e990a 100644 --- a/ext/libzip/zip.h +++ b/ext/libzip/zip.h @@ -204,7 +204,11 @@ ZIP_EXTERN const char *zip_get_file_comment(struct zip *, int, int *, int); ZIP_EXTERN const char *zip_get_name(struct zip *, int, int); ZIP_EXTERN int zip_get_num_files(struct zip *); ZIP_EXTERN int zip_name_locate(struct zip *, const char *, int); +#ifdef UNICODE +ZIP_EXTERN struct zip *zip_open(const wchar_t *, int, int *); +#else ZIP_EXTERN struct zip *zip_open(const char *, int, int *); +#endif ZIP_EXTERN int zip_rename(struct zip *, int, const char *); ZIP_EXTERN int zip_replace(struct zip *, int, struct zip_source *); ZIP_EXTERN int zip_set_archive_comment(struct zip *, const char *, int); diff --git a/ext/libzip/zip_close.c b/ext/libzip/zip_close.c index 60614c613..0feb32e94 100644 --- a/ext/libzip/zip_close.c +++ b/ext/libzip/zip_close.c @@ -53,7 +53,12 @@ static int copy_data(FILE *, off_t, FILE *, struct zip_error *); static int write_cdir(struct zip *, struct zip_cdir *, FILE *); static int _zip_cdir_set_comment(struct zip_cdir *, struct zip *); static int _zip_changed(struct zip *, int *); -static char *_zip_create_temp_output(struct zip *, FILE **); +#ifdef UNICODE +static wchar_t * +#else +static char * +#endif + _zip_create_temp_output(struct zip *, FILE **); static int _zip_torrentzip_cmp(const void *, const void *); @@ -70,7 +75,11 @@ zip_close(struct zip *za) { int survivors; int i, j, error; - char *temp; +#ifdef UNICODE + wchar_t *temp; +#else + char *temp; +#endif FILE *out; mode_t mask; struct zip_cdir *cd; @@ -92,9 +101,13 @@ zip_close(struct zip *za) /* don't create zip files with no entries */ if (survivors == 0) { if (za->zn && za->zp) { - if (remove(za->zn) != 0) { - _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); - return -1; +#ifdef UNICODE + if (_wremove(za->zn) != 0) { +#else + if (remove(za->zn) != 0) { +#endif + _zip_error_set(&za->error, ZIP_ER_REMOVE, errno); + return -1; } } _zip_free(za); @@ -133,7 +146,7 @@ zip_close(struct zip *za) } } - if ((temp=_zip_create_temp_output(za, &out)) == NULL) { + if ((temp = _zip_create_temp_output(za, &out)) == NULL) { _zip_cdir_free(cd); free(filelist); return -1; @@ -280,14 +293,22 @@ zip_close(struct zip *za) if (error) { _zip_dirent_finalize(&de); fclose(out); +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); return -1; } if (fclose(out) != 0) { _zip_error_set(&za->error, ZIP_ER_CLOSE, errno); +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); return -1; } @@ -297,13 +318,21 @@ zip_close(struct zip *za) za->zp = NULL; reopen_on_error = 1; } - if (_zip_rename(temp, za->zn) != 0) { + if (_zip_rename(temp, za->zn) != 0) { _zip_error_set(&za->error, ZIP_ER_RENAME, errno); +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); if (reopen_on_error) { /* ignore errors, since we're already in an error case */ - za->zp = fopen(za->zn, "rb"); +#ifdef UNICODE + za->zp = _wfopen(za->zn, L"rb"); +#else + za->zp = fopen(za->zn, "rb"); +#endif } return -1; } @@ -636,19 +665,35 @@ _zip_changed(struct zip *za, int *survivorsp) } +#ifdef UNICODE +static wchar_t * +#else static char * +#endif _zip_create_temp_output(struct zip *za, FILE **outp) { - char *temp; +#ifdef UNICODE + wchar_t *temp; +#else + char *temp; +#endif int tfd; FILE *tfp; - if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { +#ifdef UNICODE + if ((temp=(wchar_t *)malloc((wcslen(za->zn)+8)*2)) == NULL) { +#else + if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) { +#endif _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } - sprintf(temp, "%s.XXXXXX", za->zn); +#ifdef UNICODE + swprintf(temp, L"%s.XXXXXX", za->zn); +#else + sprintf(temp, "%s.XXXXXX", za->zn); +#endif if ((tfd=mkstemp(temp)) == -1) { _zip_error_set(&za->error, ZIP_ER_TMPOPEN, errno); @@ -661,7 +706,11 @@ _zip_create_temp_output(struct zip *za, FILE **outp) #ifndef _WIN32 close(tfd); #endif +#ifdef UNICODE + _wremove(temp); +#else remove(temp); +#endif free(temp); return NULL; } diff --git a/ext/libzip/zip_open.c b/ext/libzip/zip_open.c index a65974df9..19227cfc2 100644 --- a/ext/libzip/zip_open.c +++ b/ext/libzip/zip_open.c @@ -43,11 +43,16 @@ #include "zipint.h" static void set_error(int *, struct zip_error *, int); -static struct zip *_zip_allocate_new(const char *, int *); static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); static void _zip_check_torrentzip(struct zip *); static struct zip_cdir *_zip_find_central_dir(FILE *, int, int *, off_t); +#ifdef UNICODE +static struct zip *_zip_allocate_new(const wchar_t *, int *); +static int _zip_file_exists(const wchar_t *, int, int *); +#else +static struct zip *_zip_allocate_new(const char *, int *); static int _zip_file_exists(const char *, int, int *); +#endif static int _zip_headercomp(struct zip_dirent *, int, struct zip_dirent *, int); static unsigned char *_zip_memmem(const unsigned char *, int, @@ -56,9 +61,12 @@ static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *, int, int, struct zip_error *); - ZIP_EXTERN struct zip * +#ifdef UNICODE +zip_open(const wchar_t *fn, int flags, int *zep) +#else zip_open(const char *fn, int flags, int *zep) +#endif { FILE *fp; struct zip *za; @@ -75,8 +83,12 @@ zip_open(const char *fn, int flags, int *zep) break; } - if ((fp=fopen(fn, "rb")) == NULL) { - set_error(zep, NULL, ZIP_ER_OPEN); +#ifdef UNICODE + if ((fp=_wfopen(fn, L"rb")) == NULL) { +#else + if ((fp=fopen(fn, "rb")) == NULL) { +#endif + set_error(zep, NULL, ZIP_ER_OPEN); return NULL; } @@ -417,7 +429,11 @@ _zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, static struct zip * +#ifdef _UNICODE +_zip_allocate_new(const wchar_t *fn, int *zep) +#else _zip_allocate_new(const char *fn, int *zep) +#endif { struct zip *za; struct zip_error error; @@ -426,8 +442,12 @@ _zip_allocate_new(const char *fn, int *zep) set_error(zep, &error, 0); return NULL; } - - za->zn = strdup(fn); + +#ifdef UNICODE + za->zn = _wcsdup(fn); +#else + za->zn = strdup(fn); +#endif if (!za->zn) { _zip_free(za); set_error(zep, NULL, ZIP_ER_MEMORY); @@ -439,16 +459,27 @@ _zip_allocate_new(const char *fn, int *zep) static int +#ifdef UNICODE +_zip_file_exists(const wchar_t *fn, int flags, int *zep) +#else _zip_file_exists(const char *fn, int flags, int *zep) +#endif { - struct stat st; - +#ifdef UNICODE + struct _stat st; +#else + struct stat st; +#endif if (fn == NULL) { set_error(zep, NULL, ZIP_ER_INVAL); return -1; } - if (stat(fn, &st) != 0) { +#ifdef UNICODE + if (_wstat(fn, &st) != 0) { +#else + if (stat(fn, &st) != 0) { +#endif if (flags & ZIP_CREATE) return 0; else { diff --git a/ext/libzip/zipint.h b/ext/libzip/zipint.h index 287fd1555..f7e3c34b8 100644 --- a/ext/libzip/zipint.h +++ b/ext/libzip/zipint.h @@ -54,14 +54,18 @@ typedef int mode_t; #include "config.h" #ifndef HAVE_MKSTEMP +#ifdef UNICODE +int _zip_mkstemp(wchar_t *); +#else int _zip_mkstemp(char *); +#endif #define mkstemp _zip_mkstemp #endif #ifdef HAVE_MOVEFILEEXA #include #define _zip_rename(s, t) \ - (!MoveFileExA((s), (t), \ + (!MoveFileEx((s), (t), \ MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING)) #else #define _zip_rename rename @@ -121,7 +125,11 @@ struct zip_error { /* zip archive, part of API */ struct zip { - char *zn; /* file name */ +#ifdef UNICODE + wchar_t *zn; /* file name */ +#else + char *zn; /* file name */ +#endif FILE *zp; /* file */ struct zip_error error; /* error information */ diff --git a/native.vcxproj b/native.vcxproj index 8b11cac10..da336fa7e 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -171,6 +171,7 @@ + @@ -206,6 +207,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index fe60f0201..2c87de725 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -19,6 +19,9 @@ ui + + ext\libzip + @@ -295,6 +298,9 @@ ext\libzip + + ext\libzip +