home *** CD-ROM | disk | FTP | other *** search
/ Freelog 11 / Freelog011.iso / Bas / Compression / ZLib / contrib / minizip / miniunz.c < prev    next >
C/C++ Source or Header  |  1998-03-18  |  12KB  |  509 lines

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