blob: a308e471f508ad23f7684b2b44a129076dc8fc8c [file] [log] [blame]
/*
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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#ifdef _WIN32
#include <sys/utime.h>
#else
#include <utime.h>
#endif
#include <sys/stat.h>
#include "unzip.h"
#include "archive.h"
#define CASESENSITIVITY (0)
#define WRITEBUFFERSIZE (8192)
#define MAXFILENAME (256)
#ifdef _WIN32
#define USEWIN32IOAPI
#include "iowin32.h"
#include <direct.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(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
#if defined(unix) || defined(__APPLE__)
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(const char *dirname)
{
int ret=0;
#ifdef _WIN32
ret = _mkdir(dirname);
#else
#if defined unix || defined __APPLE__
ret = mkdir(dirname,0775);
#endif
#endif
return ret;
}
int makedir (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;
}
int do_extract_currentfile(unzFile uf, char * revisionRoot) {
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;
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') {
char * dir;
dir = (char *)malloc(strlen(revisionRoot) + strlen(filename_inzip) + 2);
strcpy(dir, revisionRoot);
strcat(dir, "/");
strcat(dir, filename_inzip);
mymkdir(dir);
free(dir);
}
else
{
const char* write_filename;
int skip=0;
int length;
char * fWFN;
write_filename = filename_inzip;
length = strlen(write_filename) + strlen(revisionRoot) + 2;
fWFN = (char *)malloc(length);
strcpy(fWFN, revisionRoot);
strcat(fWFN, "/");
strcat(fWFN, write_filename);
err = unzOpenCurrentFile(uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
}
if ((skip==0) && (err==UNZ_OK))
{
fout=fopen64(fWFN,"wb");
/* some zipfile don't contain directory alone before file */
if ((fout==NULL) && (filename_withoutpath!=(char*)filename_inzip))
{
char * dir;
int length;
char c=*(filename_withoutpath-1);
*(filename_withoutpath-1)='\0';
length = strlen(write_filename) + strlen(revisionRoot) + 2;
dir = (char *)malloc(length);
strcpy(dir, revisionRoot);
strcat(dir, "/");
strcat(dir, write_filename);
makedir(dir);
*(filename_withoutpath-1)=c;
free(dir);
fout=fopen64(fWFN,"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(fWFN,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(fWFN);
}
free(buf);
return err;
}
int do_extract(unzFile uf, char * revisionRoot) {
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);
for (i=0;i<gi.number_entry;i++)
{
if (do_extract_currentfile(uf, revisionRoot) != 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;
}
celix_status_t extractBundle(char * bundleName, char * revisionRoot) {
celix_status_t status = CELIX_SUCCESS;
char filename_try[MAXFILENAME+16] = "";
unzFile uf=NULL;
if (bundleName!=NULL)
{
# ifdef USEWIN32IOAPI
zlib_filefunc64_def ffunc;
# endif
strncpy(filename_try, bundleName,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(bundleName,&ffunc);
# else
uf = unzOpen64(bundleName);
# 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",bundleName,bundleName);
status = CELIX_FILE_IO_EXCEPTION;
} else {
if (do_extract(uf, revisionRoot) != 0) {
status = CELIX_FILE_IO_EXCEPTION;
}
unzClose(uf);
}
return status;
}