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