| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648 | /*   miniunz.c   Version 1.1, February 14h, 2010   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )         Modifications of Unzip for Zip64         Copyright (C) 2007-2008 Even Rouault         Modifications for Zip64 support on both zip and unzip         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )*/#ifndef _WIN32        #ifndef __USE_FILE_OFFSET64                #define __USE_FILE_OFFSET64        #endif        #ifndef __USE_LARGEFILE64                #define __USE_LARGEFILE64        #endif        #ifndef _LARGEFILE64_SOURCE                #define _LARGEFILE64_SOURCE        #endif        #ifndef _FILE_OFFSET_BIT                #define _FILE_OFFSET_BIT 64        #endif#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <errno.h>#include <fcntl.h>#ifdef unix# include <unistd.h># include <utime.h>#else# include <direct.h># include <io.h>#endif#include "unzip.h"#define CASESENSITIVITY (0)#define WRITEBUFFERSIZE (8192)#define MAXFILENAME (256)#ifdef _WIN32#define USEWIN32IOAPI#include "iowin32.h"#endif/*  mini unzip, demo of unzip package  usage :  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT    if it exists*//* change_file_date : change the date/time of a file    filename : the filename of the file where date/time must be modified    dosdate : the new date at the MSDos format (4 bytes)    tmu_date : the SAME new date at the tm_unz format */void change_file_date(filename,dosdate,tmu_date)    const char *filename;    uLong dosdate;    tm_unz tmu_date;{#ifdef _WIN32  HANDLE hFile;  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;  hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,                      0,NULL,OPEN_EXISTING,0,NULL);  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);  LocalFileTimeToFileTime(&ftLocal,&ftm);  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);  CloseHandle(hFile);#else#ifdef unix  struct utimbuf ut;  struct tm newdate;  newdate.tm_sec = tmu_date.tm_sec;  newdate.tm_min=tmu_date.tm_min;  newdate.tm_hour=tmu_date.tm_hour;  newdate.tm_mday=tmu_date.tm_mday;  newdate.tm_mon=tmu_date.tm_mon;  if (tmu_date.tm_year > 1900)      newdate.tm_year=tmu_date.tm_year - 1900;  else      newdate.tm_year=tmu_date.tm_year ;  newdate.tm_isdst=-1;  ut.actime=ut.modtime=mktime(&newdate);  utime(filename,&ut);#endif#endif}/* mymkdir and change_file_date are not 100 % portable   As I don't know well Unix, I wait feedback for the unix portion */int mymkdir(dirname)    const char* dirname;{    int ret=0;#ifdef _WIN32    ret = _mkdir(dirname);#else#ifdef unix    ret = mkdir (dirname,0775);#endif#endif    return ret;}int makedir (newdir)    char *newdir;{  char *buffer ;  char *p;  int  len = (int)strlen(newdir);  if (len <= 0)    return 0;  buffer = (char*)malloc(len+1);        if (buffer==NULL)        {                printf("Error allocating memory\n");                return UNZ_INTERNALERROR;        }  strcpy(buffer,newdir);  if (buffer[len-1] == '/') {    buffer[len-1] = '\0';  }  if (mymkdir(buffer) == 0)    {      free(buffer);      return 1;    }  p = buffer+1;  while (1)    {      char hold;      while(*p && *p != '\\' && *p != '/')        p++;      hold = *p;      *p = 0;      if ((mymkdir(buffer) == -1) && (errno == ENOENT))        {          printf("couldn't create directory %s\n",buffer);          free(buffer);          return 0;        }      if (hold == 0)        break;      *p++ = hold;    }  free(buffer);  return 1;}void do_banner(){    printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");    printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");}void do_help(){    printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \           "  -e  Extract without pathname (junk paths)\n" \           "  -x  Extract with pathname\n" \           "  -v  list files\n" \           "  -l  list files\n" \           "  -d  directory to extract into\n" \           "  -o  overwrite files without prompting\n" \           "  -p  extract crypted file using password\n\n");}void Display64BitsSize(ZPOS64_T n, int size_char){  /* to avoid compatibility problem , we do here the conversion */  char number[21];  int offset=19;  int pos_string = 19;  number[20]=0;  for (;;) {      number[offset]=(char)((n%10)+'0');      if (number[offset] != '0')          pos_string=offset;      n/=10;      if (offset==0)          break;      offset--;  }  {      int size_display_string = 19-pos_string;      while (size_char > size_display_string)      {          size_char--;          printf(" ");      }  }  printf("%s",&number[pos_string]);}int do_list(uf)    unzFile uf;{    uLong i;    unz_global_info64 gi;    int err;    err = unzGetGlobalInfo64(uf,&gi);    if (err!=UNZ_OK)        printf("error %d with zipfile in unzGetGlobalInfo \n",err);    printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");    printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");    for (i=0;i<gi.number_entry;i++)    {        char filename_inzip[256];        unz_file_info64 file_info;        uLong ratio=0;        const char *string_method;        char charCrypt=' ';        err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);        if (err!=UNZ_OK)        {            printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);            break;        }        if (file_info.uncompressed_size>0)            ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size);        /* display a '*' if the file is crypted */        if ((file_info.flag & 1) != 0)            charCrypt='*';        if (file_info.compression_method==0)            string_method="Stored";        else        if (file_info.compression_method==Z_DEFLATED)        {            uInt iLevel=(uInt)((file_info.flag & 0x6)/2);            if (iLevel==0)              string_method="Defl:N";            else if (iLevel==1)              string_method="Defl:X";            else if ((iLevel==2) || (iLevel==3))              string_method="Defl:F"; /* 2:fast , 3 : extra fast*/        }        else        if (file_info.compression_method==Z_BZIP2ED)        {              string_method="BZip2 ";        }        else            string_method="Unkn. ";        Display64BitsSize(file_info.uncompressed_size,7);        printf("  %6s%c",string_method,charCrypt);        Display64BitsSize(file_info.compressed_size,7);        printf(" %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",                ratio,                (uLong)file_info.tmu_date.tm_mon + 1,                (uLong)file_info.tmu_date.tm_mday,                (uLong)file_info.tmu_date.tm_year % 100,                (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,                (uLong)file_info.crc,filename_inzip);        if ((i+1)<gi.number_entry)        {            err = unzGoToNextFile(uf);            if (err!=UNZ_OK)            {                printf("error %d with zipfile in unzGoToNextFile\n",err);                break;            }        }    }    return 0;}int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)    unzFile uf;    const int* popt_extract_without_path;    int* popt_overwrite;    const char* password;{    char filename_inzip[256];    char* filename_withoutpath;    char* p;    int err=UNZ_OK;    FILE *fout=NULL;    void* buf;    uInt size_buf;    unz_file_info64 file_info;    uLong ratio=0;    err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);    if (err!=UNZ_OK)    {        printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);        return err;    }    size_buf = WRITEBUFFERSIZE;    buf = (void*)malloc(size_buf);    if (buf==NULL)    {        printf("Error allocating memory\n");        return UNZ_INTERNALERROR;    }    p = filename_withoutpath = filename_inzip;    while ((*p) != '\0')    {        if (((*p)=='/') || ((*p)=='\\'))            filename_withoutpath = p+1;        p++;    }    if ((*filename_withoutpath)=='\0')    {        if ((*popt_extract_without_path)==0)        {            printf("creating directory: %s\n",filename_inzip);            mymkdir(filename_inzip);        }    }    else    {        const char* write_filename;        int skip=0;        if ((*popt_extract_without_path)==0)            write_filename = filename_inzip;        else            write_filename = filename_withoutpath;        err = unzOpenCurrentFilePassword(uf,password);        if (err!=UNZ_OK)        {            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);        }        if (((*popt_overwrite)==0) && (err==UNZ_OK))        {            char rep=0;            FILE* ftestexist;            ftestexist = fopen64(write_filename,"rb");            if (ftestexist!=NULL)            {                fclose(ftestexist);                do                {                    char answer[128];                    int ret;                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);                    ret = scanf("%1s",answer);                    if (ret != 1)                    {                       exit(EXIT_FAILURE);                    }                    rep = answer[0] ;                    if ((rep>='a') && (rep<='z'))                        rep -= 0x20;                }                while ((rep!='Y') && (rep!='N') && (rep!='A'));            }            if (rep == 'N')                skip = 1;            if (rep == 'A')                *popt_overwrite=1;        }        if ((skip==0) && (err==UNZ_OK))        {            fout=fopen64(write_filename,"wb");            /* some zipfile don't contain directory alone before file */            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&                                (filename_withoutpath!=(char*)filename_inzip))            {                char c=*(filename_withoutpath-1);                *(filename_withoutpath-1)='\0';                makedir(write_filename);                *(filename_withoutpath-1)=c;                fout=fopen64(write_filename,"wb");            }            if (fout==NULL)            {                printf("error opening %s\n",write_filename);            }        }        if (fout!=NULL)        {            printf(" extracting: %s\n",write_filename);            do            {                err = unzReadCurrentFile(uf,buf,size_buf);                if (err<0)                {                    printf("error %d with zipfile in unzReadCurrentFile\n",err);                    break;                }                if (err>0)                    if (fwrite(buf,err,1,fout)!=1)                    {                        printf("error in writing extracted file\n");                        err=UNZ_ERRNO;                        break;                    }            }            while (err>0);            if (fout)                    fclose(fout);            if (err==0)                change_file_date(write_filename,file_info.dosDate,                                 file_info.tmu_date);        }        if (err==UNZ_OK)        {            err = unzCloseCurrentFile (uf);            if (err!=UNZ_OK)            {                printf("error %d with zipfile in unzCloseCurrentFile\n",err);            }        }        else            unzCloseCurrentFile(uf); /* don't lose the error */    }    free(buf);    return err;}int do_extract(uf,opt_extract_without_path,opt_overwrite,password)    unzFile uf;    int opt_extract_without_path;    int opt_overwrite;    const char* password;{    uLong i;    unz_global_info64 gi;    int err;    FILE* fout=NULL;    err = unzGetGlobalInfo64(uf,&gi);    if (err!=UNZ_OK)        printf("error %d with zipfile in unzGetGlobalInfo \n",err);    for (i=0;i<gi.number_entry;i++)    {        if (do_extract_currentfile(uf,&opt_extract_without_path,                                      &opt_overwrite,                                      password) != UNZ_OK)            break;        if ((i+1)<gi.number_entry)        {            err = unzGoToNextFile(uf);            if (err!=UNZ_OK)            {                printf("error %d with zipfile in unzGoToNextFile\n",err);                break;            }        }    }    return 0;}int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)    unzFile uf;    const char* filename;    int opt_extract_without_path;    int opt_overwrite;    const char* password;{    int err = UNZ_OK;    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)    {        printf("file %s not found in the zipfile\n",filename);        return 2;    }    if (do_extract_currentfile(uf,&opt_extract_without_path,                                      &opt_overwrite,                                      password) == UNZ_OK)        return 0;    else        return 1;}int main(argc,argv)    int argc;    char *argv[];{    const char *zipfilename=NULL;    const char *filename_to_extract=NULL;    const char *password=NULL;    char filename_try[MAXFILENAME+16] = "";    int i;    int ret_value=0;    int opt_do_list=0;    int opt_do_extract=1;    int opt_do_extract_withoutpath=0;    int opt_overwrite=0;    int opt_extractdir=0;    const char *dirname=NULL;    unzFile uf=NULL;    do_banner();    if (argc==1)    {        do_help();        return 0;    }    else    {        for (i=1;i<argc;i++)        {            if ((*argv[i])=='-')            {                const char *p=argv[i]+1;                while ((*p)!='\0')                {                    char c=*(p++);;                    if ((c=='l') || (c=='L'))                        opt_do_list = 1;                    if ((c=='v') || (c=='V'))                        opt_do_list = 1;                    if ((c=='x') || (c=='X'))                        opt_do_extract = 1;                    if ((c=='e') || (c=='E'))                        opt_do_extract = opt_do_extract_withoutpath = 1;                    if ((c=='o') || (c=='O'))                        opt_overwrite=1;                    if ((c=='d') || (c=='D'))                    {                        opt_extractdir=1;                        dirname=argv[i+1];                    }                    if (((c=='p') || (c=='P')) && (i+1<argc))                    {                        password=argv[i+1];                        i++;                    }                }            }            else            {                if (zipfilename == NULL)                    zipfilename = argv[i];                else if ((filename_to_extract==NULL) && (!opt_extractdir))                        filename_to_extract = argv[i] ;            }        }    }    if (zipfilename!=NULL)    {#        ifdef USEWIN32IOAPI        zlib_filefunc64_def ffunc;#        endif        strncpy(filename_try, zipfilename,MAXFILENAME-1);        /* strncpy doesnt append the trailing NULL, of the string is too long. */        filename_try[ MAXFILENAME ] = '\0';#        ifdef USEWIN32IOAPI        fill_win32_filefunc64A(&ffunc);        uf = unzOpen2_64(zipfilename,&ffunc);#        else        uf = unzOpen64(zipfilename);#        endif        if (uf==NULL)        {            strcat(filename_try,".zip");#            ifdef USEWIN32IOAPI            uf = unzOpen2_64(filename_try,&ffunc);#            else            uf = unzOpen64(filename_try);#            endif        }    }    if (uf==NULL)    {        printf("Cannot open %s or %s.zip\n",zipfilename,zipfilename);        return 1;    }    printf("%s opened\n",filename_try);    if (opt_do_list==1)        ret_value = do_list(uf);    else if (opt_do_extract==1)    {#ifdef _WIN32        if (opt_extractdir && _chdir(dirname))#else        if (opt_extractdir && chdir(dirname))#endif        {          printf("Error changing into %s, aborting\n", dirname);          exit(-1);        }        if (filename_to_extract == NULL)            ret_value = do_extract(uf, opt_do_extract_withoutpath, opt_overwrite, password);        else            ret_value = do_extract_onefile(uf, filename_to_extract, opt_do_extract_withoutpath, opt_overwrite, password);    }    unzClose(uf);    return ret_value;}
 |