1275793eaSopenharmony_ci/*
2275793eaSopenharmony_ci   miniunz.c
3275793eaSopenharmony_ci   Version 1.1, February 14h, 2010
4275793eaSopenharmony_ci   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
5275793eaSopenharmony_ci
6275793eaSopenharmony_ci         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
7275793eaSopenharmony_ci
8275793eaSopenharmony_ci         Modifications of Unzip for Zip64
9275793eaSopenharmony_ci         Copyright (C) 2007-2008 Even Rouault
10275793eaSopenharmony_ci
11275793eaSopenharmony_ci         Modifications for Zip64 support on both zip and unzip
12275793eaSopenharmony_ci         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
13275793eaSopenharmony_ci*/
14275793eaSopenharmony_ci
15275793eaSopenharmony_ci#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
16275793eaSopenharmony_ci        #ifndef __USE_FILE_OFFSET64
17275793eaSopenharmony_ci                #define __USE_FILE_OFFSET64
18275793eaSopenharmony_ci        #endif
19275793eaSopenharmony_ci        #ifndef __USE_LARGEFILE64
20275793eaSopenharmony_ci                #define __USE_LARGEFILE64
21275793eaSopenharmony_ci        #endif
22275793eaSopenharmony_ci        #ifndef _LARGEFILE64_SOURCE
23275793eaSopenharmony_ci                #define _LARGEFILE64_SOURCE
24275793eaSopenharmony_ci        #endif
25275793eaSopenharmony_ci        #ifndef _FILE_OFFSET_BIT
26275793eaSopenharmony_ci                #define _FILE_OFFSET_BIT 64
27275793eaSopenharmony_ci        #endif
28275793eaSopenharmony_ci#endif
29275793eaSopenharmony_ci
30275793eaSopenharmony_ci#if defined(__APPLE__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
31275793eaSopenharmony_ci// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
32275793eaSopenharmony_ci#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
33275793eaSopenharmony_ci#define FTELLO_FUNC(stream) ftello(stream)
34275793eaSopenharmony_ci#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
35275793eaSopenharmony_ci#else
36275793eaSopenharmony_ci#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
37275793eaSopenharmony_ci#define FTELLO_FUNC(stream) ftello64(stream)
38275793eaSopenharmony_ci#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
39275793eaSopenharmony_ci#endif
40275793eaSopenharmony_ci
41275793eaSopenharmony_ci
42275793eaSopenharmony_ci#include <stdio.h>
43275793eaSopenharmony_ci#include <stdlib.h>
44275793eaSopenharmony_ci#include <string.h>
45275793eaSopenharmony_ci#include <time.h>
46275793eaSopenharmony_ci#include <errno.h>
47275793eaSopenharmony_ci#include <fcntl.h>
48275793eaSopenharmony_ci#include <sys/stat.h>
49275793eaSopenharmony_ci
50275793eaSopenharmony_ci#ifdef _WIN32
51275793eaSopenharmony_ci# include <direct.h>
52275793eaSopenharmony_ci# include <io.h>
53275793eaSopenharmony_ci#else
54275793eaSopenharmony_ci# include <unistd.h>
55275793eaSopenharmony_ci# include <utime.h>
56275793eaSopenharmony_ci#endif
57275793eaSopenharmony_ci
58275793eaSopenharmony_ci
59275793eaSopenharmony_ci#include "unzip.h"
60275793eaSopenharmony_ci
61275793eaSopenharmony_ci#define CASESENSITIVITY (0)
62275793eaSopenharmony_ci#define WRITEBUFFERSIZE (8192)
63275793eaSopenharmony_ci#define MAXFILENAME (256)
64275793eaSopenharmony_ci
65275793eaSopenharmony_ci#ifdef _WIN32
66275793eaSopenharmony_ci#define USEWIN32IOAPI
67275793eaSopenharmony_ci#include "iowin32.h"
68275793eaSopenharmony_ci#endif
69275793eaSopenharmony_ci/*
70275793eaSopenharmony_ci  mini unzip, demo of unzip package
71275793eaSopenharmony_ci
72275793eaSopenharmony_ci  usage :
73275793eaSopenharmony_ci  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
74275793eaSopenharmony_ci
75275793eaSopenharmony_ci  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
76275793eaSopenharmony_ci    if it exists
77275793eaSopenharmony_ci*/
78275793eaSopenharmony_ci
79275793eaSopenharmony_ci
80275793eaSopenharmony_ci/* change_file_date : change the date/time of a file
81275793eaSopenharmony_ci    filename : the filename of the file where date/time must be modified
82275793eaSopenharmony_ci    dosdate : the new date at the MSDOS format (4 bytes)
83275793eaSopenharmony_ci    tmu_date : the SAME new date at the tm_unz format */
84275793eaSopenharmony_cistatic void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date)
85275793eaSopenharmony_ci{
86275793eaSopenharmony_ci#ifdef _WIN32
87275793eaSopenharmony_ci  HANDLE hFile;
88275793eaSopenharmony_ci  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
89275793eaSopenharmony_ci
90275793eaSopenharmony_ci  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
91275793eaSopenharmony_ci                      0,NULL,OPEN_EXISTING,0,NULL);
92275793eaSopenharmony_ci  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
93275793eaSopenharmony_ci  DosDateTimeToFileTime((WORD)(dosdate >> 16),(WORD)dosdate,&ftLocal);
94275793eaSopenharmony_ci  LocalFileTimeToFileTime(&ftLocal,&ftm);
95275793eaSopenharmony_ci  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
96275793eaSopenharmony_ci  CloseHandle(hFile);
97275793eaSopenharmony_ci#else
98275793eaSopenharmony_ci#if defined(unix) || defined(__APPLE__)
99275793eaSopenharmony_ci  (void)dosdate;
100275793eaSopenharmony_ci  struct utimbuf ut;
101275793eaSopenharmony_ci  struct tm newdate;
102275793eaSopenharmony_ci  newdate.tm_sec = tmu_date.tm_sec;
103275793eaSopenharmony_ci  newdate.tm_min = tmu_date.tm_min;
104275793eaSopenharmony_ci  newdate.tm_hour = tmu_date.tm_hour;
105275793eaSopenharmony_ci  newdate.tm_mday = tmu_date.tm_mday;
106275793eaSopenharmony_ci  newdate.tm_mon = tmu_date.tm_mon;
107275793eaSopenharmony_ci  if (tmu_date.tm_year > 1900)
108275793eaSopenharmony_ci  {
109275793eaSopenharmony_ci      newdate.tm_year = tmu_date.tm_year - 1900;
110275793eaSopenharmony_ci  }
111275793eaSopenharmony_ci  else
112275793eaSopenharmony_ci  {
113275793eaSopenharmony_ci      newdate.tm_year = tmu_date.tm_year ;
114275793eaSopenharmony_ci  }
115275793eaSopenharmony_ci  newdate.tm_isdst = -1;
116275793eaSopenharmony_ci
117275793eaSopenharmony_ci  ut.actime = ut.modtime = mktime(&newdate);
118275793eaSopenharmony_ci  utime(filename,&ut);
119275793eaSopenharmony_ci#else
120275793eaSopenharmony_ci  (void)filename;
121275793eaSopenharmony_ci  (void)dosdate;
122275793eaSopenharmony_ci  (void)tmu_date;
123275793eaSopenharmony_ci#endif
124275793eaSopenharmony_ci#endif
125275793eaSopenharmony_ci}
126275793eaSopenharmony_ci
127275793eaSopenharmony_ci
128275793eaSopenharmony_ci/* mymkdir and change_file_date are not 100 % portable
129275793eaSopenharmony_ci   As I don't know well Unix, I wait feedback for the unix portion */
130275793eaSopenharmony_ci
131275793eaSopenharmony_cistatic int mymkdir(const char* dirname)
132275793eaSopenharmony_ci{
133275793eaSopenharmony_ci    int ret = 0;
134275793eaSopenharmony_ci#ifdef _WIN32
135275793eaSopenharmony_ci    ret = _mkdir(dirname);
136275793eaSopenharmony_ci#elif unix
137275793eaSopenharmony_ci    ret = mkdir (dirname,0775);
138275793eaSopenharmony_ci#elif __APPLE__
139275793eaSopenharmony_ci    ret = mkdir (dirname,0775);
140275793eaSopenharmony_ci#else
141275793eaSopenharmony_ci    (void)dirname;
142275793eaSopenharmony_ci#endif
143275793eaSopenharmony_ci    return ret;
144275793eaSopenharmony_ci}
145275793eaSopenharmony_ci
146275793eaSopenharmony_cistatic int makedir(const char *newdir)
147275793eaSopenharmony_ci{
148275793eaSopenharmony_ci  char *buffer ;
149275793eaSopenharmony_ci  char *p;
150275793eaSopenharmony_ci  size_t len = strlen(newdir);
151275793eaSopenharmony_ci
152275793eaSopenharmony_ci  if (len == 0)
153275793eaSopenharmony_ci  {
154275793eaSopenharmony_ci    return 0;
155275793eaSopenharmony_ci  }
156275793eaSopenharmony_ci
157275793eaSopenharmony_ci  buffer = (char*)malloc(len+1);
158275793eaSopenharmony_ci  if (buffer==NULL)
159275793eaSopenharmony_ci  {
160275793eaSopenharmony_ci        printf("Error allocating memory\n");
161275793eaSopenharmony_ci        return UNZ_INTERNALERROR;
162275793eaSopenharmony_ci  }
163275793eaSopenharmony_ci  strcpy(buffer,newdir);
164275793eaSopenharmony_ci
165275793eaSopenharmony_ci  if (buffer[len-1] == '/') {
166275793eaSopenharmony_ci    buffer[len-1] = '\0';
167275793eaSopenharmony_ci  }
168275793eaSopenharmony_ci  if (mymkdir(buffer) == 0)
169275793eaSopenharmony_ci  {
170275793eaSopenharmony_ci      free(buffer);
171275793eaSopenharmony_ci      return 1;
172275793eaSopenharmony_ci  }
173275793eaSopenharmony_ci
174275793eaSopenharmony_ci  p = buffer+1;
175275793eaSopenharmony_ci  while (1)
176275793eaSopenharmony_ci  {
177275793eaSopenharmony_ci      char hold;
178275793eaSopenharmony_ci
179275793eaSopenharmony_ci      while(*p && *p != '\\' && *p != '/')
180275793eaSopenharmony_ci      {
181275793eaSopenharmony_ci        p++;
182275793eaSopenharmony_ci      }
183275793eaSopenharmony_ci      hold = *p;
184275793eaSopenharmony_ci      *p = 0;
185275793eaSopenharmony_ci      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
186275793eaSopenharmony_ci      {
187275793eaSopenharmony_ci          printf("couldn't create directory %s\n",buffer);
188275793eaSopenharmony_ci          free(buffer);
189275793eaSopenharmony_ci          return 0;
190275793eaSopenharmony_ci      }
191275793eaSopenharmony_ci      if (hold == 0)
192275793eaSopenharmony_ci      {
193275793eaSopenharmony_ci        break;
194275793eaSopenharmony_ci      }
195275793eaSopenharmony_ci      *p++ = hold;
196275793eaSopenharmony_ci  }
197275793eaSopenharmony_ci  free(buffer);
198275793eaSopenharmony_ci  return 1;
199275793eaSopenharmony_ci}
200275793eaSopenharmony_ci
201275793eaSopenharmony_cistatic void do_banner(void)
202275793eaSopenharmony_ci{
203275793eaSopenharmony_ci    printf("MiniUnz 1.1, demo of zLib + Unz package written by Gilles Vollant\n");
204275793eaSopenharmony_ci    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
205275793eaSopenharmony_ci}
206275793eaSopenharmony_ci
207275793eaSopenharmony_cistatic void do_help(void)
208275793eaSopenharmony_ci{
209275793eaSopenharmony_ci    printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
210275793eaSopenharmony_ci           "  -e  Extract without pathname (junk paths)\n" \
211275793eaSopenharmony_ci           "  -x  Extract with pathname\n" \
212275793eaSopenharmony_ci           "  -v  list files\n" \
213275793eaSopenharmony_ci           "  -l  list files\n" \
214275793eaSopenharmony_ci           "  -d  directory to extract into\n" \
215275793eaSopenharmony_ci           "  -o  overwrite files without prompting\n" \
216275793eaSopenharmony_ci           "  -p  extract encrypted file using password\n\n");
217275793eaSopenharmony_ci}
218275793eaSopenharmony_ci
219275793eaSopenharmony_cistatic void Display64BitsSize(ZPOS64_T n, int size_char)
220275793eaSopenharmony_ci{
221275793eaSopenharmony_ci  /* to avoid compatibility problem , we do here the conversion */
222275793eaSopenharmony_ci  char number[21];
223275793eaSopenharmony_ci  int offset=19;
224275793eaSopenharmony_ci  int pos_string = 19;
225275793eaSopenharmony_ci  number[20]=0;
226275793eaSopenharmony_ci  for (;;)
227275793eaSopenharmony_ci  {
228275793eaSopenharmony_ci      number[offset]=(char)((n%10)+'0');
229275793eaSopenharmony_ci      if (number[offset] != '0')
230275793eaSopenharmony_ci      {
231275793eaSopenharmony_ci        pos_string=offset;
232275793eaSopenharmony_ci      }
233275793eaSopenharmony_ci      n/=10;
234275793eaSopenharmony_ci      if (offset==0)
235275793eaSopenharmony_ci      {
236275793eaSopenharmony_ci        break;
237275793eaSopenharmony_ci      }
238275793eaSopenharmony_ci      offset--;
239275793eaSopenharmony_ci  }
240275793eaSopenharmony_ci  {
241275793eaSopenharmony_ci      int size_display_string = 19-pos_string;
242275793eaSopenharmony_ci      while (size_char > size_display_string)
243275793eaSopenharmony_ci      {
244275793eaSopenharmony_ci          size_char--;
245275793eaSopenharmony_ci          printf(" ");
246275793eaSopenharmony_ci      }
247275793eaSopenharmony_ci  }
248275793eaSopenharmony_ci
249275793eaSopenharmony_ci  printf("%s",&number[pos_string]);
250275793eaSopenharmony_ci}
251275793eaSopenharmony_ci
252275793eaSopenharmony_cistatic int do_list(unzFile uf)
253275793eaSopenharmony_ci{
254275793eaSopenharmony_ci    uLong i;
255275793eaSopenharmony_ci    unz_global_info64 gi;
256275793eaSopenharmony_ci    int err;
257275793eaSopenharmony_ci
258275793eaSopenharmony_ci    err = unzGetGlobalInfo64(uf,&gi);
259275793eaSopenharmony_ci    if (err != UNZ_OK)
260275793eaSopenharmony_ci    {
261275793eaSopenharmony_ci        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
262275793eaSopenharmony_ci    }
263275793eaSopenharmony_ci    printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");
264275793eaSopenharmony_ci    printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");
265275793eaSopenharmony_ci    for (i = 0;i < gi.number_entry; i++)
266275793eaSopenharmony_ci    {
267275793eaSopenharmony_ci        char filename_inzip[256];
268275793eaSopenharmony_ci        unz_file_info64 file_info;
269275793eaSopenharmony_ci        uLong ratio = 0;
270275793eaSopenharmony_ci        const char *string_method = "";
271275793eaSopenharmony_ci        char charCrypt = ' ';
272275793eaSopenharmony_ci        err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
273275793eaSopenharmony_ci        if (err != UNZ_OK)
274275793eaSopenharmony_ci        {
275275793eaSopenharmony_ci            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
276275793eaSopenharmony_ci            break;
277275793eaSopenharmony_ci        }
278275793eaSopenharmony_ci        if (file_info.uncompressed_size > 0)
279275793eaSopenharmony_ci            ratio = (uLong)((file_info.compressed_size*100) / file_info.uncompressed_size);
280275793eaSopenharmony_ci
281275793eaSopenharmony_ci        /* display a '*' if the file is encrypted */
282275793eaSopenharmony_ci        if ((file_info.flag & 1) != 0)
283275793eaSopenharmony_ci        {
284275793eaSopenharmony_ci            charCrypt = '*';
285275793eaSopenharmony_ci        }
286275793eaSopenharmony_ci
287275793eaSopenharmony_ci        if (file_info.compression_method == 0)
288275793eaSopenharmony_ci        {
289275793eaSopenharmony_ci            string_method = "Stored";
290275793eaSopenharmony_ci        }
291275793eaSopenharmony_ci        else
292275793eaSopenharmony_ci        if (file_info.compression_method == Z_DEFLATED)
293275793eaSopenharmony_ci        {
294275793eaSopenharmony_ci            uInt iLevel=(uInt)((file_info.flag & 0x6) / 2);
295275793eaSopenharmony_ci            if (iLevel == 0)
296275793eaSopenharmony_ci            {
297275793eaSopenharmony_ci                string_method = "Defl:N";
298275793eaSopenharmony_ci            }
299275793eaSopenharmony_ci            else if (iLevel == 1)
300275793eaSopenharmony_ci            {
301275793eaSopenharmony_ci              string_method = "Defl:X";
302275793eaSopenharmony_ci            }
303275793eaSopenharmony_ci            else if ((iLevel == 2) || (iLevel == 3))
304275793eaSopenharmony_ci            {
305275793eaSopenharmony_ci              string_method = "Defl:F"; /* 2:fast , 3 : extra fast*/
306275793eaSopenharmony_ci            }
307275793eaSopenharmony_ci        }
308275793eaSopenharmony_ci        else
309275793eaSopenharmony_ci        if (file_info.compression_method == Z_BZIP2ED)
310275793eaSopenharmony_ci        {
311275793eaSopenharmony_ci            string_method = "BZip2 ";
312275793eaSopenharmony_ci        }
313275793eaSopenharmony_ci        else
314275793eaSopenharmony_ci        {
315275793eaSopenharmony_ci            string_method = "Unkn. ";
316275793eaSopenharmony_ci        }
317275793eaSopenharmony_ci
318275793eaSopenharmony_ci        Display64BitsSize(file_info.uncompressed_size,7);
319275793eaSopenharmony_ci        printf("  %6s%c",string_method,charCrypt);
320275793eaSopenharmony_ci        Display64BitsSize(file_info.compressed_size,7);
321275793eaSopenharmony_ci        printf(" %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
322275793eaSopenharmony_ci                ratio,
323275793eaSopenharmony_ci                (uLong)file_info.tmu_date.tm_mon + 1,
324275793eaSopenharmony_ci                (uLong)file_info.tmu_date.tm_mday,
325275793eaSopenharmony_ci                (uLong)file_info.tmu_date.tm_year % 100,
326275793eaSopenharmony_ci                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
327275793eaSopenharmony_ci                (uLong)file_info.crc,filename_inzip);
328275793eaSopenharmony_ci        if (gi.number_entry > (i+1))
329275793eaSopenharmony_ci        {
330275793eaSopenharmony_ci            err = unzGoToNextFile(uf);
331275793eaSopenharmony_ci            if (err != UNZ_OK)
332275793eaSopenharmony_ci            {
333275793eaSopenharmony_ci                printf("error %d with zipfile in unzGoToNextFile\n",err);
334275793eaSopenharmony_ci                break;
335275793eaSopenharmony_ci            }
336275793eaSopenharmony_ci        }
337275793eaSopenharmony_ci    }
338275793eaSopenharmony_ci
339275793eaSopenharmony_ci    return 0;
340275793eaSopenharmony_ci}
341275793eaSopenharmony_ci
342275793eaSopenharmony_ci
343275793eaSopenharmony_cistatic int do_extract_currentfile(unzFile uf,
344275793eaSopenharmony_ci                                  const int* popt_extract_without_path,
345275793eaSopenharmony_ci                                  int* popt_overwrite,
346275793eaSopenharmony_ci                                  const char* password)
347275793eaSopenharmony_ci{
348275793eaSopenharmony_ci    char filename_inzip[256];
349275793eaSopenharmony_ci    char* filename_withoutpath;
350275793eaSopenharmony_ci    char* p;
351275793eaSopenharmony_ci    int err = UNZ_OK;
352275793eaSopenharmony_ci    FILE *fout = NULL;
353275793eaSopenharmony_ci    void* buf;
354275793eaSopenharmony_ci    uInt size_buf;
355275793eaSopenharmony_ci
356275793eaSopenharmony_ci    unz_file_info64 file_info;
357275793eaSopenharmony_ci    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
358275793eaSopenharmony_ci
359275793eaSopenharmony_ci    if (err != UNZ_OK)
360275793eaSopenharmony_ci    {
361275793eaSopenharmony_ci        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
362275793eaSopenharmony_ci        return err;
363275793eaSopenharmony_ci    }
364275793eaSopenharmony_ci
365275793eaSopenharmony_ci    size_buf = WRITEBUFFERSIZE;
366275793eaSopenharmony_ci    buf = (void*)malloc(size_buf);
367275793eaSopenharmony_ci    if (buf == NULL)
368275793eaSopenharmony_ci    {
369275793eaSopenharmony_ci        printf("Error allocating memory\n");
370275793eaSopenharmony_ci        return UNZ_INTERNALERROR;
371275793eaSopenharmony_ci    }
372275793eaSopenharmony_ci
373275793eaSopenharmony_ci    p = filename_withoutpath = filename_inzip;
374275793eaSopenharmony_ci    while ((*p) != '\0')
375275793eaSopenharmony_ci    {
376275793eaSopenharmony_ci        if (((*p) == '/') || ((*p) == '\\'))
377275793eaSopenharmony_ci        {
378275793eaSopenharmony_ci            filename_withoutpath = p+1;
379275793eaSopenharmony_ci        }
380275793eaSopenharmony_ci        p++;
381275793eaSopenharmony_ci    }
382275793eaSopenharmony_ci
383275793eaSopenharmony_ci    if ((*filename_withoutpath) == '\0')
384275793eaSopenharmony_ci    {
385275793eaSopenharmony_ci        if ((*popt_extract_without_path) == 0)
386275793eaSopenharmony_ci        {
387275793eaSopenharmony_ci            printf("creating directory: %s\n",filename_inzip);
388275793eaSopenharmony_ci            mymkdir(filename_inzip);
389275793eaSopenharmony_ci        }
390275793eaSopenharmony_ci    }
391275793eaSopenharmony_ci    else
392275793eaSopenharmony_ci    {
393275793eaSopenharmony_ci        const char* write_filename;
394275793eaSopenharmony_ci        int skip = 0;
395275793eaSopenharmony_ci
396275793eaSopenharmony_ci        if ((*popt_extract_without_path) == 0)
397275793eaSopenharmony_ci        {
398275793eaSopenharmony_ci            write_filename = filename_inzip;
399275793eaSopenharmony_ci        }
400275793eaSopenharmony_ci        else
401275793eaSopenharmony_ci        {
402275793eaSopenharmony_ci            write_filename = filename_withoutpath;
403275793eaSopenharmony_ci        }
404275793eaSopenharmony_ci
405275793eaSopenharmony_ci        if (write_filename[0] != '\0')
406275793eaSopenharmony_ci        {
407275793eaSopenharmony_ci            const char* relative_check = write_filename;
408275793eaSopenharmony_ci            while (relative_check[1] != '\0')
409275793eaSopenharmony_ci            {
410275793eaSopenharmony_ci                if (relative_check[0] == '.' && relative_check[1] == '.')
411275793eaSopenharmony_ci                {
412275793eaSopenharmony_ci                    write_filename = relative_check;
413275793eaSopenharmony_ci                }
414275793eaSopenharmony_ci                relative_check++;
415275793eaSopenharmony_ci            }
416275793eaSopenharmony_ci        }
417275793eaSopenharmony_ci
418275793eaSopenharmony_ci        while (write_filename[0] == '/' || write_filename[0] == '.')
419275793eaSopenharmony_ci        {
420275793eaSopenharmony_ci            write_filename++;
421275793eaSopenharmony_ci        }
422275793eaSopenharmony_ci
423275793eaSopenharmony_ci        err = unzOpenCurrentFilePassword(uf,password);
424275793eaSopenharmony_ci        if (err != UNZ_OK)
425275793eaSopenharmony_ci        {
426275793eaSopenharmony_ci            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
427275793eaSopenharmony_ci        }
428275793eaSopenharmony_ci
429275793eaSopenharmony_ci        if (((*popt_overwrite) == 0) && (err == UNZ_OK))
430275793eaSopenharmony_ci        {
431275793eaSopenharmony_ci            char rep = 0;
432275793eaSopenharmony_ci            FILE* ftestexist;
433275793eaSopenharmony_ci            ftestexist = FOPEN_FUNC(write_filename,"rb");
434275793eaSopenharmony_ci            if (ftestexist != NULL)
435275793eaSopenharmony_ci            {
436275793eaSopenharmony_ci                fclose(ftestexist);
437275793eaSopenharmony_ci                do
438275793eaSopenharmony_ci                {
439275793eaSopenharmony_ci                    char answer[128];
440275793eaSopenharmony_ci                    int ret;
441275793eaSopenharmony_ci
442275793eaSopenharmony_ci                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
443275793eaSopenharmony_ci                    ret = scanf("%1s",answer);
444275793eaSopenharmony_ci                    if (ret != 1)
445275793eaSopenharmony_ci                    {
446275793eaSopenharmony_ci                       exit(EXIT_FAILURE);
447275793eaSopenharmony_ci                    }
448275793eaSopenharmony_ci                    rep = answer[0] ;
449275793eaSopenharmony_ci                    if ((rep >= 'a') && (rep <= 'z'))
450275793eaSopenharmony_ci                    {
451275793eaSopenharmony_ci                        rep -= 0x20;
452275793eaSopenharmony_ci                    }
453275793eaSopenharmony_ci                }
454275793eaSopenharmony_ci                while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
455275793eaSopenharmony_ci            }
456275793eaSopenharmony_ci
457275793eaSopenharmony_ci            if (rep == 'N')
458275793eaSopenharmony_ci            {
459275793eaSopenharmony_ci                skip = 1;
460275793eaSopenharmony_ci            }
461275793eaSopenharmony_ci
462275793eaSopenharmony_ci            if (rep == 'A')
463275793eaSopenharmony_ci            {
464275793eaSopenharmony_ci                *popt_overwrite=1;
465275793eaSopenharmony_ci            }
466275793eaSopenharmony_ci        }
467275793eaSopenharmony_ci
468275793eaSopenharmony_ci        if ((skip == 0) && (err == UNZ_OK))
469275793eaSopenharmony_ci        {
470275793eaSopenharmony_ci            fout=FOPEN_FUNC(write_filename,"wb");
471275793eaSopenharmony_ci            /* some zipfile don't contain directory alone before file */
472275793eaSopenharmony_ci            if ((fout == NULL) && ((*popt_extract_without_path) == 0) &&
473275793eaSopenharmony_ci                                (filename_withoutpath!=(char*)filename_inzip))
474275793eaSopenharmony_ci            {
475275793eaSopenharmony_ci                char c=*(filename_withoutpath - 1);
476275793eaSopenharmony_ci                *(filename_withoutpath-1) = '\0';
477275793eaSopenharmony_ci                makedir(write_filename);
478275793eaSopenharmony_ci                *(filename_withoutpath-1) = c;
479275793eaSopenharmony_ci                fout=FOPEN_FUNC(write_filename,"wb");
480275793eaSopenharmony_ci            }
481275793eaSopenharmony_ci
482275793eaSopenharmony_ci            if (fout == NULL)
483275793eaSopenharmony_ci            {
484275793eaSopenharmony_ci                printf("error opening %s\n",write_filename);
485275793eaSopenharmony_ci            }
486275793eaSopenharmony_ci        }
487275793eaSopenharmony_ci
488275793eaSopenharmony_ci        if (fout != NULL)
489275793eaSopenharmony_ci        {
490275793eaSopenharmony_ci            printf(" extracting: %s\n",write_filename);
491275793eaSopenharmony_ci
492275793eaSopenharmony_ci            do
493275793eaSopenharmony_ci            {
494275793eaSopenharmony_ci                err = unzReadCurrentFile(uf,buf,size_buf);
495275793eaSopenharmony_ci                if (err < 0)
496275793eaSopenharmony_ci                {
497275793eaSopenharmony_ci                    printf("error %d with zipfile in unzReadCurrentFile\n",err);
498275793eaSopenharmony_ci                    break;
499275793eaSopenharmony_ci                }
500275793eaSopenharmony_ci                if (err > 0)
501275793eaSopenharmony_ci                    if (fwrite(buf,(unsigned)err,1,fout) != 1)
502275793eaSopenharmony_ci                    {
503275793eaSopenharmony_ci                        printf("error in writing extracted file\n");
504275793eaSopenharmony_ci                        err=UNZ_ERRNO;
505275793eaSopenharmony_ci                        break;
506275793eaSopenharmony_ci                    }
507275793eaSopenharmony_ci            }
508275793eaSopenharmony_ci            while (err > 0);
509275793eaSopenharmony_ci            if (fout)
510275793eaSopenharmony_ci            {
511275793eaSopenharmony_ci                fclose(fout);
512275793eaSopenharmony_ci            }
513275793eaSopenharmony_ci
514275793eaSopenharmony_ci            if (err == 0)
515275793eaSopenharmony_ci            {
516275793eaSopenharmony_ci                change_file_date(write_filename,file_info.dosDate,
517275793eaSopenharmony_ci                                 file_info.tmu_date);
518275793eaSopenharmony_ci            }
519275793eaSopenharmony_ci        }
520275793eaSopenharmony_ci
521275793eaSopenharmony_ci        if (err == UNZ_OK)
522275793eaSopenharmony_ci        {
523275793eaSopenharmony_ci            err = unzCloseCurrentFile (uf);
524275793eaSopenharmony_ci            if (err != UNZ_OK)
525275793eaSopenharmony_ci            {
526275793eaSopenharmony_ci                printf("error %d with zipfile in unzCloseCurrentFile\n",err);
527275793eaSopenharmony_ci            }
528275793eaSopenharmony_ci        }
529275793eaSopenharmony_ci        else
530275793eaSopenharmony_ci        {
531275793eaSopenharmony_ci            unzCloseCurrentFile(uf); /* don't lose the error */
532275793eaSopenharmony_ci        }
533275793eaSopenharmony_ci    }
534275793eaSopenharmony_ci
535275793eaSopenharmony_ci    free(buf);
536275793eaSopenharmony_ci    return err;
537275793eaSopenharmony_ci}
538275793eaSopenharmony_ci
539275793eaSopenharmony_ci
540275793eaSopenharmony_cistatic int do_extract(unzFile uf, int opt_extract_without_path, int opt_overwrite, const char* password)
541275793eaSopenharmony_ci{
542275793eaSopenharmony_ci    uLong i;
543275793eaSopenharmony_ci    unz_global_info64 gi;
544275793eaSopenharmony_ci    int err;
545275793eaSopenharmony_ci
546275793eaSopenharmony_ci    err = unzGetGlobalInfo64(uf,&gi);
547275793eaSopenharmony_ci    if (err != UNZ_OK)
548275793eaSopenharmony_ci    {
549275793eaSopenharmony_ci        printf("error %d with zipfile in unzGetGlobalInfo \n",err);
550275793eaSopenharmony_ci    }
551275793eaSopenharmony_ci
552275793eaSopenharmony_ci    for (i = 0;i < gi.number_entry; i++)
553275793eaSopenharmony_ci    {
554275793eaSopenharmony_ci        if (do_extract_currentfile(uf,&opt_extract_without_path,
555275793eaSopenharmony_ci                                      &opt_overwrite,
556275793eaSopenharmony_ci                                      password) != UNZ_OK)
557275793eaSopenharmony_ci            break;
558275793eaSopenharmony_ci
559275793eaSopenharmony_ci        if (gi.number_entry > (i+1))
560275793eaSopenharmony_ci        {
561275793eaSopenharmony_ci            err = unzGoToNextFile(uf);
562275793eaSopenharmony_ci            if (err != UNZ_OK)
563275793eaSopenharmony_ci            {
564275793eaSopenharmony_ci                printf("error %d with zipfile in unzGoToNextFile\n",err);
565275793eaSopenharmony_ci                break;
566275793eaSopenharmony_ci            }
567275793eaSopenharmony_ci        }
568275793eaSopenharmony_ci    }
569275793eaSopenharmony_ci
570275793eaSopenharmony_ci    return 0;
571275793eaSopenharmony_ci}
572275793eaSopenharmony_ci
573275793eaSopenharmony_cistatic int do_extract_onefile(unzFile uf,
574275793eaSopenharmony_ci                              const char* filename,
575275793eaSopenharmony_ci                              int opt_extract_without_path,
576275793eaSopenharmony_ci                              int opt_overwrite,
577275793eaSopenharmony_ci                              const char* password)
578275793eaSopenharmony_ci{
579275793eaSopenharmony_ci    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
580275793eaSopenharmony_ci    {
581275793eaSopenharmony_ci        printf("file %s not found in the zipfile\n",filename);
582275793eaSopenharmony_ci        return 2;
583275793eaSopenharmony_ci    }
584275793eaSopenharmony_ci
585275793eaSopenharmony_ci    if (do_extract_currentfile(uf,&opt_extract_without_path,
586275793eaSopenharmony_ci                                      &opt_overwrite,
587275793eaSopenharmony_ci                                      password) == UNZ_OK)
588275793eaSopenharmony_ci    {
589275793eaSopenharmony_ci        return 0;
590275793eaSopenharmony_ci    }
591275793eaSopenharmony_ci    else
592275793eaSopenharmony_ci    {
593275793eaSopenharmony_ci        return 1;
594275793eaSopenharmony_ci    }
595275793eaSopenharmony_ci}
596275793eaSopenharmony_ci
597275793eaSopenharmony_ci
598275793eaSopenharmony_ciint main(int argc, char *argv[])
599275793eaSopenharmony_ci{
600275793eaSopenharmony_ci    const char *zipfilename = NULL;
601275793eaSopenharmony_ci    const char *filename_to_extract = NULL;
602275793eaSopenharmony_ci    const char *password = NULL;
603275793eaSopenharmony_ci    char filename_try[MAXFILENAME+16] = "";
604275793eaSopenharmony_ci    int i;
605275793eaSopenharmony_ci    int ret_value = 0;
606275793eaSopenharmony_ci    int opt_do_list = 0;
607275793eaSopenharmony_ci    int opt_do_extract = 1;
608275793eaSopenharmony_ci    int opt_do_extract_withoutpath = 0;
609275793eaSopenharmony_ci    int opt_overwrite = 0;
610275793eaSopenharmony_ci    int opt_extractdir = 0;
611275793eaSopenharmony_ci    const char *dirname = NULL;
612275793eaSopenharmony_ci    unzFile uf = NULL;
613275793eaSopenharmony_ci
614275793eaSopenharmony_ci    do_banner();
615275793eaSopenharmony_ci    if (argc == 1)
616275793eaSopenharmony_ci    {
617275793eaSopenharmony_ci        do_help();
618275793eaSopenharmony_ci        return 0;
619275793eaSopenharmony_ci    }
620275793eaSopenharmony_ci    else
621275793eaSopenharmony_ci    {
622275793eaSopenharmony_ci        for (i = 1;i < argc; i++)
623275793eaSopenharmony_ci        {
624275793eaSopenharmony_ci            if ((*argv[i]) == '-')
625275793eaSopenharmony_ci            {
626275793eaSopenharmony_ci                const char *p = argv[i]+1;
627275793eaSopenharmony_ci
628275793eaSopenharmony_ci                while ((*p) != '\0')
629275793eaSopenharmony_ci                {
630275793eaSopenharmony_ci                    char c = *(p++);
631275793eaSopenharmony_ci                    if ((c == 'l') || (c == 'L'))
632275793eaSopenharmony_ci                    {
633275793eaSopenharmony_ci                        opt_do_list = 1;
634275793eaSopenharmony_ci                    }
635275793eaSopenharmony_ci                    if ((c == 'v') || (c == 'V'))
636275793eaSopenharmony_ci                    {
637275793eaSopenharmony_ci                        opt_do_list = 1;
638275793eaSopenharmony_ci                    }
639275793eaSopenharmony_ci                    if ((c == 'x') || (c == 'X'))
640275793eaSopenharmony_ci                    {
641275793eaSopenharmony_ci                        opt_do_extract = 1;
642275793eaSopenharmony_ci                    }
643275793eaSopenharmony_ci                    if ((c == 'e') || (c == 'E'))
644275793eaSopenharmony_ci                    {
645275793eaSopenharmony_ci                        opt_do_extract = opt_do_extract_withoutpath = 1;
646275793eaSopenharmony_ci                    }
647275793eaSopenharmony_ci                    if ((c == 'o') || (c == 'O'))
648275793eaSopenharmony_ci                    {
649275793eaSopenharmony_ci                        opt_overwrite=1;
650275793eaSopenharmony_ci                    }
651275793eaSopenharmony_ci                    if ((c == 'd') || (c == 'D'))
652275793eaSopenharmony_ci                    {
653275793eaSopenharmony_ci                        opt_extractdir = 1;
654275793eaSopenharmony_ci                        dirname = argv[i+1];
655275793eaSopenharmony_ci                    }
656275793eaSopenharmony_ci
657275793eaSopenharmony_ci                    if (((c == 'p') || (c == 'P')) && (i+1 < argc))
658275793eaSopenharmony_ci                    {
659275793eaSopenharmony_ci                        password = argv[i+1];
660275793eaSopenharmony_ci                        i++;
661275793eaSopenharmony_ci                    }
662275793eaSopenharmony_ci                }
663275793eaSopenharmony_ci            }
664275793eaSopenharmony_ci            else
665275793eaSopenharmony_ci            {
666275793eaSopenharmony_ci                if (zipfilename == NULL)
667275793eaSopenharmony_ci                {
668275793eaSopenharmony_ci                    zipfilename = argv[i];
669275793eaSopenharmony_ci                }
670275793eaSopenharmony_ci                else if ((filename_to_extract == NULL) && (!opt_extractdir))
671275793eaSopenharmony_ci                {
672275793eaSopenharmony_ci                    filename_to_extract = argv[i];
673275793eaSopenharmony_ci                }
674275793eaSopenharmony_ci            }
675275793eaSopenharmony_ci        }
676275793eaSopenharmony_ci    }
677275793eaSopenharmony_ci
678275793eaSopenharmony_ci    if (zipfilename != NULL)
679275793eaSopenharmony_ci    {
680275793eaSopenharmony_ci
681275793eaSopenharmony_ci#        ifdef USEWIN32IOAPI
682275793eaSopenharmony_ci        zlib_filefunc64_def ffunc;
683275793eaSopenharmony_ci#        endif
684275793eaSopenharmony_ci
685275793eaSopenharmony_ci        strncpy(filename_try, zipfilename,MAXFILENAME-1);
686275793eaSopenharmony_ci        /* strncpy doesn't append the trailing NULL, of the string is too long. */
687275793eaSopenharmony_ci        filename_try[ MAXFILENAME ] = '\0';
688275793eaSopenharmony_ci
689275793eaSopenharmony_ci#        ifdef USEWIN32IOAPI
690275793eaSopenharmony_ci        fill_win32_filefunc64A(&ffunc);
691275793eaSopenharmony_ci        uf = unzOpen2_64(zipfilename,&ffunc);
692275793eaSopenharmony_ci#        else
693275793eaSopenharmony_ci        uf = unzOpen64(zipfilename);
694275793eaSopenharmony_ci#        endif
695275793eaSopenharmony_ci        if (uf == NULL)
696275793eaSopenharmony_ci        {
697275793eaSopenharmony_ci            strcat(filename_try,".zip");
698275793eaSopenharmony_ci#            ifdef USEWIN32IOAPI
699275793eaSopenharmony_ci            uf = unzOpen2_64(filename_try,&ffunc);
700275793eaSopenharmony_ci#            else
701275793eaSopenharmony_ci            uf = unzOpen64(filename_try);
702275793eaSopenharmony_ci#            endif
703275793eaSopenharmony_ci        }
704275793eaSopenharmony_ci    }
705275793eaSopenharmony_ci
706275793eaSopenharmony_ci    if (uf == NULL)
707275793eaSopenharmony_ci    {
708275793eaSopenharmony_ci        printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
709275793eaSopenharmony_ci        return 1;
710275793eaSopenharmony_ci    }
711275793eaSopenharmony_ci    printf("%s opened\n",filename_try);
712275793eaSopenharmony_ci
713275793eaSopenharmony_ci    if (opt_do_list == 1)
714275793eaSopenharmony_ci        ret_value = do_list(uf);
715275793eaSopenharmony_ci    else if (opt_do_extract == 1)
716275793eaSopenharmony_ci    {
717275793eaSopenharmony_ci#ifdef _WIN32
718275793eaSopenharmony_ci        if (opt_extractdir && _chdir(dirname))
719275793eaSopenharmony_ci#else
720275793eaSopenharmony_ci        if (opt_extractdir && chdir(dirname))
721275793eaSopenharmony_ci#endif
722275793eaSopenharmony_ci        {
723275793eaSopenharmony_ci          printf("Error changing into %s, aborting\n", dirname);
724275793eaSopenharmony_ci          exit(-1);
725275793eaSopenharmony_ci        }
726275793eaSopenharmony_ci
727275793eaSopenharmony_ci        if (filename_to_extract == NULL)
728275793eaSopenharmony_ci        {
729275793eaSopenharmony_ci            ret_value = do_extract(uf, opt_do_extract_withoutpath, opt_overwrite, password);
730275793eaSopenharmony_ci        }
731275793eaSopenharmony_ci        else
732275793eaSopenharmony_ci        {
733275793eaSopenharmony_ci            ret_value = do_extract_onefile(uf, filename_to_extract, opt_do_extract_withoutpath, opt_overwrite, password);
734275793eaSopenharmony_ci        }
735275793eaSopenharmony_ci    }
736275793eaSopenharmony_ci
737275793eaSopenharmony_ci    unzClose(uf);
738275793eaSopenharmony_ci
739275793eaSopenharmony_ci    return ret_value;
740275793eaSopenharmony_ci}
741