miniunz.c
上传用户:shengde
上传日期:2021-02-21
资源大小:638k
文件大小:17k
源码类别:

压缩解压

开发平台:

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