Move two minizip functions from filetools.cpp to its own file minizip/zipunzip.cpp, covered by minizip's original license

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20025 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Bo Peng 2007-09-03 21:09:11 +00:00
parent 9a95d2a936
commit 22ce34e5d5
7 changed files with 556 additions and 433 deletions

View File

@ -431,6 +431,7 @@ src_support_minizip_files = Split('''
ioapi.c ioapi.c
iowin32.c iowin32.c
zip.c zip.c
zipunzip.cpp
unzip.c unzip.c
''') ''')

View File

@ -134,7 +134,6 @@ using support::subst;
using support::tempName; using support::tempName;
using support::trim; using support::trim;
using support::sum; using support::sum;
using support::unzipToDir;
namespace Alert = frontend::Alert; namespace Alert = frontend::Alert;
namespace os = support::os; namespace os = support::os;
@ -658,7 +657,7 @@ bool Buffer::readFile(FileName const & filename)
if (format == "zip") { if (format == "zip") {
// decompress to a temp directory // decompress to a temp directory
LYXERR(Debug::FILES) << filename << " is in zip format. Unzip to " << temppath() << endl; LYXERR(Debug::FILES) << filename << " is in zip format. Unzip to " << temppath() << endl;
unzipToDir(filename.toFilesystemEncoding(), temppath()); ::unzipToDir(filename.toFilesystemEncoding(), temppath());
// //
FileName manifest(addName(temppath(), "manifest.txt")); FileName manifest(addName(temppath(), "manifest.txt"));
FileName lyxfile(addName(temppath(), FileName lyxfile(addName(temppath(),

View File

@ -61,7 +61,6 @@ using support::onlyFilename;
using support::makeRelPath; using support::makeRelPath;
using support::changeExtension; using support::changeExtension;
using support::bformat; using support::bformat;
using support::zipFiles;
using support::prefixIs; using support::prefixIs;
using support::sum; using support::sum;
using support::makedir; using support::makedir;
@ -261,7 +260,7 @@ bool EmbeddedFiles::write(DocFileName const & filename)
onlyFilename(changeExtension( onlyFilename(changeExtension(
filename.toFilesystemEncoding(), ".zip")))); filename.toFilesystemEncoding(), ".zip"))));
zipFiles(zipfile, filenames); ::zipFiles(zipfile.toFilesystemEncoding(), filenames);
// copy file back // copy file back
try { try {
fs::copy_file(zipfile.toFilesystemEncoding(), filename.toFilesystemEncoding(), false); fs::copy_file(zipfile.toFilesystemEncoding(), filename.toFilesystemEncoding(), false);

View File

@ -101,7 +101,8 @@ liblyxsupport_la_SOURCES = \
minizip/unzip.c \ minizip/unzip.c \
minizip/unzip.h \ minizip/unzip.h \
minizip/zip.c \ minizip/zip.c \
minizip/zip.h minizip/zip.h \
minizip/zipunzip.cpp
############################## Tests ################################## ############################## Tests ##################################

View File

@ -50,44 +50,6 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_DIRECT_H
# include <direct.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_SYS_UTIME_H
# include <sys/utime.h>
#endif
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
#include "zip.h"
#include "unzip.h"
#ifdef WIN32
#define USEWIN32IOAPI
#include "iowin32.h"
#endif
#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)
#ifndef CXX_GLOBAL_CSTD
using std::fgetc;
#endif
using std::endl; using std::endl;
using std::getline; using std::getline;
using std::make_pair; using std::make_pair;
@ -1285,392 +1247,5 @@ int compare_timestamps(FileName const & filename1, FileName const & filename2)
return cmp; return cmp;
} }
// the following is adapted from zlib-1.2.3/contrib/minizip.c
// and miniunz.c, except that
// 1. mkdir, makedir is replaced by lyx' own version
// 2. printf is replaced by lyxerr
#ifdef WIN32
uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
{
int ret = 0;
{
FILETIME ftLocal;
HANDLE hFind;
WIN32_FIND_DATA ff32;
hFind = FindFirstFile(f,&ff32);
if (hFind != INVALID_HANDLE_VALUE)
{
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
FindClose(hFind);
ret = 1;
}
}
return ret;
}
#else
#ifdef unix
uLong filetime(const char * f, tm_zip * tmzip, uLong * /*dt*/)
{
int ret=0;
struct stat s; /* results of stat() */
struct tm* filedate;
time_t tm_t=0;
if (strcmp(f,"-")!=0) {
char name[MAXFILENAME+1];
int len = strlen(f);
if (len > MAXFILENAME)
len = MAXFILENAME;
strncpy(name, f,MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */
name[ MAXFILENAME ] = '\0';
if (name[len - 1] == '/')
name[len - 1] = '\0';
/* not all systems allow stat'ing a file with / appended */
if (stat(name,&s)==0) {
tm_t = s.st_mtime;
ret = 1;
}
}
filedate = localtime(&tm_t);
tmzip->tm_sec = filedate->tm_sec;
tmzip->tm_min = filedate->tm_min;
tmzip->tm_hour = filedate->tm_hour;
tmzip->tm_mday = filedate->tm_mday;
tmzip->tm_mon = filedate->tm_mon ;
tmzip->tm_year = filedate->tm_year;
return ret;
}
#else
uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
{
return 0;
}
#endif
#endif
bool zipFiles(DocFileName const & zipfile, vector<pair<string, string> > const & files)
{
int err = 0;
zipFile zf;
int errclose;
void * buf = NULL;
int size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf);
if (buf==NULL) {
lyxerr << "Error allocating memory" << endl;
return false;
}
string const zfile = zipfile.toFilesystemEncoding();
const char * fname = zfile.c_str();
#ifdef USEWIN32IOAPI
zlib_filefunc_def ffunc;
fill_win32_filefunc(&ffunc);
// false: not append
zf = zipOpen2(fname, false, NULL, &ffunc);
#else
zf = zipOpen(fname, false);
#endif
if (zf == NULL) {
lyxerr << "error opening " << zipfile << endl;
return false;
}
for (vector<pair<string, string> >::const_iterator it = files.begin(); it != files.end(); ++it) {
FILE * fin;
int size_read;
zip_fileinfo zi;
const char * diskfilename = it->first.c_str();
const char * filenameinzip = it->second.c_str();
unsigned long crcFile=0;
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0;
zi.internal_fa = 0;
zi.external_fa = 0;
filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);
err = zipOpenNewFileInZip3(zf, filenameinzip, &zi,
NULL,0,NULL,0,NULL /* comment*/,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION, // compression level
0,
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
NULL, // password,
crcFile);
if (err != ZIP_OK) {
lyxerr << "error in opening " << filenameinzip << " in zipfile" << endl;
return false;
}
fin = fopen(diskfilename, "rb");
if (fin==NULL) {
lyxerr << "error in opening " << diskfilename << " for reading" << endl;
return false;
}
do {
err = ZIP_OK;
size_read = (int)fread(buf, 1, size_buf, fin);
if (size_read < size_buf)
if (feof(fin)==0) {
lyxerr << "error in reading " << filenameinzip << endl;
return false;
}
if (size_read>0) {
err = zipWriteInFileInZip (zf, buf, size_read);
if (err<0) {
lyxerr << "error in writing " << filenameinzip << " in the zipfile" << endl;
return false;
}
}
} while ((err == ZIP_OK) && (size_read>0));
if (fin)
fclose(fin);
err = zipCloseFileInZip(zf);
if (err != ZIP_OK) {
lyxerr << "error in closing " << filenameinzip << "in the zipfile" << endl;
return false;
}
}
errclose = zipClose(zf, NULL);
if (errclose != ZIP_OK) {
lyxerr << "error in closing " << zipfile << endl;
return false;
}
free(buf);
return true;
}
// adapted from miniunz.c
/* 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(const char * filename, uLong dosdate, tm_unz tmu_date)
{
#ifdef WIN32
HANDLE hFile;
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
hFile = CreateFile(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
utimbuf ut;
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
}
int do_extract_currentfile(unzFile uf,
const int * popt_extract_without_path,
int * popt_overwrite,
const char * password,
const char * dirname)
{
char filename_inzip[256];
char* filename_withoutpath;
char* p;
int err=UNZ_OK;
FILE *fout=NULL;
void* buf;
uInt size_buf;
unz_file_info file_info;
//uLong ratio=0;
err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
if (err!=UNZ_OK) {
lyxerr << "error " << err << " with zipfile in unzGetCurrentFileInfo" << endl;
return err;
}
size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf);
if (buf==NULL) {
lyxerr << "Error allocating memory" << endl;
return UNZ_INTERNALERROR;
}
p = filename_withoutpath = filename_inzip;
while ((*p) != '\0') {
if (((*p)=='/') || ((*p)=='\\'))
filename_withoutpath = p+1;
p++;
}
// this is a directory
if ((*filename_withoutpath)=='\0') {
if ((*popt_extract_without_path)==0)
makedir(filename_inzip);
}
// this is a filename
else {
char write_filename[1024];
strcpy(write_filename, dirname);
int len = strlen(write_filename);
if (write_filename[len-1] != '\\' &&
write_filename[len-1] != '/')
strcat(write_filename, "/");
if ((*popt_extract_without_path)==0)
strcat(write_filename, filename_inzip);
else
strcat(write_filename, filename_withoutpath);
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK) {
lyxerr << "error " << err << " with zipfile in unzOpenCurrentFilePassword" << endl;
} else {
fout=fopen(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=fopen(write_filename,"wb");
}
if (fout==NULL) {
lyxerr << "error opening " << write_filename << endl;
}
}
if (fout!=NULL) {
LYXERR(Debug::FILES) << " extracting: " << write_filename << endl;
do {
err = unzReadCurrentFile(uf,buf,size_buf);
if (err<0) {
lyxerr << "error " << err << " with zipfile in unzReadCurrentFile" << endl;
break;
}
if (err>0)
if (fwrite(buf,err,1,fout)!=1) {
lyxerr << "error in writing extracted file" << endl;
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) {
lyxerr << "error " << err << " with zipfile in unzCloseCurrentFile" << endl;
}
}
else
unzCloseCurrentFile(uf); /* don't lose the error */
}
free(buf);
return err;
}
bool unzipToDir(string const & zipfile, string const & dirname)
{
unzFile uf=NULL;
#ifdef USEWIN32IOAPI
zlib_filefunc_def ffunc;
#endif
const char * zipfilename = zipfile.c_str();
#ifdef USEWIN32IOAPI
fill_win32_filefunc(&ffunc);
uf = unzOpen2(zipfilename, &ffunc);
#else
uf = unzOpen(zipfilename);
#endif
if (uf==NULL) {
lyxerr << "Cannot open " << zipfile << " or " << zipfile << ".zip" << endl;
return false;
}
uLong i;
unz_global_info gi;
int err;
//FILE* fout=NULL;
int opt_extract_without_path = 0;
int opt_overwrite = 1;
char * password = NULL;
err = unzGetGlobalInfo (uf, &gi);
if (err != UNZ_OK) {
lyxerr << "error " << err << " with zipfile in unzGetGlobalInfo " << endl;
return false;
}
for (i=0; i < gi.number_entry; i++) {
if (do_extract_currentfile(uf, &opt_extract_without_path,
&opt_overwrite,
password, dirname.c_str()) != UNZ_OK)
break;
if ((i+1)<gi.number_entry) {
err = unzGoToNextFile(uf);
if (err != UNZ_OK) {
lyxerr << "error " << err << " with zipfile in unzGoToNextFile" << endl;;
break;
}
}
}
unzCloseCurrentFile(uf);
return true;
}
} //namespace support } //namespace support
} // namespace lyx } // namespace lyx

View File

@ -314,13 +314,17 @@ typedef std::pair<int, std::string> cmd_ret;
cmd_ret const runCommand(std::string const & cmd); cmd_ret const runCommand(std::string const & cmd);
} // namespace support
} // namespace lyx
/// The following functions are implemented in minizip/zipunzip.cpp, and are not in
/// the lyx::support namespace
/// zip several files to a zipfile. In-zip filenames are also specified /// zip several files to a zipfile. In-zip filenames are also specified
bool zipFiles(DocFileName const & zipfile, std::vector<std::pair<std::string, std::string> > const & files); bool zipFiles(std::string const & zipfile, std::vector<std::pair<std::string, std::string> > const & files);
/// Unzip a zip file to a directory /// Unzip a zip file to a directory
bool unzipToDir(std::string const & zipfile, std::string const & path); bool unzipToDir(std::string const & zipfile, std::string const & path);
} // namespace support
} // namespace lyx
#endif #endif

View File

@ -0,0 +1,544 @@
/* zipunzip.cpp -- IO for compress .zip files using zlib
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible.
Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported
For uncompress .zip file, look at unzip.h
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
http://www.info-zip.org/pub/infozip/doc/
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip
*/
// The original minizip.c and miniunz.c distributed with minizip provide
// two command line tools minizip and miniunz. This file combines these two
// files and modifies the interface to provide two functions zipFiles and
// unzipToDir. This file is covered by the original minizip license.
//
#include <config.h>
#include <string>
#include <vector>
#include <utility>
using std::string;
using std::vector;
using std::pair;
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_DIRECT_H
# include <direct.h>
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_SYS_UTIME_H
# include <sys/utime.h>
#endif
#ifdef HAVE_UTIME_H
# include <utime.h>
#endif
#include <fcntl.h>
#include "zip.h"
#include "unzip.h"
#ifdef WIN32
#define USEWIN32IOAPI
#include "iowin32.h"
#endif
#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)
#ifndef CXX_GLOBAL_CSTD
using std::fgetc;
#endif
#ifdef WIN32
uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
{
int ret = 0;
{
FILETIME ftLocal;
HANDLE hFind;
WIN32_FIND_DATA ff32;
hFind = FindFirstFile(f,&ff32);
if (hFind != INVALID_HANDLE_VALUE)
{
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
FindClose(hFind);
ret = 1;
}
}
return ret;
}
#else
#ifdef unix
uLong filetime(const char * f, tm_zip * tmzip, uLong * /*dt*/)
{
int ret=0;
struct stat s; /* results of stat() */
struct tm* filedate;
time_t tm_t=0;
if (strcmp(f,"-")!=0) {
char name[MAXFILENAME+1];
int len = strlen(f);
if (len > MAXFILENAME)
len = MAXFILENAME;
strncpy(name, f,MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */
name[ MAXFILENAME ] = '\0';
if (name[len - 1] == '/')
name[len - 1] = '\0';
/* not all systems allow stat'ing a file with / appended */
if (stat(name,&s)==0) {
tm_t = s.st_mtime;
ret = 1;
}
}
filedate = localtime(&tm_t);
tmzip->tm_sec = filedate->tm_sec;
tmzip->tm_min = filedate->tm_min;
tmzip->tm_hour = filedate->tm_hour;
tmzip->tm_mday = filedate->tm_mday;
tmzip->tm_mon = filedate->tm_mon ;
tmzip->tm_year = filedate->tm_year;
return ret;
}
#else
uLong filetime(const char * f, tm_zip * tmzip, uLong * dt)
{
return 0;
}
#endif
#endif
bool zipFiles(string const & zipfile, vector<pair<string, string> > const & files)
{
int err = 0;
zipFile zf;
int errclose;
void * buf = NULL;
int size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf);
if (buf==NULL) {
printf("Error allocating memory\n");
return false;
}
const char * fname = zipfile.c_str();
#ifdef USEWIN32IOAPI
zlib_filefunc_def ffunc;
fill_win32_filefunc(&ffunc);
// false: not append
zf = zipOpen2(fname, false, NULL, &ffunc);
#else
zf = zipOpen(fname, false);
#endif
if (zf == NULL) {
return false;
}
for (vector<pair<string, string> >::const_iterator it = files.begin(); it != files.end(); ++it) {
FILE * fin;
int size_read;
zip_fileinfo zi;
const char * diskfilename = it->first.c_str();
const char * filenameinzip = it->second.c_str();
unsigned long crcFile=0;
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0;
zi.internal_fa = 0;
zi.external_fa = 0;
filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);
err = zipOpenNewFileInZip3(zf, filenameinzip, &zi,
NULL,0,NULL,0,NULL /* comment*/,
Z_DEFLATED,
Z_DEFAULT_COMPRESSION, // compression level
0,
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
NULL, // password,
crcFile);
if (err != ZIP_OK) {
printf("error in opening %s in zipfile\n",filenameinzip);
return false;
}
fin = fopen(diskfilename, "rb");
if (fin==NULL) {
return false;
}
do {
err = ZIP_OK;
size_read = (int)fread(buf, 1, size_buf, fin);
if (size_read < size_buf)
if (feof(fin)==0) {
printf("error in reading %s\n",filenameinzip);
return false;
}
if (size_read>0) {
err = zipWriteInFileInZip (zf, buf, size_read);
if (err<0) {
printf("error in writing %s in the zipfile\n",
filenameinzip);
return false;
}
}
} while ((err == ZIP_OK) && (size_read>0));
if (fin)
fclose(fin);
err = zipCloseFileInZip(zf);
if (err != ZIP_OK) {
printf("error in closing %s in the zipfile\n",
filenameinzip);
return false;
}
}
errclose = zipClose(zf, NULL);
if (errclose != ZIP_OK) {
printf("error in closing zip file\n");
return false;
}
free(buf);
return true;
}
// adapted from miniunz.c
int mymkdir(char const * pathname, unsigned long int mode)
{
#if HAVE_MKDIR
# if MKDIR_TAKES_ONE_ARG
// MinGW32
return ::mkdir(pathname);
# else
// POSIX
return ::mkdir(pathname, mode_t(mode));
# endif
#elif defined(_WIN32)
// plain Windows 32
return CreateDirectory(pathname, 0) != 0 ? 0 : -1;
#elif HAVE__MKDIR
return ::_mkdir(pathname);
#else
# error "Don't know how to create a directory on this system."
#endif
}
int makedir(char * newdir)
{
char *buffer;
char *p;
int len = (int)strlen(newdir);
int mode = 0775;
if (len <= 0)
return 1;
buffer = (char*)malloc(len+1);
strcpy(buffer,newdir);
if (buffer[len-1] == '/')
buffer[len-1] = '\0';
if (mymkdir(buffer, mode) == 0) {
free(buffer);
return 0;
}
p = buffer + 1;
while (1) {
char hold;
while(*p && *p != '\\' && *p != '/')
p++;
hold = *p;
*p = 0;
if (mymkdir(buffer, mode) != 0) {
printf("couldn't create directory %s\n",buffer);
free(buffer);
return 1;
}
if (hold == 0)
break;
*p++ = hold;
}
free(buffer);
return 0;
}
/* 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(const char * filename, uLong dosdate, tm_unz tmu_date)
{
#ifdef WIN32
HANDLE hFile;
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
hFile = CreateFile(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
utimbuf ut;
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
}
int do_extract_currentfile(unzFile uf,
const int * popt_extract_without_path,
int * popt_overwrite,
const char * password,
const char * dirname)
{
char filename_inzip[256];
char* filename_withoutpath;
char* p;
int err=UNZ_OK;
FILE *fout=NULL;
void* buf;
uInt size_buf;
unz_file_info file_info;
//uLong ratio=0;
err = unzGetCurrentFileInfo(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++;
}
// this is a directory
if ((*filename_withoutpath)=='\0') {
if ((*popt_extract_without_path)==0)
makedir(filename_inzip);
}
// this is a filename
else {
char write_filename[1024];
strcpy(write_filename, dirname);
int len = strlen(write_filename);
if (write_filename[len-1] != '\\' &&
write_filename[len-1] != '/')
strcat(write_filename, "/");
if ((*popt_extract_without_path)==0)
strcat(write_filename, filename_inzip);
else
strcat(write_filename, filename_withoutpath);
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK) {
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
} else {
fout=fopen(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=fopen(write_filename,"wb");
}
if (fout==NULL) {
printf("error opening %s\n",write_filename);
}
}
if (fout!=NULL) {
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;
}
bool unzipToDir(string const & zipfile, string const & dirname)
{
unzFile uf=NULL;
#ifdef USEWIN32IOAPI
zlib_filefunc_def ffunc;
#endif
const char * zipfilename = zipfile.c_str();
#ifdef USEWIN32IOAPI
fill_win32_filefunc(&ffunc);
uf = unzOpen2(zipfilename, &ffunc);
#else
uf = unzOpen(zipfilename);
#endif
if (uf==NULL) {
return false;
}
uLong i;
unz_global_info gi;
int err;
//FILE* fout=NULL;
int opt_extract_without_path = 0;
int opt_overwrite = 1;
char * password = NULL;
err = unzGetGlobalInfo (uf, &gi);
if (err != UNZ_OK) {
printf("error %d with zipfile in unzGetGlobalInfo \n",err);
return false;
}
for (i=0; i < gi.number_entry; i++) {
if (do_extract_currentfile(uf, &opt_extract_without_path,
&opt_overwrite,
password, dirname.c_str()) != 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;
}
}
}
unzCloseCurrentFile(uf);
return true;
}