📄 staffilesystem.cpp
字号:
/*****************************************************************************//* Software Testing Automation Framework (STAF) *//* (C) Copyright IBM Corp. 2001 *//* *//* This software is licensed under the Common Public License (CPL) V1.0. *//*****************************************************************************/#include "STAF.h"#include <deque>#include <algorithm>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <dirent.h>#include "STAFFileSystem.h"#include "STAFMutexSem.h"// Typesstruct STAFFSEntryImpl{ STAFFSEntryImpl(const STAFString &thePathString, STAFFSEntryType_t theType, unsigned int isALink, off_t theSize, time_t theModTime, const STAFString &theLinkTarget) : pathString(thePathString), type(theType), isLink(isALink), size(theSize), modTime(theModTime), linkTarget(theLinkTarget) { /* Do Nothing*/ } STAFString pathString; STAFFSEntryType_t type; unsigned int isLink; // 1 = Link; 0 = Not a link off_t size; time_t modTime; STAFString linkTarget;};typedef std::deque<STAFFSEntry_t> STAFFSEntryList;struct STAFFSEnumHandleImpl{ STAFFSEntryList entries;};struct STAFFSOSFileLockImpl{ STAFFSOSFileLockImpl(int theFileDes) : fileDes(theFileDes) { /* Do Nothing */ } int fileDes;};// Some global stringsstatic STAFString sSlash(kUTF8_SLASH);static STAFString sPeriod(kUTF8_PERIOD);static STAFString sDoublePeriod(sPeriod + sPeriod);// Semaphore for directory enumerationstatic STAFMutexSem sEnumSem;/*****************************************************************************//* Helper APIs *//*****************************************************************************/struct STAFSortEnumByName{ STAFSortEnumByName(STAFFSCaseSensitive_t caseSensitive) : fCaseSensitive(caseSensitive) { /* Do nothing */ } bool operator()(STAFFSEntry_t lhs, STAFFSEntry_t rhs) { unsigned int comp = 0; if (fCaseSensitive == kSTAFFSCaseSensitive) { STAFStringCompareTo(lhs->pathString.getImpl(), rhs->pathString.getImpl(), &comp, 0); } else { STAFStringCompareTo(lhs->pathString.toUpperCase().getImpl(), rhs->pathString.toUpperCase().getImpl(), &comp, 0); } return (comp == 1); } STAFFSCaseSensitive_t fCaseSensitive;};static bool sortEnumBySize(STAFFSEntry_t lhs, STAFFSEntry_t rhs){ return (lhs->size < rhs->size);}static bool sortEnumByModTime(STAFFSEntry_t lhs, STAFFSEntry_t rhs){ return (STAFTimestamp(lhs->modTime) < STAFTimestamp(rhs->modTime));}// Remove any trailing slashes (that are not also leading slashes) from a path// and return the updated string.static STAFString removeTrailingSlashes(const STAFString &path){ STAFString newPath = path; if (newPath.findFirstNotOf(sSlash, STAFString::kChar) != STAFString::kNPos) { unsigned int lastNonSlashLoc = newPath.findLastNotOf(sSlash, STAFString::kChar); if (lastNonSlashLoc + 1 != newPath.length()) { newPath = newPath.subString(0, lastNonSlashLoc + 1, STAFString::kChar); } } return newPath;}/*****************************************************************************//* General File System APIs *//*****************************************************************************///STAFRC_t STAFFSInfo(STAFString_t *info, STAFFSInfoType_t infoType)STAFRC_t STAFFSInfo(void *info, STAFFSInfoType_t infoType){ if (info == 0) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { switch (infoType) { case kSTAFFSPathSep: { *reinterpret_cast<STAFString_t *>(info) = STAFString(kUTF8_COLON).adoptImpl(); break; } case kSTAFFSFileSep: { *reinterpret_cast<STAFString_t *>(info) = STAFString(kUTF8_SLASH).adoptImpl(); break; } case kSTAFFSLineSep: { *reinterpret_cast<STAFString_t *>(info) = STAFString(kUTF8_LF).adoptImpl(); break; } case kSTAFFSCaseSensitivity: { *reinterpret_cast<STAFFSCaseSensitive_t *>(info) = kSTAFFSCaseSensitive; break; } default: { retCode = kSTAFInvalidParm; } } } catch (...) { retCode = kSTAFUnknownError; } return retCode;}/*****************************************************************************//* Path APIs *//*****************************************************************************/STAFRC_t STAFFSAssemblePath(STAFString_t *path, STAFStringConst_t root, unsigned int numDirs, STAFStringConst_t *dirs, STAFStringConst_t name, STAFStringConst_t extension){ if (path == 0) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { STAFString theRoot(root); STAFString theName(name); STAFString theExtension(extension); STAFString result; // If a root was specified add it if (theRoot.length() != 0) result += theRoot; // Add the directories if (numDirs != 0) { // Add a slash if we need it if ((result.length() != 0) && (result.subString(result.length(STAFString::kChar) - 1, STAFString::kRemainder, STAFString::kChar) != sSlash)) { result += sSlash; } // Tack on each directory and a slash, except the last one for (unsigned int i = 0; i < (numDirs - 1); ++i) { result += dirs[i]; result += sSlash; } // Add the last directory without a slash result += dirs[numDirs - 1]; } if ((theName.length() != 0) || (theExtension.length() != 0)) { // Add a slash if we need it if ((result.length() != 0) && (result.subString(result.length(STAFString::kChar) - 1, STAFString::kRemainder, STAFString::kChar) != sSlash)) { result += sSlash; } // Add the name if (theName.length() != 0) result += theName; // Add the extension if (theExtension.length() != 0) { result += sPeriod; result += theExtension; } } *path = result.adoptImpl(); } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSDisassemblePath(STAFStringConst_t path, STAFString_t *root, unsigned int *numDirs, STAFString_t **dirs, STAFString_t *name, STAFString_t *extension){ if (path == 0) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { STAFString thePath(path); // See if they have a root slash present. Remove it, if present. STAFString theRoot; if (thePath.subString(0, 1, STAFString::kChar) == sSlash) { theRoot = sSlash; thePath = thePath.subString(thePath.findFirstNotOf(sSlash)); } if (root) *root = theRoot.adoptImpl(); // Remove any trailing slashes (that are not also leading slashes) thePath = removeTrailingSlashes(thePath); // Now, find all the directories std::deque<STAFString> theDirs; for (unsigned int slashLoc = thePath.find(sSlash); slashLoc != STAFString::kNPos; slashLoc = thePath.find(sSlash)) { theDirs.push_back(thePath.subString(0, slashLoc)); thePath = thePath.subString(thePath.findFirstNotOf(sSlash, slashLoc)); } if (numDirs) *numDirs = theDirs.size(); if (dirs) { if (theDirs.size() == 0) *dirs = 0; else *dirs = new STAFString_t[theDirs.size()]; for (unsigned int i = 0; i < theDirs.size(); ++i) (*dirs)[i] = theDirs[i].adoptImpl(); } // If the name is "." or ".." then leave it alone, otherwise // separate the name and the extension if ((thePath == sPeriod) || (thePath == sDoublePeriod)) { if (name) *name = thePath.adoptImpl(); if (extension) *extension = STAFString().adoptImpl(); } else { // Next find and remove the extension STAFString theExtension; unsigned int extLoc = thePath.findLastOf(sPeriod); // Note: If find a period and it is the last character // (e.g. grannyapple.), keep the period as part of the name if ((extLoc != STAFString::kNPos) && (extLoc != (thePath.length() - 1))) { theExtension = thePath.subString(extLoc + thePath.sizeOfChar(extLoc)); thePath = thePath.subString(0, extLoc); } if (extension) *extension = theExtension.adoptImpl(); // We are now left with the name if (name) *name = thePath.adoptImpl(); } } catch (...) { retCode = kSTAFUnknownError;} return retCode;}STAFRC_t STAFFSFreePathDirs(STAFString_t *dirs){ delete [] dirs; return kSTAFOk;}/*****************************************************************************//* File System Entry APIs *//*****************************************************************************/STAFRC_t STAFFSExists(STAFStringConst_t path, unsigned int *exists, unsigned int *osRC){ if (path == 0) return kSTAFInvalidParm; if (exists == 0) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { // Remove any trailing slashes (that are not also leading slashes) STAFString thePath = removeTrailingSlashes(path); struct stat data = { 0 }; int rc = stat(thePath.toCurrentCodePage()->buffer(), &data); if (rc == 0) { *exists = 1; } else if (errno == ENOENT) { *exists = 0; } else { if (osRC) *osRC = errno; retCode = kSTAFBaseOSError; } } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSGetEntry(STAFStringConst_t path, STAFFSEntry_t *entry, unsigned int *osRC){ if ((path == 0) || (entry == 0)) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { // Remove any trailing slashes (that are not also leading slashes) STAFString thePath = removeTrailingSlashes(path); struct stat data = { 0 }; int rc = lstat(thePath.toCurrentCodePage()->buffer(), &data); if (rc < 0) { if (osRC) *osRC = errno; return kSTAFBaseOSError; } unsigned int isLink = 0; STAFString theLinkTarget(""); if (S_ISLNK(data.st_mode)) { isLink = 1; theLinkTarget = STAFString("<Unknown>"); rc = stat(thePath.toCurrentCodePage()->buffer(), &data); // Get the name of the target referred to by the symbolic link #ifndef STAF_OS_NAME_ZOS char buf[PATH_MAX + 1] = { 0 };#else // XXX: Get an error compiling on z/OS if use PATH_MAX char buf[256] = { 0 };#endif size_t len; len = readlink(thePath.toCurrentCodePage()->buffer(), buf, sizeof(buf)-1); if (len < 0) theLinkTarget = theLinkTarget + STAFString(" OSRC:" + errno); else theLinkTarget = STAFString(buf); } STAFFSEntryType_t theType = kSTAFFSOther; if (S_ISREG(data.st_mode)) theType = kSTAFFSFile; else if (S_ISDIR(data.st_mode)) theType = kSTAFFSDirectory; else if (S_ISFIFO(data.st_mode)) theType = kSTAFFSPipe; else if (S_ISSOCK(data.st_mode)) theType = kSTAFFSSocket; else if (S_ISCHR(data.st_mode)) theType = kSTAFFSCharDev; else if (S_ISBLK(data.st_mode)) theType = kSTAFFSBlkDev; else if (S_ISLNK(data.st_mode)) theType = kSTAFFSSymLink; *entry = new STAFFSEntryImpl(thePath, theType, isLink, data.st_size, data.st_mtime, theLinkTarget); } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSEntryGetPathString(STAFFSEntry_t entry, STAFStringConst_t *pathString, unsigned int *osRC){ if (entry == 0) return kSTAFInvalidObject; if (pathString == 0) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { *pathString = entry->pathString.getImpl(); } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSEntryGetType(STAFFSEntry_t entry, STAFFSEntryType_t *type, unsigned int *osRC){ if (entry == 0) return kSTAFInvalidObject; if (type == 0) return kSTAFInvalidParm; STAFRC_t retCode = kSTAFOk; try { *type = entry->type; } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSEntryGetSize(STAFFSEntry_t entry, unsigned int *upperSize, unsigned int *lowerSize, unsigned int *osRC){ if (entry == 0) return kSTAFInvalidObject; STAFRC_t retCode = kSTAFOk; try { if (sizeof(off_t) > sizeof(unsigned int)) { *upperSize = (entry->size >> 32) & 0xFFFFFFFF; *lowerSize = entry->size & 0xFFFFFFFF; } else { *upperSize = 0; *lowerSize = entry->size; } } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSEntryGetModTime(STAFFSEntry_t entry, time_t *modTime, unsigned int *osRC){ if (entry == 0) return kSTAFInvalidObject; STAFRC_t retCode = kSTAFOk; try { *modTime = entry->modTime; } catch (...) { retCode = kSTAFUnknownError; } return retCode;}STAFRC_t STAFFSEntryGetIsLink(STAFFSEntry_t entry, unsigned int *isLink, unsigned int *osRC)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -