跨平台的zip文件压缩处理,支持压缩解压文件夹
根据minizip改写的模块,需要zlib支持
输出的接口:
1 #define RG_ZIP_FILE_REPLACE 0 2 #define RG_ZIP_FILE_APPEND 1 3 4 //压缩文件夹目录,递归压缩 5 //szDir是需要压缩的目录,dstLevel是压缩的目录在压缩包里面的层次标识 6 //可直接指定"" 7 //szZipFile压缩包的文件名 8 //replaceFlag指定替换或者是追加进压缩包 9 int DoZipDir(const char* szDir, const char* dstLevel, const char* szZipFile, int replaceFlag); 10 11 //压缩单个文件,szFile是文件名,其它参数解析同上 12 int DoZipFile(const char* szFile, const char* dstLevel, const char* szZipFile, int replaceFlag); 13 14 //解压缩文件 15 //szZipFile是需要解压的压缩包文件名 16 //指定需要解压到的目录,直接指定为"",解压至当前目录 17 int DoUnzip(const char* szZipFile, const char* szTargetDir); 18 19 //从压缩包里面解压单个文件出来 20 //srcFileToExtract对应压缩文件时的dstLevel 21 //其它参数解析同上 22 int DoUnzipFile(const char* szZipFile, const char* srcFileToExtract, const char* szTargetDir);
本文仅仅提供封装的api,zlib库和info-zip请自行下载
其它涉及的代码可以下载minizip或者info-zip,推荐使用minizip,本代码是在minizip的基础上修改而来,支持跨平台
1 /* 2 minizip.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 #ifdef _DEBUG 16 #pragma comment(lib, "../../lib/win32/libzd.lib") 17 #else 18 #pragma comment(lib, "../../lib/win32/libz.lib") 19 #endif 20 21 #ifndef _WIN32 22 #ifndef __USE_FILE_OFFSET64 23 #define __USE_FILE_OFFSET64 24 #endif 25 #ifndef __USE_LARGEFILE64 26 #define __USE_LARGEFILE64 27 #endif 28 #ifndef _LARGEFILE64_SOURCE 29 #define _LARGEFILE64_SOURCE 30 #endif 31 #ifndef _FILE_OFFSET_BIT 32 #define _FILE_OFFSET_BIT 64 33 #endif 34 #endif 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <time.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 43 #ifdef _LINUX 44 # include <utime.h> 45 # include <sys/types.h> 46 # include <sys/stat.h> 47 # include <unistd.h> 48 #include <dirent.h> 49 #else 50 # include <direct.h> 51 # include <io.h> 52 #endif 53 54 #include "zip.h" 55 #include "stdstring.h" 56 #include <vector> 57 #include "comfun.h" 58 59 using namespace std; 60 61 // #ifdef _WIN32 62 // #define USEWIN32IOAPI 63 // #include "iowin32.h" 64 // #endif 65 66 67 68 #define WRITEBUFFERSIZE (16384) 69 #define MAXFILENAME (256) 70 71 #ifdef _WIN32 72 static uLong filetime(const char *f, tm_zip *tmzip, uLong *dt) 73 /*char *f; name of file to get info on */ 74 /* tm_zip *tmzip; return value: access, modific. and creation times */ 75 /*uLong *dt; dostime */ 76 { 77 int ret = 0; 78 { 79 FILETIME ftLocal; 80 HANDLE hFind; 81 WIN32_FIND_DATAA ff32; 82 83 hFind = FindFirstFileA(f,&ff32); 84 if (hFind != INVALID_HANDLE_VALUE) 85 { 86 FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); 87 FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); 88 FindClose(hFind); 89 ret = 1; 90 } 91 } 92 return ret; 93 } 94 #else 95 #ifdef _LINUX 96 static uLong filetime(const char *f, tm_zip *tmzip, uLong *dt) 97 /*char *f; name of file to get info on */ 98 /*tm_zip *tmzip; return value: access, modific. and creation times */ 99 /*uLong *dt; dostime */ 100 { 101 int ret=0; 102 struct stat s; /* results of stat() */ 103 struct tm* filedate; 104 time_t tm_t=0; 105 106 if (strcmp(f,"-")!=0) 107 { 108 char name[MAXFILENAME+1]; 109 int len = strlen(f); 110 if (len > MAXFILENAME) 111 len = MAXFILENAME; 112 113 strncpy(name, f,MAXFILENAME-1); 114 /* strncpy doesnt append the trailing NULL, of the string is too long. */ 115 name[ MAXFILENAME ] = '\0'; 116 117 if (name[len - 1] == '/') 118 name[len - 1] = '\0'; 119 /* not all systems allow stat'ing a file with / appended */ 120 if (stat(name,&s)==0) 121 { 122 tm_t = s.st_mtime; 123 ret = 1; 124 } 125 } 126 filedate = localtime(&tm_t); 127 128 tmzip->tm_sec = filedate->tm_sec; 129 tmzip->tm_min = filedate->tm_min; 130 tmzip->tm_hour = filedate->tm_hour; 131 tmzip->tm_mday = filedate->tm_mday; 132 tmzip->tm_mon = filedate->tm_mon ; 133 tmzip->tm_year = filedate->tm_year; 134 135 return ret; 136 } 137 #else 138 uLong filetime(char *f, tm_zip *tmzip, uLong *dt) 139 { 140 return 0; 141 } 142 #endif 143 #endif 144 145 static int check_exist_file(const char* filename) 146 { 147 FILE* ftestexist; 148 int ret = 1; 149 ftestexist = fopen64(filename,"rb"); 150 if (ftestexist==NULL) 151 ret = 0; 152 else 153 fclose(ftestexist); 154 155 return ret; 156 } 157 158 static int isLargeFile(const char* filename) 159 { 160 int largeFile = 0; 161 ZPOS64_T pos = 0; 162 FILE* pFile = fopen64(filename, "rb"); 163 164 if(pFile != NULL) 165 { 166 int n = fseeko64(pFile, 0, SEEK_END); 167 168 pos = ftello64(pFile); 169 170 if(pos >= 0xffffffff) 171 largeFile = 1; 172 173 fclose(pFile); 174 } 175 176 return largeFile; 177 } 178 179 static int DoZipFile(zipFile zf, const char* srcFile, const char* dstLevel) 180 { 181 if(zf == NULL || srcFile == NULL) return __LINE__; 182 183 int err=0; 184 int size_buf=0; 185 void* buf=NULL; 186 FILE * fin; 187 int size_read; 188 const char* filenameinzip = srcFile; 189 const char *savefilenameinzip; 190 zip_fileinfo zi; 191 int zip64 = 0; 192 193 zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = 194 zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; 195 zi.dosDate = 0; 196 zi.internal_fa = 0; 197 zi.external_fa = 0; 198 filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); 199 200 zip64 = isLargeFile(filenameinzip); 201 202 /* The path name saved, should not include a leading slash. */ 203 /*if it did, windows/xp and dynazip couldn't read the zip file. */ 204 savefilenameinzip = dstLevel; 205 while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) 206 { 207 savefilenameinzip++; 208 } 209 210 err = zipOpenNewFileInZip3_64(zf, savefilenameinzip, &zi, 211 NULL, 0, NULL, 0, NULL /* comment*/, 212 Z_DEFLATED, 213 Z_DEFAULT_COMPRESSION,0, 214 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, 215 NULL, 0, zip64); 216 217 if (err != ZIP_OK) 218 printf("error in opening %s in zipfile\n",filenameinzip); 219 else 220 { 221 fin = fopen64(filenameinzip,"rb"); 222 if (fin==NULL) 223 { 224 err=ZIP_ERRNO; 225 printf("error in opening %s for reading\n",filenameinzip); 226 } 227 } 228 229 if (err == ZIP_OK) 230 { 231 size_buf = WRITEBUFFERSIZE; 232 buf = (void*)malloc(size_buf); 233 if (buf==NULL) 234 { 235 printf("Error allocating memory\n"); 236 err = ZIP_INTERNALERROR; 237 } 238 else 239 { 240 do 241 { 242 err = ZIP_OK; 243 size_read = (int)fread(buf,1,size_buf,fin); 244 if (size_read < size_buf) 245 if (feof(fin)==0) 246 { 247 printf("error in reading %s\n",filenameinzip); 248 err = ZIP_ERRNO; 249 } 250 251 if (size_read>0) 252 { 253 err = zipWriteInFileInZip (zf,buf,size_read); 254 if (err<0) 255 { 256 printf("error in writing %s in the zipfile\n", 257 filenameinzip); 258 } 259 260 } 261 } while ((err == ZIP_OK) && (size_read>0)); 262 263 free(buf); 264 } 265 } 266 267 if (fin) 268 fclose(fin); 269 270 if (err<0) 271 err=ZIP_ERRNO; 272 else 273 { 274 err = zipCloseFileInZip(zf); 275 if (err!=ZIP_OK) 276 printf("error in closing %s in the zipfile\n", 277 filenameinzip); 278 } 279 280 return 0; 281 } 282 283 int DoZipFile(const char* strFile, const char* dstLevel, const char* strZipFile, int replaceFlag) 284 { 285 int openMode = APPEND_STATUS_CREATE; 286 if (check_exist_file(strZipFile)) 287 { 288 if (replaceFlag == RG_ZIP_FILE_APPEND) 289 { 290 openMode = APPEND_STATUS_ADDINZIP; 291 } 292 else 293 { 294 openMode = APPEND_STATUS_CREATE; 295 } 296 } 297 298 zipFile zf; 299 zf = zipOpen64(strZipFile, openMode); 300 if (zf) 301 { 302 CStdString strDstLevel; 303 if(dstLevel) strDstLevel = dstLevel; 304 strDstLevel.Trim(); 305 if(strDstLevel.IsEmpty()) 306 { 307 strDstLevel = strFile; 308 if(strDstLevel.Right(1) == "\\" || strDstLevel.Right(1) == "/") 309 strDstLevel = strDstLevel.Left(strDstLevel.GetLength() - 1); 310 int nFind = strDstLevel.ReverseFind('\\'); 311 if(nFind == -1) nFind = strDstLevel.ReverseFind('/'); 312 if(nFind != -1) 313 strDstLevel = strDstLevel.Mid(nFind); 314 } 315 316 if (strDstLevel.Left(1) == "\\" || strDstLevel.Left(1) == "/") 317 strDstLevel = strDstLevel.Right(strDstLevel.GetLength() - 1); 318 319 DoZipFile(zf, strFile, strDstLevel.c_str()); 320 zipClose(zf, NULL); 321 return 0; 322 } 323 324 return 0; 325 } 326 327 static int GetFilesFromDir(const char* strDir, vector<CStdString> &_fileInfo) 328 { 329 330 #ifdef _WIN32 331 CStdString strFind = strDir; 332 CStdString strPath; 333 if (strFind.Right(1) != "\\") 334 { 335 strFind += "\\"; 336 } 337 strPath = strFind; 338 strFind += "*.*"; 339 340 WIN32_FIND_DATA wfd; 341 HANDLE hFind = FindFirstFile(strFind, &wfd); 342 if (hFind != INVALID_HANDLE_VALUE) 343 { 344 while(FindNextFile(hFind, &wfd)) 345 { 346 if (strcmp(wfd.cFileName, ".") == 0 || strcmp(wfd.cFileName, "..") == 0) 347 { 348 continue; 349 } 350 CStdString strFilePath = strPath + wfd.cFileName; 351 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 352 { 353 GetFilesFromDir(strFilePath.c_str(), _fileInfo); 354 } 355 else 356 { 357 _fileInfo.push_back(strFilePath); 358 } 359 } 360 FindClose(hFind); 361 return 0; 362 } 363 364 return __LINE__; 365 #else 366 struct stat statbuf; 367 struct dirent *dirp; 368 DIR *dp; 369 const char* szPath = strDir; 370 371 if(lstat(szPath, &statbuf) < 0) 372 { 373 perror("lstat"); 374 return __LINE__; 375 } 376 if(S_ISDIR(statbuf.st_mode) == 0) 377 { 378 _fileInfo.push_back(szPath); 379 return 0; 380 } 381 382 if((dp = opendir(szPath)) == NULL) 383 { 384 perror("opendir"); 385 return __LINE__; 386 } 387 388 while((dirp = readdir(dp)) != NULL) 389 { 390 if(strcmp(dirp->d_name, ".") == 0 || 391 strcmp(dirp->d_name, "..") == 0) 392 continue; 393 394 std::string subDir = string(szPath) + "/"; 395 subDir += dirp->d_name; 396 if(dirp->d_type == DT_REG) 397 { 398 _fileInfo.push_back(subDir); 399 } 400 else if(dirp->d_type == DT_DIR) 401 { 402 GetFilesFromDir(subDir.c_str(), _fileInfo); 403 } 404 } 405 406 closedir(dp); 407 #endif 408 } 409 410 int DoZipDir(const char* strDir, const char* dstLevel, const char* strZipFile, int replaceFlag) 411 { 412 int openMode = APPEND_STATUS_CREATE; 413 if(check_exist_file(strZipFile)) 414 { 415 if (replaceFlag == RG_ZIP_FILE_APPEND) 416 { 417 openMode = APPEND_STATUS_ADDINZIP; 418 } 419 else 420 { 421 remove(strZipFile); 422 openMode = APPEND_STATUS_CREATE; 423 } 424 } 425 426 CStdString strDstLevel; 427 if(dstLevel) strDstLevel= dstLevel; 428 strDstLevel.Trim(); 429 if(strDstLevel.IsEmpty()) { //use current dir path as zip file path level 430 strDstLevel = strDir; 431 if(strDstLevel.Right(1) == "/" || strDstLevel.Right(1) == "\\") //remove the last slash 432 strDstLevel = strDstLevel.Left(strDstLevel.GetLength() - 1); 433 434 int nFind = strDstLevel.ReverseFind('\\'); //now get the dst level in zip file 435 if(nFind == -1) nFind = strDstLevel.ReverseFind('/'); 436 if(nFind != -1) strDstLevel = strDstLevel.Mid(nFind); 437 } 438 439 //add pending slash 440 #ifdef _WIN32 441 if(strDstLevel.Right(1) != "\\") strDstLevel += "\\"; 442 #else 443 if(strDstLevel.Right(1) != "/") strDstLevel += "/"; 444 #endif 445 446 //remove slash at the beginning of the string 447 if (strDstLevel.Left(1) == "\\" || strDstLevel.Left(1) == "/") 448 strDstLevel = strDstLevel.Right(strDstLevel.GetLength() - 1); 449 450 zipFile zf; 451 zf = zipOpen64(strZipFile, openMode); 452 if (zf) 453 { 454 vector<CStdString> _fileInfo; 455 GetFilesFromDir(strDir, _fileInfo); 456 for (size_t i = 0; i < _fileInfo.size(); ++i) 457 { 458 CStdString strFilePath = _fileInfo[i]; 459 CStdString strFileLevel; 460 int nFind = strFilePath.Find(strDir); 461 if(nFind != -1) strFileLevel = strFilePath.Mid(strlen(strDir)); 462 463 if (strFileLevel.Left(1) == "\\" || strFileLevel.Left(1) == "/") 464 strFileLevel = strFileLevel.Right(strFileLevel.GetLength() - 1); 465 466 strFileLevel = strDstLevel + strFileLevel; 467 strFileLevel.Replace("\\", "/"); 468 469 DoZipFile(zf, strFilePath.c_str(), strFileLevel.c_str()); 470 // printf("%s\n%s\n", strFilePath.c_str(), strFileLevel.c_str()); 471 } 472 473 zipClose(zf, NULL); 474 return 0; 475 } 476 477 return __LINE__; 478 } 479 480 #ifdef _TESTZIP 481 int main(int argc, char* argv[]) 482 { 483 if(argc < 2) 484 { 485 printf("Usage: %s zipfile filetozip\n", argv[0]); 486 getchar(); 487 return 1; 488 } 489 const char* szZipFile = argv[1]; 490 bool bFirst = true; 491 for(int i = 2; i < argc; ++i) 492 { 493 const char* filetozip = argv[i]; 494 DWORD dwAttr = GetFileAttributes(filetozip); 495 if(dwAttr == INVALID_FILE_ATTRIBUTES) 496 { 497 printf("invalid file name: %s\n", filetozip); 498 continue; 499 } 500 if(dwAttr & FILE_ATTRIBUTE_DIRECTORY) 501 { 502 DoZipDir(filetozip, "", szZipFile, 503 bFirst ? RG_ZIP_FILE_REPLACE : RG_ZIP_FILE_APPEND); 504 bFirst = false; 505 } 506 else if(dwAttr & FILE_ATTRIBUTE_NORMAL) 507 { 508 DoZipFile(filetozip, "", szZipFile, 509 bFirst ? RG_ZIP_FILE_REPLACE : RG_ZIP_FILE_APPEND); 510 bFirst = false; 511 } 512 } 513 514 getchar(); 515 516 return 0; 517 } 518 519 #endif
解压缩API实现,其中的CStdString可以使用CString代替,接口与CString一致。
其它涉及的代码可以下载minizip或者info-zip,推荐使用minizip,本代码是在minizip的基础上修改而来,支持跨平台
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 #ifndef _WIN32 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 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <time.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 37 #ifdef _LINUX 38 #include <unistd.h> 39 #include <utime.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #else 43 #include <direct.h> 44 #include <io.h> 45 #include <Windows.h> 46 #endif 47 48 #include "unzip.h" 49 #include "stdstring.h" 50 51 #define CASESENSITIVITY (0) 52 #define WRITEBUFFERSIZE (8192) 53 #define MAXFILENAME (256) 54 55 /* 56 #ifdef _WIN32 57 #define USEWIN32IOAPI 58 #include "iowin32.h" 59 #endif 60 */ 61 /* 62 mini unzip, demo of unzip package 63 64 usage : 65 Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] 66 67 list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT 68 if it exists 69 */ 70 71 72 /* change_file_date : change the date/time of a file 73 filename : the filename of the file where date/time must be modified 74 dosdate : the new date at the MSDos format (4 bytes) 75 tmu_date : the SAME new date at the tm_unz format */ 76 static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) 77 { 78 #ifdef _WIN32 79 HANDLE hFile; 80 FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; 81 82 hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, 83 0,NULL,OPEN_EXISTING,0,NULL); 84 GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); 85 DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); 86 LocalFileTimeToFileTime(&ftLocal,&ftm); 87 SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); 88 CloseHandle(hFile); 89 #else 90 #ifdef _LINUX 91 struct utimbuf ut; 92 struct tm newdate; 93 newdate.tm_sec = tmu_date.tm_sec; 94 newdate.tm_min=tmu_date.tm_min; 95 newdate.tm_hour=tmu_date.tm_hour; 96 newdate.tm_mday=tmu_date.tm_mday; 97 newdate.tm_mon=tmu_date.tm_mon; 98 if (tmu_date.tm_year > 1900) 99 newdate.tm_year=tmu_date.tm_year - 1900; 100 else 101 newdate.tm_year=tmu_date.tm_year ; 102 newdate.tm_isdst=-1; 103 104 ut.actime=ut.modtime=mktime(&newdate); 105 utime(filename,&ut); 106 #endif 107 #endif 108 } 109 110 111 /* mymkdir and change_file_date are not 100 % portable 112 As I don't know well Unix, I wait feedback for the unix portion */ 113 114 static int mymkdir(const char* dirname) 115 { 116 int ret=0; 117 #ifdef _WIN32 118 ret = _mkdir(dirname); 119 #else 120 #ifdef _LINUX 121 ret = mkdir (dirname,0775); 122 #endif 123 #endif 124 return ret; 125 } 126 127 int makedir (const char *newdir) 128 { 129 char *buffer ; 130 char *p; 131 int len = (int)strlen(newdir); 132 133 if (len <= 0) 134 return 0; 135 136 buffer = (char*)malloc(len+1); 137 if (buffer==NULL) 138 { 139 printf("Error allocating memory\n"); 140 return UNZ_INTERNALERROR; 141 } 142 strcpy(buffer,newdir); 143 144 if (buffer[len-1] == '/') { 145 buffer[len-1] = '\0'; 146 } 147 if (mymkdir(buffer) == 0) 148 { 149 free(buffer); 150 return 1; 151 } 152 153 p = buffer+1; 154 while (1) 155 { 156 char hold; 157 158 while(*p && *p != '\\' && *p != '/') 159 p++; 160 hold = *p; 161 *p = 0; 162 if ((mymkdir(buffer) == -1) && (errno == ENOENT)) 163 { 164 printf("couldn't create directory %s\n",buffer); 165 free(buffer); 166 return 0; 167 } 168 if (hold == 0) 169 break; 170 *p++ = hold; 171 } 172 free(buffer); 173 return 1; 174 } 175 176 static int do_extract_currentfile(unzFile uf, const char* password) 177 { 178 char filename_inzip[256]; 179 char* filename_withoutpath; 180 char* p; 181 int err=UNZ_OK; 182 FILE *fout=NULL; 183 void* buf; 184 uInt size_buf; 185 186 unz_file_info64 file_info; 187 uLong ratio=0; 188 err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0); 189 190 if (err!=UNZ_OK) 191 { 192 printf("error %d with zipfile in unzGetCurrentFileInfo\n",err); 193 return err; 194 } 195 196 size_buf = WRITEBUFFERSIZE; 197 buf = (void*)malloc(size_buf); 198 if (buf==NULL) 199 { 200 printf("Error allocating memory\n"); 201 return UNZ_INTERNALERROR; 202 } 203 204 p = filename_withoutpath = filename_inzip; 205 while ((*p) != '\0') 206 { 207 if (((*p)=='/') || ((*p)=='\\')) 208 filename_withoutpath = p+1; 209 p++; 210 } 211 212 if ((*filename_withoutpath)=='\0') 213 { 214 mymkdir(filename_inzip); 215 } 216 else 217 { 218 const char* write_filename; 219 220 write_filename = filename_inzip; 221 222 err = unzOpenCurrentFilePassword(uf,password); 223 if (err==UNZ_OK) 224 { 225 fout=fopen64(write_filename,"wb"); 226 227 /* some zipfile don't contain directory alone before file */ 228 if ((fout==NULL) && 229 (filename_withoutpath!=(char*)filename_inzip)) 230 { 231 char c=*(filename_withoutpath-1); 232 *(filename_withoutpath-1)='\0'; 233 makedir(write_filename); 234 *(filename_withoutpath-1)=c; 235 fout=fopen64(write_filename,"wb"); 236 } 237 238 if (fout==NULL) 239 { 240 printf("error opening %s\n",write_filename); 241 } 242 } 243 else 244 { 245 printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err); 246 } 247 248 if (fout!=NULL) 249 { 250 do 251 { 252 err = unzReadCurrentFile(uf,buf,size_buf); 253 if (err<0) 254 { 255 printf("error %d with zipfile in unzReadCurrentFile\n",err); 256 break; 257 } 258 if (err>0) 259 if (fwrite(buf,err,1,fout)!=1) 260 { 261 printf("error in writing extracted file\n"); 262 err=UNZ_ERRNO; 263 break; 264 } 265 } 266 while (err>0); 267 if (fout) 268 fclose(fout); 269 270 if (err==UNZ_OK) 271 change_file_date(write_filename,file_info.dosDate, 272 file_info.tmu_date); 273 } 274 275 if (err==UNZ_OK) 276 { 277 err = unzCloseCurrentFile (uf); 278 if (err!=UNZ_OK) 279 { 280 printf("error %d with zipfile in unzCloseCurrentFile\n",err); 281 } 282 } 283 else 284 unzCloseCurrentFile(uf); /* don't lose the error */ 285 } 286 287 free(buf); 288 return err; 289 } 290 291 292 static int do_extract(unzFile uf, const char* password) 293 { 294 uLong i; 295 unz_global_info64 gi; 296 int err; 297 FILE* fout=NULL; 298 299 err = unzGetGlobalInfo64(uf,&gi); 300 if (err!=UNZ_OK) 301 printf("error %d with zipfile in unzGetGlobalInfo \n",err); 302 303 for (i=0;i<gi.number_entry;i++) 304 { 305 if (do_extract_currentfile(uf, password) != UNZ_OK) 306 break; 307 308 if ((i+1) < gi.number_entry) 309 { 310 err = unzGoToNextFile(uf); 311 if (err!=UNZ_OK) 312 { 313 printf("error %d with zipfile in unzGoToNextFile\n",err); 314 break; 315 } 316 } 317 } 318 319 return 0; 320 } 321 322 static int do_extract_onefile(unzFile uf, const char* filename, const char* password) 323 { 324 int err = UNZ_OK; 325 if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK) 326 { 327 printf("file %s not found in the zipfile\n",filename); 328 return 2; 329 } 330 331 if (do_extract_currentfile(uf, password) == UNZ_OK) 332 return 0; 333 else 334 return 1; 335 } 336 337 338 int DoUnzip(const char* szZipFile, const char* szTargetDir) 339 { 340 if (szZipFile == NULL) 341 { 342 return __LINE__; 343 } 344 345 CStdString dirname; 346 if(szTargetDir) dirname = szTargetDir; 347 dirname.Trim(); 348 349 unzFile uf = unzOpen64(szZipFile); 350 if (uf) 351 { 352 #ifdef _WIN32 353 if (!dirname.IsEmpty() && _chdir(dirname.c_str())) 354 #else 355 if (!dirname.IsEmpty() && chdir(dirname.c_str())) 356 #endif 357 { 358 printf("Error changing into %s, aborting\n", dirname.c_str()); 359 return __LINE__; 360 } 361 362 do_extract(uf, NULL); 363 364 unzClose(uf); 365 return 0; 366 } 367 368 return __LINE__; 369 } 370 371 int DoUnzipFile(const char* szZipFile, const char* srcFileToExtract, const char* szTargetDir) 372 { 373 if (szZipFile == NULL) 374 { 375 return __LINE__; 376 } 377 378 CStdString dirname; 379 if(szTargetDir) dirname = szTargetDir; 380 dirname.Trim(); 381 382 unzFile uf = unzOpen64(szZipFile); 383 if (uf) 384 { 385 #ifdef _WIN32 386 if (!dirname.IsEmpty() && _chdir(dirname.c_str())) 387 #else 388 if (!dirname.IsEmpty() && chdir(dirname.c_str())) 389 #endif 390 { 391 printf("Error changing into %s, aborting\n", dirname.c_str()); 392 return __LINE__; 393 } 394 395 do_extract_onefile(uf, srcFileToExtract, NULL); 396 397 unzClose(uf); 398 return 0; 399 } 400 401 return __LINE__; 402 } 403 404 #ifdef _TESTUNZIP 405 int main(int argc, char* argv[]) 406 { 407 if(argc < 1) 408 { 409 printf("Usage: %s zipfile\n", argv[0]); 410 return 1; 411 } 412 413 bool bExtractSingalFile = false; 414 for(int i = 1; i < argc; ++i) 415 { 416 if(strcmp(argv[i], "-s") == 0) 417 { 418 if(i + 1 < argc) 419 { 420 i++; 421 const char* filetoextract = argv[i]; 422 printf("extract singal file %s\n", filetoextract); 423 i++; 424 if(i < argc) 425 { 426 DoUnzipFile(argv[i++], filetoextract, NULL); 427 } 428 } 429 } 430 else 431 DoUnzip(argv[i], NULL); 432 } 433 434 return 0; 435 } 436 #endif