mirror of https://github.com/BOINC/boinc.git
Fixes to BOINC zip library from Carl Christensen. Carl says:
"I found a problem with boinc_zip; it seems some Linux STL's aren't very nice about classes that are inherited from their objects on multiple use; or huge file lists that we use on CPDN. So I rewrite it to just use "straight" std::string's in a vector. It's fully backwardly compatible and seems to work fine." svn path=/trunk/boinc/; revision=9203
This commit is contained in:
parent
18db739b31
commit
998db46c9b
|
@ -240,3 +240,15 @@ Rom 9 Jan 2006 (HEAD)
|
|||
- Tag for 5.3.9 release, all platforms
|
||||
boinc_core_release_5_3_9
|
||||
|
||||
Bruce 9 Jan 2006
|
||||
- Fixes to BOINC zip library from Carl Christensen. Carl says:
|
||||
"I found a problem with boinc_zip; it seems some Linux STL's
|
||||
aren't very nice about classes that are inherited from their
|
||||
objects on multiple use; or huge file lists that we use on CPDN.
|
||||
So I rewrite it to just use "straight" std::string's in a vector.
|
||||
It's fully backwardly compatible and seems to work fine."
|
||||
|
||||
zip/
|
||||
boinc_zip.h
|
||||
boinc_zip.cpp
|
||||
|
||||
|
|
|
@ -33,141 +33,131 @@ using std::string;
|
|||
#define _MAX_PATH 255
|
||||
#endif
|
||||
|
||||
// ZipFileEntry/List stuff
|
||||
ZipFileEntry::ZipFileEntry(const std::string strIn, unsigned char ucSort)
|
||||
{
|
||||
this->assign(strIn);
|
||||
stat(strIn.c_str(), &m_statFile);
|
||||
m_ucSort = ucSort;
|
||||
}
|
||||
unsigned char g_ucSort;
|
||||
|
||||
ZipFileEntry::ZipFileEntry(const std::string strIn, const struct stat instat, unsigned char ucSort)
|
||||
{
|
||||
this->assign(strIn);
|
||||
m_statFile = instat;
|
||||
m_ucSort = ucSort;
|
||||
}
|
||||
// a "binary predicate" for use by the std::sort algorithm
|
||||
// return true if "first > second" according to the g_ucSort type
|
||||
|
||||
ZipFileEntry::~ZipFileEntry()
|
||||
{
|
||||
this->assign("");
|
||||
}
|
||||
bool StringVectorSort(const std::string& first, const std::string& second)
|
||||
{
|
||||
|
||||
bool ZipFileEntry::operator< (const ZipFileEntry& other) const
|
||||
{
|
||||
bool bRet = false;
|
||||
if (m_ucSort & SORT_NAME
|
||||
&& m_ucSort & SORT_ASCENDING
|
||||
&& strcmp(this->c_str(), other.c_str())<0)
|
||||
bRet = true;
|
||||
else if (m_ucSort & SORT_NAME
|
||||
&& m_ucSort & SORT_DESCENDING
|
||||
&& strcmp(this->c_str(), other.c_str())>0)
|
||||
bRet = true;
|
||||
else if (m_ucSort & SORT_TIME
|
||||
&& m_ucSort & SORT_ASCENDING
|
||||
&& this->m_statFile.st_mtime < other.m_statFile.st_mtime)
|
||||
bRet = true;
|
||||
else if (m_ucSort & SORT_TIME
|
||||
&& m_ucSort & SORT_DESCENDING
|
||||
&& this->m_statFile.st_mtime > other.m_statFile.st_mtime)
|
||||
bRet = true;
|
||||
bool bRet = false;
|
||||
if (g_ucSort & SORT_NAME
|
||||
&& g_ucSort & SORT_ASCENDING
|
||||
&& strcmp(first.c_str(), second.c_str())<0)
|
||||
bRet = true;
|
||||
else if (g_ucSort & SORT_NAME
|
||||
&& g_ucSort & SORT_DESCENDING
|
||||
&& strcmp(first.c_str(), second.c_str())>0)
|
||||
bRet = true;
|
||||
else if (g_ucSort & SORT_TIME)
|
||||
{
|
||||
struct stat st[2];
|
||||
stat(first.c_str(), &st[0]);
|
||||
stat(second.c_str(), &st[1]);
|
||||
if (g_ucSort & SORT_ASCENDING) {
|
||||
bRet = st[0].st_mtime < st[1].st_mtime;
|
||||
}
|
||||
else {
|
||||
bRet = st[0].st_mtime > st[1].st_mtime;
|
||||
}
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
return bRet;
|
||||
}
|
||||
|
||||
int boinc_zip(int bZipType, const std::string szFileZip, const std::string szFileIn)
|
||||
{
|
||||
ZipFileList tempvec;
|
||||
tempvec.push_back(ZipFileEntry(szFileIn));
|
||||
return boinc_zip(bZipType, szFileZip, &tempvec);
|
||||
ZipFileList tempvec;
|
||||
tempvec.push_back(szFileIn);
|
||||
return boinc_zip(bZipType, szFileZip, &tempvec);
|
||||
}
|
||||
|
||||
int boinc_zip(int bZipType, const char* szFileZip, const char* szFileIn)
|
||||
{ // just use the regular boinc_zip
|
||||
std::string strFileZip, strFileIn;
|
||||
strFileZip.assign(szFileZip);
|
||||
strFileIn.assign(szFileIn);
|
||||
ZipFileList tempvec;
|
||||
tempvec.push_back(ZipFileEntry(strFileIn));
|
||||
return boinc_zip(bZipType, strFileZip, &tempvec);
|
||||
std::string strFileZip, strFileIn;
|
||||
strFileZip.assign(szFileZip);
|
||||
strFileIn.assign(szFileIn);
|
||||
ZipFileList tempvec;
|
||||
tempvec.push_back(strFileIn);
|
||||
return boinc_zip(bZipType, strFileZip, &tempvec);
|
||||
}
|
||||
|
||||
int boinc_zip(int bZipType, const std::string szFileZip,
|
||||
const ZipFileList* pvectszFileIn)
|
||||
{
|
||||
int carg;
|
||||
char** av;
|
||||
int iRet = 0, i = 0, nVecSize = 0;
|
||||
int carg;
|
||||
char** av;
|
||||
int iRet = 0, i = 0, nVecSize = 0;
|
||||
|
||||
if (pvectszFileIn) nVecSize = pvectszFileIn->size();
|
||||
if (pvectszFileIn) nVecSize = pvectszFileIn->size();
|
||||
|
||||
// if unzipping but no file out, so it just uses cwd, only 3 args
|
||||
//if (bZipType == UNZIP_IT)
|
||||
// carg = 3 + nVecSize;
|
||||
//else
|
||||
carg = 3 + nVecSize;
|
||||
// if unzipping but no file out, so it just uses cwd, only 3 args
|
||||
//if (bZipType == UNZIP_IT)
|
||||
// carg = 3 + nVecSize;
|
||||
//else
|
||||
carg = 3 + nVecSize;
|
||||
|
||||
// make a dynamic array
|
||||
av = (char**) calloc(carg, sizeof(char*));
|
||||
for (i=0;i<carg;i++)
|
||||
av[i] = (char*) calloc(_MAX_PATH,sizeof(char));
|
||||
// make a dynamic array
|
||||
av = (char**) calloc(carg, sizeof(char*));
|
||||
for (i=0;i<carg;i++)
|
||||
av[i] = (char*) calloc(_MAX_PATH,sizeof(char));
|
||||
|
||||
// just form an argc/argv to spoof the "main"
|
||||
// default options are to recurse into directories
|
||||
//if (options && strlen(options))
|
||||
// strcpy(av[1], options);
|
||||
// just form an argc/argv to spoof the "main"
|
||||
// default options are to recurse into directories
|
||||
//if (options && strlen(options))
|
||||
// strcpy(av[1], options);
|
||||
|
||||
if (bZipType == ZIP_IT)
|
||||
{
|
||||
strcpy(av[0], "zip");
|
||||
// default zip options -- no dir names, no subdirs, highest compression, quiet mode
|
||||
if (strlen(av[1])==0)
|
||||
strcpy(av[1], "-j9");
|
||||
//strcpy(av[1], "-9jq");
|
||||
strcpy(av[2], szFileZip.c_str());
|
||||
if (bZipType == ZIP_IT)
|
||||
{
|
||||
strcpy(av[0], "zip");
|
||||
// default zip options -- no dir names, no subdirs, highest compression, quiet mode
|
||||
if (strlen(av[1])==0)
|
||||
strcpy(av[1], "-j9");
|
||||
//strcpy(av[1], "-9jq");
|
||||
strcpy(av[2], szFileZip.c_str());
|
||||
|
||||
//sz 3 onward will be each vector
|
||||
int jj;
|
||||
for (jj=0; jj<nVecSize; jj++)
|
||||
strcpy(av[3+jj], pvectszFileIn->at(jj).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(av[0], "unzip");
|
||||
// default unzip options -- preserve subdirs, overwrite
|
||||
if (strlen(av[1])==0)
|
||||
strcpy(av[1], "-o");
|
||||
strcpy(av[2], szFileZip.c_str());
|
||||
//sz 3 onward will be each vector
|
||||
int jj;
|
||||
for (jj=0; jj<nVecSize; jj++)
|
||||
strcpy(av[3+jj], pvectszFileIn->at(jj).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(av[0], "unzip");
|
||||
// default unzip options -- preserve subdirs, overwrite
|
||||
if (strlen(av[1])==0)
|
||||
strcpy(av[1], "-o");
|
||||
strcpy(av[2], szFileZip.c_str());
|
||||
|
||||
// if they passed in a directory unzip there
|
||||
if (carg == 4)
|
||||
sprintf(av[3], "-d%s", pvectszFileIn->at(0).c_str());
|
||||
}
|
||||
// strcpy(av[carg-1], ""); // null arg
|
||||
// printf("args: %s %s %s %s\n", av[0], av[1], av[2], av[3]);
|
||||
// if they passed in a directory unzip there
|
||||
if (carg == 4)
|
||||
sprintf(av[3], "-d%s", pvectszFileIn->at(0).c_str());
|
||||
}
|
||||
// strcpy(av[carg-1], ""); // null arg
|
||||
// printf("args: %s %s %s %s\n", av[0], av[1], av[2], av[3]);
|
||||
|
||||
if (bZipType == ZIP_IT)
|
||||
{
|
||||
if (access(szFileZip.c_str(), 0) == 0)
|
||||
{ // old zip file exists so unlink (otherwise zip will reuse, doesn't seem to be a flag to
|
||||
// bypass zip reusing it
|
||||
unlink(szFileZip.c_str());
|
||||
}
|
||||
iRet = zip_main(carg, av);
|
||||
}
|
||||
else {
|
||||
// make sure zip file exists
|
||||
if (access(szFileZip.c_str(), 0) == 0)
|
||||
iRet = unzip_main(carg, av);
|
||||
else
|
||||
iRet = 2;
|
||||
}
|
||||
if (bZipType == ZIP_IT)
|
||||
{
|
||||
if (access(szFileZip.c_str(), 0) == 0)
|
||||
{ // old zip file exists so unlink (otherwise zip will reuse, doesn't seem to be a flag to
|
||||
// bypass zip reusing it
|
||||
unlink(szFileZip.c_str());
|
||||
}
|
||||
iRet = zip_main(carg, av);
|
||||
}
|
||||
else {
|
||||
// make sure zip file exists
|
||||
if (access(szFileZip.c_str(), 0) == 0)
|
||||
iRet = unzip_main(carg, av);
|
||||
else
|
||||
iRet = 2;
|
||||
}
|
||||
|
||||
for (i=0;i<carg;i++)
|
||||
free(av[i]);
|
||||
free(av);
|
||||
return iRet;
|
||||
for (i=0;i<carg;i++)
|
||||
free(av[i]);
|
||||
free(av);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,132 +175,134 @@ int boinc_zip(int bZipType, const std::string szFileZip,
|
|||
// CMC Note: this is a 'BOINC-friendly' implementation of "old" CPDN code
|
||||
// the "wildcard matching"/regexp is a bit crude, it matches substrings in
|
||||
// order in a file; to match all files such as *.pc.*.x4.*.nc" you would send in
|
||||
// ".pc|.x4.|.nc" for 'pattern'
|
||||
// ".pc|.x4.|.nc" for 'pattern'
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
bool boinc_filelist(const std::string directory,
|
||||
const std::string pattern,
|
||||
ZipFileList* pList,
|
||||
const unsigned char ucSort, const bool bClear)
|
||||
{
|
||||
std::string strFile;
|
||||
const unsigned char ucSort, const bool bClear)
|
||||
{
|
||||
g_ucSort = ucSort; // set the global sort type right off the bat
|
||||
std::string strFile;
|
||||
// at most three |'s may be passed in pattern match
|
||||
int iPos[3], iFnd, iCtr, i, lastPos;
|
||||
std::string strFullPath;
|
||||
char strPart[3][32];
|
||||
std::string spattern = pattern;
|
||||
int iPos[3], iFnd, iCtr, i, lastPos;
|
||||
std::string strFullPath;
|
||||
char strPart[3][32];
|
||||
std::string spattern = pattern;
|
||||
std::string strDir = directory;
|
||||
std::string strUserDir = directory;
|
||||
int iLen = strUserDir.size();
|
||||
std::string strUserDir = directory;
|
||||
int iLen = strUserDir.size();
|
||||
|
||||
if (!pList) return false;
|
||||
|
||||
// wildcards are blank!
|
||||
if (pattern == "*" || pattern == "*.*") spattern.assign("");
|
||||
// wildcards are blank!
|
||||
if (pattern == "*" || pattern == "*.*") spattern.assign("");
|
||||
|
||||
if (bClear)
|
||||
pList->clear(); // removes old entries that may be in pList
|
||||
if (bClear)
|
||||
pList->clear(); // removes old entries that may be in pList
|
||||
|
||||
// first tack on a final slash on user dir if required
|
||||
if (strUserDir[iLen-1] != '\\'
|
||||
&& strUserDir[iLen] != '/')
|
||||
{
|
||||
// need a final slash, but what type?
|
||||
// / is safe on all OS's for CPDN at least
|
||||
// but if they already used \ use that
|
||||
// well they didn't use a backslash so just use a slash
|
||||
if (strUserDir.find("\\") == string::npos)
|
||||
strUserDir += "/";
|
||||
else
|
||||
strUserDir += "\\";
|
||||
}
|
||||
// first tack on a final slash on user dir if required
|
||||
if (strUserDir[iLen-1] != '\\'
|
||||
&& strUserDir[iLen] != '/')
|
||||
{
|
||||
// need a final slash, but what type?
|
||||
// / is safe on all OS's for CPDN at least
|
||||
// but if they already used \ use that
|
||||
// well they didn't use a backslash so just use a slash
|
||||
if (strUserDir.find("\\") == string::npos)
|
||||
strUserDir += "/";
|
||||
else
|
||||
strUserDir += "\\";
|
||||
}
|
||||
|
||||
// transform strDir to either all \\ or all /
|
||||
int j;
|
||||
for (j=0; j<(int)directory.size(); j++) {
|
||||
// take off final / or backslash
|
||||
if (j == ((int)directory.size()-1)
|
||||
&& (strDir[j] == '/' || strDir[j]=='\\'))
|
||||
strDir.resize(directory.size()-1);
|
||||
else {
|
||||
// transform strDir to either all \\ or all /
|
||||
int j;
|
||||
for (j=0; j<(int)directory.size(); j++) {
|
||||
// take off final / or backslash
|
||||
if (j == ((int)directory.size()-1)
|
||||
&& (strDir[j] == '/' || strDir[j]=='\\'))
|
||||
strDir.resize(directory.size()-1);
|
||||
else {
|
||||
#ifdef _WIN32 // transform paths appropriate for OS
|
||||
if (directory[j] == '/')
|
||||
strDir[j] = '\\';
|
||||
strDir[j] = '\\';
|
||||
#else
|
||||
if (directory[j] == '\\')
|
||||
strDir[j] = '/';
|
||||
strDir[j] = '/';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DirScanner dirscan(strDir);
|
||||
memset(strPart, 0x00, 3*32);
|
||||
while (dirscan.scan(strFile))
|
||||
{
|
||||
iCtr = 0;
|
||||
lastPos = 0;
|
||||
iPos[0] = -1;
|
||||
iPos[1] = -1;
|
||||
iPos[2] = -1;
|
||||
// match the whole filename returned against the regexp to see if it's a hit
|
||||
// first get all the |'s to get the pieces to verify
|
||||
while (iCtr<3 && (iPos[iCtr] = (int) spattern.find('|', lastPos)) > -1)
|
||||
{
|
||||
if (iCtr==0) {
|
||||
strncpy(strPart[0], spattern.c_str(), iPos[iCtr]);
|
||||
}
|
||||
else {
|
||||
strncpy(strPart[iCtr], spattern.c_str()+lastPos, iPos[iCtr]-lastPos);
|
||||
}
|
||||
lastPos = iPos[iCtr]+1;
|
||||
DirScanner dirscan(strDir);
|
||||
memset(strPart, 0x00, 3*32);
|
||||
while (dirscan.scan(strFile))
|
||||
{
|
||||
iCtr = 0;
|
||||
lastPos = 0;
|
||||
iPos[0] = -1;
|
||||
iPos[1] = -1;
|
||||
iPos[2] = -1;
|
||||
// match the whole filename returned against the regexp to see if it's a hit
|
||||
// first get all the |'s to get the pieces to verify
|
||||
while (iCtr<3 && (iPos[iCtr] = (int) spattern.find('|', lastPos)) > -1)
|
||||
{
|
||||
if (iCtr==0) {
|
||||
strncpy(strPart[0], spattern.c_str(), iPos[iCtr]);
|
||||
}
|
||||
else {
|
||||
strncpy(strPart[iCtr], spattern.c_str()+lastPos, iPos[iCtr]-lastPos);
|
||||
}
|
||||
lastPos = iPos[iCtr]+1;
|
||||
|
||||
iCtr++;
|
||||
}
|
||||
if (iCtr>0) // found a | so need to get the part from lastpos onward
|
||||
{
|
||||
strncpy(strPart[iCtr], spattern.c_str()+lastPos, spattern.length() - lastPos);
|
||||
}
|
||||
iCtr++;
|
||||
}
|
||||
if (iCtr>0) // found a | so need to get the part from lastpos onward
|
||||
{
|
||||
strncpy(strPart[iCtr], spattern.c_str()+lastPos, spattern.length() - lastPos);
|
||||
}
|
||||
|
||||
// check no | were found at all
|
||||
if (iCtr == 0)
|
||||
{
|
||||
strcpy(strPart[0], spattern.c_str());
|
||||
iCtr++; // fake iCtr up 1 to get in the loop below
|
||||
}
|
||||
// check no | were found at all
|
||||
if (iCtr == 0)
|
||||
{
|
||||
strcpy(strPart[0], spattern.c_str());
|
||||
iCtr++; // fake iCtr up 1 to get in the loop below
|
||||
}
|
||||
|
||||
bool bFound = true;
|
||||
for (i = 0; i <= iCtr && bFound; i++)
|
||||
{
|
||||
if (i==0) {
|
||||
iFnd = (int) strFile.find(strPart[0]);
|
||||
bFound = (bool) (iFnd > -1);
|
||||
}
|
||||
else {
|
||||
// search forward of the old part found
|
||||
iFnd = (int) strFile.find(strPart[i], iFnd+1);
|
||||
bFound = bFound && (bool) (iFnd > -1);
|
||||
}
|
||||
}
|
||||
bool bFound = true;
|
||||
for (i = 0; i <= iCtr && bFound; i++)
|
||||
{
|
||||
if (i==0) {
|
||||
iFnd = (int) strFile.find(strPart[0]);
|
||||
bFound = (bool) (iFnd > -1);
|
||||
}
|
||||
else {
|
||||
// search forward of the old part found
|
||||
iFnd = (int) strFile.find(strPart[i], iFnd+1);
|
||||
bFound = bFound && (bool) (iFnd > -1);
|
||||
}
|
||||
}
|
||||
|
||||
if (bFound)
|
||||
{
|
||||
// this pattern matched the file, add to vector
|
||||
// NB: first get stat to make sure it really is a file
|
||||
strFullPath = strUserDir + strFile;
|
||||
// only add if the file really exists (i.e. not a directory)
|
||||
if (is_file(strFullPath.c_str())) {
|
||||
ZipFileEntry zfe(strFullPath, ucSort);
|
||||
pList->push_back(zfe);
|
||||
}
|
||||
}
|
||||
if (bFound)
|
||||
{
|
||||
// this pattern matched the file, add to vector
|
||||
// NB: first get stat to make sure it really is a file
|
||||
strFullPath = strUserDir + strFile;
|
||||
// only add if the file really exists (i.e. not a directory)
|
||||
if (is_file(strFullPath.c_str())) {
|
||||
pList->push_back(strFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// sort by file creation time
|
||||
|
||||
std::sort(pList->begin(), pList->end()); // may as well sort it?
|
||||
// sort by file creation time
|
||||
if (pList->size()>1) { // sort if list is greather than 1
|
||||
std::sort(pList->begin(), pList->end(), StringVectorSort); // may as well sort it?
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *BOINC_RCSID_bdf38b2dfb = "$Id$";
|
||||
|
||||
|
|
|
@ -32,21 +32,7 @@
|
|||
#ifdef __cplusplus
|
||||
using std::string;
|
||||
|
||||
class ZipFileEntry :public std::string
|
||||
{
|
||||
public:
|
||||
ZipFileEntry(const std::string strIn, unsigned char ucSort = SORT_NAME | SORT_DESCENDING);
|
||||
ZipFileEntry(const std::string strIn, const struct stat instat, unsigned char ucSort = SORT_NAME | SORT_DESCENDING);
|
||||
~ZipFileEntry();
|
||||
bool operator< (const ZipFileEntry& other) const; // sorts by filetime
|
||||
|
||||
struct stat m_statFile; // keep file stats in here
|
||||
|
||||
private:
|
||||
unsigned char m_ucSort;
|
||||
};
|
||||
|
||||
typedef std::vector<ZipFileEntry> ZipFileList;
|
||||
typedef std::vector<std::string> ZipFileList;
|
||||
|
||||
// forward declarations for boinc_zip functions
|
||||
// note it's basically like running zip/unzip, just comprise an argc/argv
|
||||
|
@ -67,8 +53,8 @@ typedef std::vector<ZipFileEntry> ZipFileList;
|
|||
bool boinc_filelist(const std::string directory,
|
||||
const std::string pattern,
|
||||
ZipFileList* pList,
|
||||
const unsigned char ucSort = SORT_NAME | SORT_DESCENDING,
|
||||
const bool bClear = true);
|
||||
const unsigned char ucSort = SORT_NAME | SORT_DESCENDING,
|
||||
const bool bClear = true);
|
||||
int boinc_zip(int bZipType, const std::string szFileZip, const ZipFileList* pvectszFileIn);
|
||||
int boinc_zip(int bZipType, const std::string szFileZip, const std::string szFileIn);
|
||||
extern "C"
|
||||
|
@ -77,6 +63,3 @@ extern
|
|||
#endif
|
||||
int boinc_zip(int bZipType, const char* szFileZip, const char* szFileIn);
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue