Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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