cannam@89: /* cannam@89: miniunz.c cannam@89: Version 1.1, February 14h, 2010 cannam@89: sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) cannam@89: cannam@89: Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) cannam@89: cannam@89: Modifications of Unzip for Zip64 cannam@89: Copyright (C) 2007-2008 Even Rouault cannam@89: cannam@89: Modifications for Zip64 support on both zip and unzip cannam@89: Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) cannam@89: */ cannam@89: cannam@89: #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) cannam@89: #ifndef __USE_FILE_OFFSET64 cannam@89: #define __USE_FILE_OFFSET64 cannam@89: #endif cannam@89: #ifndef __USE_LARGEFILE64 cannam@89: #define __USE_LARGEFILE64 cannam@89: #endif cannam@89: #ifndef _LARGEFILE64_SOURCE cannam@89: #define _LARGEFILE64_SOURCE cannam@89: #endif cannam@89: #ifndef _FILE_OFFSET_BIT cannam@89: #define _FILE_OFFSET_BIT 64 cannam@89: #endif cannam@89: #endif cannam@89: cannam@89: #ifdef __APPLE__ cannam@89: // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions cannam@89: #define FOPEN_FUNC(filename, mode) fopen(filename, mode) cannam@89: #define FTELLO_FUNC(stream) ftello(stream) cannam@89: #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) cannam@89: #else cannam@89: #define FOPEN_FUNC(filename, mode) fopen64(filename, mode) cannam@89: #define FTELLO_FUNC(stream) ftello64(stream) cannam@89: #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) cannam@89: #endif cannam@89: cannam@89: cannam@89: #include cannam@89: #include cannam@89: #include cannam@89: #include cannam@89: #include cannam@89: #include cannam@89: cannam@89: #ifdef _WIN32 cannam@89: # include cannam@89: # include cannam@89: #else cannam@89: # include cannam@89: # include cannam@89: #endif cannam@89: cannam@89: cannam@89: #include "unzip.h" cannam@89: cannam@89: #define CASESENSITIVITY (0) cannam@89: #define WRITEBUFFERSIZE (8192) cannam@89: #define MAXFILENAME (256) cannam@89: cannam@89: #ifdef _WIN32 cannam@89: #define USEWIN32IOAPI cannam@89: #include "iowin32.h" cannam@89: #endif cannam@89: /* cannam@89: mini unzip, demo of unzip package cannam@89: cannam@89: usage : cannam@89: Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] cannam@89: cannam@89: list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT cannam@89: if it exists cannam@89: */ cannam@89: cannam@89: cannam@89: /* change_file_date : change the date/time of a file cannam@89: filename : the filename of the file where date/time must be modified cannam@89: dosdate : the new date at the MSDos format (4 bytes) cannam@89: tmu_date : the SAME new date at the tm_unz format */ cannam@89: void change_file_date(filename,dosdate,tmu_date) cannam@89: const char *filename; cannam@89: uLong dosdate; cannam@89: tm_unz tmu_date; cannam@89: { cannam@89: #ifdef _WIN32 cannam@89: HANDLE hFile; cannam@89: FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; cannam@89: cannam@89: hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, cannam@89: 0,NULL,OPEN_EXISTING,0,NULL); cannam@89: GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); cannam@89: DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); cannam@89: LocalFileTimeToFileTime(&ftLocal,&ftm); cannam@89: SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); cannam@89: CloseHandle(hFile); cannam@89: #else cannam@89: #ifdef unix || __APPLE__ cannam@89: struct utimbuf ut; cannam@89: struct tm newdate; cannam@89: newdate.tm_sec = tmu_date.tm_sec; cannam@89: newdate.tm_min=tmu_date.tm_min; cannam@89: newdate.tm_hour=tmu_date.tm_hour; cannam@89: newdate.tm_mday=tmu_date.tm_mday; cannam@89: newdate.tm_mon=tmu_date.tm_mon; cannam@89: if (tmu_date.tm_year > 1900) cannam@89: newdate.tm_year=tmu_date.tm_year - 1900; cannam@89: else cannam@89: newdate.tm_year=tmu_date.tm_year ; cannam@89: newdate.tm_isdst=-1; cannam@89: cannam@89: ut.actime=ut.modtime=mktime(&newdate); cannam@89: utime(filename,&ut); cannam@89: #endif cannam@89: #endif cannam@89: } cannam@89: cannam@89: cannam@89: /* mymkdir and change_file_date are not 100 % portable cannam@89: As I don't know well Unix, I wait feedback for the unix portion */ cannam@89: cannam@89: int mymkdir(dirname) cannam@89: const char* dirname; cannam@89: { cannam@89: int ret=0; cannam@89: #ifdef _WIN32 cannam@89: ret = _mkdir(dirname); cannam@89: #elif unix cannam@89: ret = mkdir (dirname,0775); cannam@89: #elif __APPLE__ cannam@89: ret = mkdir (dirname,0775); cannam@89: #endif cannam@89: return ret; cannam@89: } cannam@89: cannam@89: int makedir (newdir) cannam@89: char *newdir; cannam@89: { cannam@89: char *buffer ; cannam@89: char *p; cannam@89: int len = (int)strlen(newdir); cannam@89: cannam@89: if (len <= 0) cannam@89: return 0; cannam@89: cannam@89: buffer = (char*)malloc(len+1); cannam@89: if (buffer==NULL) cannam@89: { cannam@89: printf("Error allocating memory\n"); cannam@89: return UNZ_INTERNALERROR; cannam@89: } cannam@89: strcpy(buffer,newdir); cannam@89: cannam@89: if (buffer[len-1] == '/') { cannam@89: buffer[len-1] = '\0'; cannam@89: } cannam@89: if (mymkdir(buffer) == 0) cannam@89: { cannam@89: free(buffer); cannam@89: return 1; cannam@89: } cannam@89: cannam@89: p = buffer+1; cannam@89: while (1) cannam@89: { cannam@89: char hold; cannam@89: cannam@89: while(*p && *p != '\\' && *p != '/') cannam@89: p++; cannam@89: hold = *p; cannam@89: *p = 0; cannam@89: if ((mymkdir(buffer) == -1) && (errno == ENOENT)) cannam@89: { cannam@89: printf("couldn't create directory %s\n",buffer); cannam@89: free(buffer); cannam@89: return 0; cannam@89: } cannam@89: if (hold == 0) cannam@89: break; cannam@89: *p++ = hold; cannam@89: } cannam@89: free(buffer); cannam@89: return 1; cannam@89: } cannam@89: cannam@89: void do_banner() cannam@89: { cannam@89: printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); cannam@89: printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); cannam@89: } cannam@89: cannam@89: void do_help() cannam@89: { cannam@89: printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ cannam@89: " -e Extract without pathname (junk paths)\n" \ cannam@89: " -x Extract with pathname\n" \ cannam@89: " -v list files\n" \ cannam@89: " -l list files\n" \ cannam@89: " -d directory to extract into\n" \ cannam@89: " -o overwrite files without prompting\n" \ cannam@89: " -p extract crypted file using password\n\n"); cannam@89: } cannam@89: cannam@89: void Display64BitsSize(ZPOS64_T n, int size_char) cannam@89: { cannam@89: /* to avoid compatibility problem , we do here the conversion */ cannam@89: char number[21]; cannam@89: int offset=19; cannam@89: int pos_string = 19; cannam@89: number[20]=0; cannam@89: for (;;) { cannam@89: number[offset]=(char)((n%10)+'0'); cannam@89: if (number[offset] != '0') cannam@89: pos_string=offset; cannam@89: n/=10; cannam@89: if (offset==0) cannam@89: break; cannam@89: offset--; cannam@89: } cannam@89: { cannam@89: int size_display_string = 19-pos_string; cannam@89: while (size_char > size_display_string) cannam@89: { cannam@89: size_char--; cannam@89: printf(" "); cannam@89: } cannam@89: } cannam@89: cannam@89: printf("%s",&number[pos_string]); cannam@89: } cannam@89: cannam@89: int do_list(uf) cannam@89: unzFile uf; cannam@89: { cannam@89: uLong i; cannam@89: unz_global_info64 gi; cannam@89: int err; cannam@89: cannam@89: err = unzGetGlobalInfo64(uf,&gi); cannam@89: if (err!=UNZ_OK) cannam@89: printf("error %d with zipfile in unzGetGlobalInfo \n",err); cannam@89: printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); cannam@89: printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); cannam@89: for (i=0;i0) cannam@89: ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); cannam@89: cannam@89: /* display a '*' if the file is crypted */ cannam@89: if ((file_info.flag & 1) != 0) cannam@89: charCrypt='*'; cannam@89: cannam@89: if (file_info.compression_method==0) cannam@89: string_method="Stored"; cannam@89: else cannam@89: if (file_info.compression_method==Z_DEFLATED) cannam@89: { cannam@89: uInt iLevel=(uInt)((file_info.flag & 0x6)/2); cannam@89: if (iLevel==0) cannam@89: string_method="Defl:N"; cannam@89: else if (iLevel==1) cannam@89: string_method="Defl:X"; cannam@89: else if ((iLevel==2) || (iLevel==3)) cannam@89: string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ cannam@89: } cannam@89: else cannam@89: if (file_info.compression_method==Z_BZIP2ED) cannam@89: { cannam@89: string_method="BZip2 "; cannam@89: } cannam@89: else cannam@89: string_method="Unkn. "; cannam@89: cannam@89: Display64BitsSize(file_info.uncompressed_size,7); cannam@89: printf(" %6s%c",string_method,charCrypt); cannam@89: Display64BitsSize(file_info.compressed_size,7); cannam@89: printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", cannam@89: ratio, cannam@89: (uLong)file_info.tmu_date.tm_mon + 1, cannam@89: (uLong)file_info.tmu_date.tm_mday, cannam@89: (uLong)file_info.tmu_date.tm_year % 100, cannam@89: (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, cannam@89: (uLong)file_info.crc,filename_inzip); cannam@89: if ((i+1)='a') && (rep<='z')) cannam@89: rep -= 0x20; cannam@89: } cannam@89: while ((rep!='Y') && (rep!='N') && (rep!='A')); cannam@89: } cannam@89: cannam@89: if (rep == 'N') cannam@89: skip = 1; cannam@89: cannam@89: if (rep == 'A') cannam@89: *popt_overwrite=1; cannam@89: } cannam@89: cannam@89: if ((skip==0) && (err==UNZ_OK)) cannam@89: { cannam@89: fout=FOPEN_FUNC(write_filename,"wb"); cannam@89: /* some zipfile don't contain directory alone before file */ cannam@89: if ((fout==NULL) && ((*popt_extract_without_path)==0) && cannam@89: (filename_withoutpath!=(char*)filename_inzip)) cannam@89: { cannam@89: char c=*(filename_withoutpath-1); cannam@89: *(filename_withoutpath-1)='\0'; cannam@89: makedir(write_filename); cannam@89: *(filename_withoutpath-1)=c; cannam@89: fout=FOPEN_FUNC(write_filename,"wb"); cannam@89: } cannam@89: cannam@89: if (fout==NULL) cannam@89: { cannam@89: printf("error opening %s\n",write_filename); cannam@89: } cannam@89: } cannam@89: cannam@89: if (fout!=NULL) cannam@89: { cannam@89: printf(" extracting: %s\n",write_filename); cannam@89: cannam@89: do cannam@89: { cannam@89: err = unzReadCurrentFile(uf,buf,size_buf); cannam@89: if (err<0) cannam@89: { cannam@89: printf("error %d with zipfile in unzReadCurrentFile\n",err); cannam@89: break; cannam@89: } cannam@89: if (err>0) cannam@89: if (fwrite(buf,err,1,fout)!=1) cannam@89: { cannam@89: printf("error in writing extracted file\n"); cannam@89: err=UNZ_ERRNO; cannam@89: break; cannam@89: } cannam@89: } cannam@89: while (err>0); cannam@89: if (fout) cannam@89: fclose(fout); cannam@89: cannam@89: if (err==0) cannam@89: change_file_date(write_filename,file_info.dosDate, cannam@89: file_info.tmu_date); cannam@89: } cannam@89: cannam@89: if (err==UNZ_OK) cannam@89: { cannam@89: err = unzCloseCurrentFile (uf); cannam@89: if (err!=UNZ_OK) cannam@89: { cannam@89: printf("error %d with zipfile in unzCloseCurrentFile\n",err); cannam@89: } cannam@89: } cannam@89: else cannam@89: unzCloseCurrentFile(uf); /* don't lose the error */ cannam@89: } cannam@89: cannam@89: free(buf); cannam@89: return err; cannam@89: } cannam@89: cannam@89: cannam@89: int do_extract(uf,opt_extract_without_path,opt_overwrite,password) cannam@89: unzFile uf; cannam@89: int opt_extract_without_path; cannam@89: int opt_overwrite; cannam@89: const char* password; cannam@89: { cannam@89: uLong i; cannam@89: unz_global_info64 gi; cannam@89: int err; cannam@89: FILE* fout=NULL; cannam@89: cannam@89: err = unzGetGlobalInfo64(uf,&gi); cannam@89: if (err!=UNZ_OK) cannam@89: printf("error %d with zipfile in unzGetGlobalInfo \n",err); cannam@89: cannam@89: for (i=0;i