diff --git a/checkin_notes b/checkin_notes index decea9c652..dafc7acce7 100755 --- a/checkin_notes +++ b/checkin_notes @@ -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 + diff --git a/zip/boinc_zip.cpp b/zip/boinc_zip.cpp index 4123d0ae37..f436f1938b 100644 --- a/zip/boinc_zip.cpp +++ b/zip/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;iat(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; jjat(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;iclear(); // 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$"; + diff --git a/zip/boinc_zip.h b/zip/boinc_zip.h index 03f8188348..33c1f970cc 100644 --- a/zip/boinc_zip.h +++ b/zip/boinc_zip.h @@ -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 ZipFileList; +typedef std::vector 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 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); - - -