(root)/
gcc-13.2.0/
zlib/
contrib/
minizip/
miniunz.c
       1  /*
       2     miniunz.c
       3     Version 1.1, February 14h, 2010
       4     sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
       5  
       6           Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
       7  
       8           Modifications of Unzip for Zip64
       9           Copyright (C) 2007-2008 Even Rouault
      10  
      11           Modifications for Zip64 support on both zip and unzip
      12           Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
      13  */
      14  
      15  #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
      16          #ifndef __USE_FILE_OFFSET64
      17                  #define __USE_FILE_OFFSET64
      18          #endif
      19          #ifndef __USE_LARGEFILE64
      20                  #define __USE_LARGEFILE64
      21          #endif
      22          #ifndef _LARGEFILE64_SOURCE
      23                  #define _LARGEFILE64_SOURCE
      24          #endif
      25          #ifndef _FILE_OFFSET_BIT
      26                  #define _FILE_OFFSET_BIT 64
      27          #endif
      28  #endif
      29  
      30  #ifdef __APPLE__
      31  // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
      32  #define FOPEN_FUNC(filename, mode) fopen(filename, mode)
      33  #define FTELLO_FUNC(stream) ftello(stream)
      34  #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
      35  #else
      36  #define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
      37  #define FTELLO_FUNC(stream) ftello64(stream)
      38  #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
      39  #endif
      40  
      41  
      42  #include <stdio.h>
      43  #include <stdlib.h>
      44  #include <string.h>
      45  #include <time.h>
      46  #include <errno.h>
      47  #include <fcntl.h>
      48  
      49  #ifdef _WIN32
      50  # include <direct.h>
      51  # include <io.h>
      52  #else
      53  # include <unistd.h>
      54  # include <utime.h>
      55  #endif
      56  
      57  
      58  #include "unzip.h"
      59  
      60  #define CASESENSITIVITY (0)
      61  #define WRITEBUFFERSIZE (8192)
      62  #define MAXFILENAME (256)
      63  
      64  #ifdef _WIN32
      65  #define USEWIN32IOAPI
      66  #include "iowin32.h"
      67  #endif
      68  /*
      69    mini unzip, demo of unzip package
      70  
      71    usage :
      72    Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]
      73  
      74    list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
      75      if it exists
      76  */
      77  
      78  
      79  /* change_file_date : change the date/time of a file
      80      filename : the filename of the file where date/time must be modified
      81      dosdate : the new date at the MSDos format (4 bytes)
      82      tmu_date : the SAME new date at the tm_unz format */
      83  void change_file_date(filename,dosdate,tmu_date)
      84      const char *filename;
      85      uLong dosdate;
      86      tm_unz tmu_date;
      87  {
      88  #ifdef _WIN32
      89    HANDLE hFile;
      90    FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
      91  
      92    hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
      93                        0,NULL,OPEN_EXISTING,0,NULL);
      94    GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
      95    DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
      96    LocalFileTimeToFileTime(&ftLocal,&ftm);
      97    SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
      98    CloseHandle(hFile);
      99  #else
     100  #ifdef unix || __APPLE__
     101    struct utimbuf ut;
     102    struct tm newdate;
     103    newdate.tm_sec = tmu_date.tm_sec;
     104    newdate.tm_min=tmu_date.tm_min;
     105    newdate.tm_hour=tmu_date.tm_hour;
     106    newdate.tm_mday=tmu_date.tm_mday;
     107    newdate.tm_mon=tmu_date.tm_mon;
     108    if (tmu_date.tm_year > 1900)
     109        newdate.tm_year=tmu_date.tm_year - 1900;
     110    else
     111        newdate.tm_year=tmu_date.tm_year ;
     112    newdate.tm_isdst=-1;
     113  
     114    ut.actime=ut.modtime=mktime(&newdate);
     115    utime(filename,&ut);
     116  #endif
     117  #endif
     118  }
     119  
     120  
     121  /* mymkdir and change_file_date are not 100 % portable
     122     As I don't know well Unix, I wait feedback for the unix portion */
     123  
     124  int mymkdir(dirname)
     125      const char* dirname;
     126  {
     127      int ret=0;
     128  #ifdef _WIN32
     129      ret = _mkdir(dirname);
     130  #elif unix
     131      ret = mkdir (dirname,0775);
     132  #elif __APPLE__
     133      ret = mkdir (dirname,0775);
     134  #endif
     135      return ret;
     136  }
     137  
     138  int makedir (newdir)
     139      char *newdir;
     140  {
     141    char *buffer ;
     142    char *p;
     143    int  len = (int)strlen(newdir);
     144  
     145    if (len <= 0)
     146      return 0;
     147  
     148    buffer = (char*)malloc(len+1);
     149          if (buffer==NULL)
     150          {
     151                  printf("Error allocating memory\n");
     152                  return UNZ_INTERNALERROR;
     153          }
     154    strcpy(buffer,newdir);
     155  
     156    if (buffer[len-1] == '/') {
     157      buffer[len-1] = '\0';
     158    }
     159    if (mymkdir(buffer) == 0)
     160      {
     161        free(buffer);
     162        return 1;
     163      }
     164  
     165    p = buffer+1;
     166    while (1)
     167      {
     168        char hold;
     169  
     170        while(*p && *p != '\\' && *p != '/')
     171          p++;
     172        hold = *p;
     173        *p = 0;
     174        if ((mymkdir(buffer) == -1) && (errno == ENOENT))
     175          {
     176            printf("couldn't create directory %s\n",buffer);
     177            free(buffer);
     178            return 0;
     179          }
     180        if (hold == 0)
     181          break;
     182        *p++ = hold;
     183      }
     184    free(buffer);
     185    return 1;
     186  }
     187  
     188  void do_banner()
     189  {
     190      printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
     191      printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
     192  }
     193  
     194  void do_help()
     195  {
     196      printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
     197             "  -e  Extract without pathname (junk paths)\n" \
     198             "  -x  Extract with pathname\n" \
     199             "  -v  list files\n" \
     200             "  -l  list files\n" \
     201             "  -d  directory to extract into\n" \
     202             "  -o  overwrite files without prompting\n" \
     203             "  -p  extract crypted file using password\n\n");
     204  }
     205  
     206  void Display64BitsSize(ZPOS64_T n, int size_char)
     207  {
     208    /* to avoid compatibility problem , we do here the conversion */
     209    char number[21];
     210    int offset=19;
     211    int pos_string = 19;
     212    number[20]=0;
     213    for (;;) {
     214        number[offset]=(char)((n%10)+'0');
     215        if (number[offset] != '0')
     216            pos_string=offset;
     217        n/=10;
     218        if (offset==0)
     219            break;
     220        offset--;
     221    }
     222    {
     223        int size_display_string = 19-pos_string;
     224        while (size_char > size_display_string)
     225        {
     226            size_char--;
     227            printf(" ");
     228        }
     229    }
     230  
     231    printf("%s",&number[pos_string]);
     232  }
     233  
     234  int do_list(uf)
     235      unzFile uf;
     236  {
     237      uLong i;
     238      unz_global_info64 gi;
     239      int err;
     240  
     241      err = unzGetGlobalInfo64(uf,&gi);
     242      if (err!=UNZ_OK)
     243          printf("error %d with zipfile in unzGetGlobalInfo \n",err);
     244      printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");
     245      printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");
     246      for (i=0;i<gi.number_entry;i++)
     247      {
     248          char filename_inzip[256];
     249          unz_file_info64 file_info;
     250          uLong ratio=0;
     251          const char *string_method;
     252          char charCrypt=' ';
     253          err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
     254          if (err!=UNZ_OK)
     255          {
     256              printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
     257              break;
     258          }
     259          if (file_info.uncompressed_size>0)
     260              ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size);
     261  
     262          /* display a '*' if the file is crypted */
     263          if ((file_info.flag & 1) != 0)
     264              charCrypt='*';
     265  
     266          if (file_info.compression_method==0)
     267              string_method="Stored";
     268          else
     269          if (file_info.compression_method==Z_DEFLATED)
     270          {
     271              uInt iLevel=(uInt)((file_info.flag & 0x6)/2);
     272              if (iLevel==0)
     273                string_method="Defl:N";
     274              else if (iLevel==1)
     275                string_method="Defl:X";
     276              else if ((iLevel==2) || (iLevel==3))
     277                string_method="Defl:F"; /* 2:fast , 3 : extra fast*/
     278          }
     279          else
     280          if (file_info.compression_method==Z_BZIP2ED)
     281          {
     282                string_method="BZip2 ";
     283          }
     284          else
     285              string_method="Unkn. ";
     286  
     287          Display64BitsSize(file_info.uncompressed_size,7);
     288          printf("  %6s%c",string_method,charCrypt);
     289          Display64BitsSize(file_info.compressed_size,7);
     290          printf(" %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
     291                  ratio,
     292                  (uLong)file_info.tmu_date.tm_mon + 1,
     293                  (uLong)file_info.tmu_date.tm_mday,
     294                  (uLong)file_info.tmu_date.tm_year % 100,
     295                  (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
     296                  (uLong)file_info.crc,filename_inzip);
     297          if ((i+1)<gi.number_entry)
     298          {
     299              err = unzGoToNextFile(uf);
     300              if (err!=UNZ_OK)
     301              {
     302                  printf("error %d with zipfile in unzGoToNextFile\n",err);
     303                  break;
     304              }
     305          }
     306      }
     307  
     308      return 0;
     309  }
     310  
     311  
     312  int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
     313      unzFile uf;
     314      const int* popt_extract_without_path;
     315      int* popt_overwrite;
     316      const char* password;
     317  {
     318      char filename_inzip[256];
     319      char* filename_withoutpath;
     320      char* p;
     321      int err=UNZ_OK;
     322      FILE *fout=NULL;
     323      void* buf;
     324      uInt size_buf;
     325  
     326      unz_file_info64 file_info;
     327      uLong ratio=0;
     328      err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
     329  
     330      if (err!=UNZ_OK)
     331      {
     332          printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
     333          return err;
     334      }
     335  
     336      size_buf = WRITEBUFFERSIZE;
     337      buf = (void*)malloc(size_buf);
     338      if (buf==NULL)
     339      {
     340          printf("Error allocating memory\n");
     341          return UNZ_INTERNALERROR;
     342      }
     343  
     344      p = filename_withoutpath = filename_inzip;
     345      while ((*p) != '\0')
     346      {
     347          if (((*p)=='/') || ((*p)=='\\'))
     348              filename_withoutpath = p+1;
     349          p++;
     350      }
     351  
     352      if ((*filename_withoutpath)=='\0')
     353      {
     354          if ((*popt_extract_without_path)==0)
     355          {
     356              printf("creating directory: %s\n",filename_inzip);
     357              mymkdir(filename_inzip);
     358          }
     359      }
     360      else
     361      {
     362          const char* write_filename;
     363          int skip=0;
     364  
     365          if ((*popt_extract_without_path)==0)
     366              write_filename = filename_inzip;
     367          else
     368              write_filename = filename_withoutpath;
     369  
     370          err = unzOpenCurrentFilePassword(uf,password);
     371          if (err!=UNZ_OK)
     372          {
     373              printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
     374          }
     375  
     376          if (((*popt_overwrite)==0) && (err==UNZ_OK))
     377          {
     378              char rep=0;
     379              FILE* ftestexist;
     380              ftestexist = FOPEN_FUNC(write_filename,"rb");
     381              if (ftestexist!=NULL)
     382              {
     383                  fclose(ftestexist);
     384                  do
     385                  {
     386                      char answer[128];
     387                      int ret;
     388  
     389                      printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
     390                      ret = scanf("%1s",answer);
     391                      if (ret != 1)
     392                      {
     393                         exit(EXIT_FAILURE);
     394                      }
     395                      rep = answer[0] ;
     396                      if ((rep>='a') && (rep<='z'))
     397                          rep -= 0x20;
     398                  }
     399                  while ((rep!='Y') && (rep!='N') && (rep!='A'));
     400              }
     401  
     402              if (rep == 'N')
     403                  skip = 1;
     404  
     405              if (rep == 'A')
     406                  *popt_overwrite=1;
     407          }
     408  
     409          if ((skip==0) && (err==UNZ_OK))
     410          {
     411              fout=FOPEN_FUNC(write_filename,"wb");
     412              /* some zipfile don't contain directory alone before file */
     413              if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
     414                                  (filename_withoutpath!=(char*)filename_inzip))
     415              {
     416                  char c=*(filename_withoutpath-1);
     417                  *(filename_withoutpath-1)='\0';
     418                  makedir(write_filename);
     419                  *(filename_withoutpath-1)=c;
     420                  fout=FOPEN_FUNC(write_filename,"wb");
     421              }
     422  
     423              if (fout==NULL)
     424              {
     425                  printf("error opening %s\n",write_filename);
     426              }
     427          }
     428  
     429          if (fout!=NULL)
     430          {
     431              printf(" extracting: %s\n",write_filename);
     432  
     433              do
     434              {
     435                  err = unzReadCurrentFile(uf,buf,size_buf);
     436                  if (err<0)
     437                  {
     438                      printf("error %d with zipfile in unzReadCurrentFile\n",err);
     439                      break;
     440                  }
     441                  if (err>0)
     442                      if (fwrite(buf,err,1,fout)!=1)
     443                      {
     444                          printf("error in writing extracted file\n");
     445                          err=UNZ_ERRNO;
     446                          break;
     447                      }
     448              }
     449              while (err>0);
     450              if (fout)
     451                      fclose(fout);
     452  
     453              if (err==0)
     454                  change_file_date(write_filename,file_info.dosDate,
     455                                   file_info.tmu_date);
     456          }
     457  
     458          if (err==UNZ_OK)
     459          {
     460              err = unzCloseCurrentFile (uf);
     461              if (err!=UNZ_OK)
     462              {
     463                  printf("error %d with zipfile in unzCloseCurrentFile\n",err);
     464              }
     465          }
     466          else
     467              unzCloseCurrentFile(uf); /* don't lose the error */
     468      }
     469  
     470      free(buf);
     471      return err;
     472  }
     473  
     474  
     475  int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
     476      unzFile uf;
     477      int opt_extract_without_path;
     478      int opt_overwrite;
     479      const char* password;
     480  {
     481      uLong i;
     482      unz_global_info64 gi;
     483      int err;
     484      FILE* fout=NULL;
     485  
     486      err = unzGetGlobalInfo64(uf,&gi);
     487      if (err!=UNZ_OK)
     488          printf("error %d with zipfile in unzGetGlobalInfo \n",err);
     489  
     490      for (i=0;i<gi.number_entry;i++)
     491      {
     492          if (do_extract_currentfile(uf,&opt_extract_without_path,
     493                                        &opt_overwrite,
     494                                        password) != UNZ_OK)
     495              break;
     496  
     497          if ((i+1)<gi.number_entry)
     498          {
     499              err = unzGoToNextFile(uf);
     500              if (err!=UNZ_OK)
     501              {
     502                  printf("error %d with zipfile in unzGoToNextFile\n",err);
     503                  break;
     504              }
     505          }
     506      }
     507  
     508      return 0;
     509  }
     510  
     511  int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)
     512      unzFile uf;
     513      const char* filename;
     514      int opt_extract_without_path;
     515      int opt_overwrite;
     516      const char* password;
     517  {
     518      int err = UNZ_OK;
     519      if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
     520      {
     521          printf("file %s not found in the zipfile\n",filename);
     522          return 2;
     523      }
     524  
     525      if (do_extract_currentfile(uf,&opt_extract_without_path,
     526                                        &opt_overwrite,
     527                                        password) == UNZ_OK)
     528          return 0;
     529      else
     530          return 1;
     531  }
     532  
     533  
     534  int main(argc,argv)
     535      int argc;
     536      char *argv[];
     537  {
     538      const char *zipfilename=NULL;
     539      const char *filename_to_extract=NULL;
     540      const char *password=NULL;
     541      char filename_try[MAXFILENAME+16] = "";
     542      int i;
     543      int ret_value=0;
     544      int opt_do_list=0;
     545      int opt_do_extract=1;
     546      int opt_do_extract_withoutpath=0;
     547      int opt_overwrite=0;
     548      int opt_extractdir=0;
     549      const char *dirname=NULL;
     550      unzFile uf=NULL;
     551  
     552      do_banner();
     553      if (argc==1)
     554      {
     555          do_help();
     556          return 0;
     557      }
     558      else
     559      {
     560          for (i=1;i<argc;i++)
     561          {
     562              if ((*argv[i])=='-')
     563              {
     564                  const char *p=argv[i]+1;
     565  
     566                  while ((*p)!='\0')
     567                  {
     568                      char c=*(p++);;
     569                      if ((c=='l') || (c=='L'))
     570                          opt_do_list = 1;
     571                      if ((c=='v') || (c=='V'))
     572                          opt_do_list = 1;
     573                      if ((c=='x') || (c=='X'))
     574                          opt_do_extract = 1;
     575                      if ((c=='e') || (c=='E'))
     576                          opt_do_extract = opt_do_extract_withoutpath = 1;
     577                      if ((c=='o') || (c=='O'))
     578                          opt_overwrite=1;
     579                      if ((c=='d') || (c=='D'))
     580                      {
     581                          opt_extractdir=1;
     582                          dirname=argv[i+1];
     583                      }
     584  
     585                      if (((c=='p') || (c=='P')) && (i+1<argc))
     586                      {
     587                          password=argv[i+1];
     588                          i++;
     589                      }
     590                  }
     591              }
     592              else
     593              {
     594                  if (zipfilename == NULL)
     595                      zipfilename = argv[i];
     596                  else if ((filename_to_extract==NULL) && (!opt_extractdir))
     597                          filename_to_extract = argv[i] ;
     598              }
     599          }
     600      }
     601  
     602      if (zipfilename!=NULL)
     603      {
     604  
     605  #        ifdef USEWIN32IOAPI
     606          zlib_filefunc64_def ffunc;
     607  #        endif
     608  
     609          strncpy(filename_try, zipfilename,MAXFILENAME-1);
     610          /* strncpy doesnt append the trailing NULL, of the string is too long. */
     611          filename_try[ MAXFILENAME ] = '\0';
     612  
     613  #        ifdef USEWIN32IOAPI
     614          fill_win32_filefunc64A(&ffunc);
     615          uf = unzOpen2_64(zipfilename,&ffunc);
     616  #        else
     617          uf = unzOpen64(zipfilename);
     618  #        endif
     619          if (uf==NULL)
     620          {
     621              strcat(filename_try,".zip");
     622  #            ifdef USEWIN32IOAPI
     623              uf = unzOpen2_64(filename_try,&ffunc);
     624  #            else
     625              uf = unzOpen64(filename_try);
     626  #            endif
     627          }
     628      }
     629  
     630      if (uf==NULL)
     631      {
     632          printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);
     633          return 1;
     634      }
     635      printf("%s opened\n",filename_try);
     636  
     637      if (opt_do_list==1)
     638          ret_value = do_list(uf);
     639      else if (opt_do_extract==1)
     640      {
     641  #ifdef _WIN32
     642          if (opt_extractdir && _chdir(dirname))
     643  #else
     644          if (opt_extractdir && chdir(dirname))
     645  #endif
     646          {
     647            printf("Error changing into %s, aborting\n", dirname);
     648            exit(-1);
     649          }
     650  
     651          if (filename_to_extract == NULL)
     652              ret_value = do_extract(uf, opt_do_extract_withoutpath, opt_overwrite, password);
     653          else
     654              ret_value = do_extract_onefile(uf, filename_to_extract, opt_do_extract_withoutpath, opt_overwrite, password);
     655      }
     656  
     657      unzClose(uf);
     658  
     659      return ret_value;
     660  }