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