123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948 |
- #ifndef _TWINKLE_CICOMPONENT_INTERFACE_H__
- #define _TWINKLE_CICOMPONENT_INTERFACE_H__
- #pragma once
- #if defined(_MSC_VER)
- #include <Windows.h>
- #else
- #include <winpr/wtypes.h>
- #ifndef FILE_ATTRIBUTE_READONLY
- #define FILE_ATTRIBUTE_READONLY 0x00000001
- #define FILE_ATTRIBUTE_HIDDEN 0x00000002
- #define FILE_ATTRIBUTE_SYSTEM 0x00000004
- #define FILE_ATTRIBUTE_DIRECTORY 0x00000010
- #define FILE_ATTRIBUTE_ARCHIVE 0x00000020
- #define FILE_ATTRIBUTE_DEVICE 0x00000040
- #define FILE_ATTRIBUTE_NORMAL 0x00000080
- #define FILE_ATTRIBUTE_TEMPORARY 0x00000100
- #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
- #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
- #define FILE_ATTRIBUTE_COMPRESSED 0x00000800
- #define FILE_ATTRIBUTE_OFFLINE 0x00001000
- #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
- #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
- #define FILE_ATTRIBUTE_VIRTUAL 0x00010000
- #endif
- #endif //_MSC_VER
- #include <vector>
- #include <map>
- #include <string>
- #include <algorithm>
- #include "AutoArray.h"
- #include "fileutil.h"
- using namespace std;
- enum FileType
- {
- FT_Unknown,
- FT_Root,
- FT_Volume,
- FT_Directory,
- FT_File
- };
- class CSimpleFileComponent
- {
- public:
- CSimpleFileComponent()
- :mftCreate(0)
- ,mftModified(0)
- ,mftAccess(0)
- ,mAttributes(0)
- ,mFileSize(0)
- ,mLevel(-1)
- ,mNameOffset(0)
- ,mNameLength(0)
- {
- }
- //For CFileShell, the inherent class must re-implement the function.
- //as is: return new CInherentClass(*this);
- virtual CSimpleFileComponent* Clone() const
- {
- return new CSimpleFileComponent(*this);
- }
- virtual void Clear()
- {
- mftCreate = mftAccess = mftModified = 0;
- mAttributes = 0;
- mLevel = -1;
- mNameLength = 0;
- mNameOffset = 0;
- }
- virtual FileType GetFileType() const
- {
- if(mAttributes != 0)
- {
- if(mAttributes & FILE_ATTRIBUTE_DIRECTORY)
- return FT_Directory;
- return FT_File;
- }
- if(mLevel == 0)
- return FT_Volume;
- else if(mLevel == -2)
- return FT_Root;
- return FT_Unknown;
- }
- public:
- ULONGLONG mftCreate;
- ULONGLONG mftModified;
- ULONGLONG mftAccess;
- ULONGLONG mFileSize;
- DWORD mAttributes;
- int mLevel; //file's hierarchy display in volume.
- DWORD mNameOffset;
- DWORD mNameLength;
- };
- //Use Handle Class for the CFileComponent hierarchy
- class CSimpleFileShell
- {
- public:
- CSimpleFileShell()
- :_pointer(0)
- , _count(new size_t(1))
- {}
- CSimpleFileShell(const CSimpleFileShell& rhs)
- :_pointer(rhs._pointer)
- , _count(rhs._count)
- {
- ++*_count;
- }
- CSimpleFileShell(const CSimpleFileComponent& rhs)
- :_pointer(rhs.Clone())
- , _count(new size_t(1))
- {}
- ~CSimpleFileShell()
- {
- removeRef();
- }
- CSimpleFileShell& operator=(const CSimpleFileShell& rhs)
- {
- ++*rhs._count;
- removeRef();
- _pointer = rhs._pointer;
- _count = rhs._count;
- return *this;
- }
- operator CSimpleFileComponent* () const {
- if (_pointer) return _pointer;
- else return NULL; //throw logic_error("unbound CFileComponent !");
- }
- CSimpleFileComponent* operator->() {
- if (_pointer) return _pointer;
- else throw logic_error("unbound CFileComponent !");
- }
- const CSimpleFileComponent* operator->() const {
- if (_pointer) return _pointer;
- else throw logic_error("unbound CFileComponent !");
- }
- const CSimpleFileComponent& operator*() const {
- if (_pointer) return *_pointer;
- else throw logic_error("unbound CFileComponent !");
- }
- CSimpleFileComponent& operator*() {
- if (_pointer) return *_pointer;
- else throw logic_error("unbound CFileComponent !");
- }
- private:
- CSimpleFileComponent* _pointer;
- size_t* _count;
- void removeRef()
- {
- if (--*_count == 0)
- {
- delete _pointer;
- delete _count;
- }
- }
- };
- typedef CAutoArray<CSimpleFileComponent> CAutoFiles;
- typedef struct FILE_LAYOUT_ENTRY {
- //Always Volume or Directory informaiton
- CSimpleFileComponent Current;
- //Sub directory or file informaion
- CAutoFiles SubFiles;
- //Contain file name stream
- CAutoBuffer FileNamesBuffer;
- } FILE_LAYOUT_ENTRY, *PFILE_LAYOUT_ENTRY;
- //Premise: Should be initialize entry->current first.
- static ULONGLONG GetSubFileInfors(PFILE_LAYOUT_ENTRY Entry, DWORD& dwDirCount, DWORD& dwFileCount, const DWORD dwFilterMask = 0);
- static unsigned long long GetDirectorySize(LPCTSTR dirPath, int nDepth = -1024);
- inline static DWORD GetDirectoryItemCount(LPCTSTR dirPath, int nDepth = -1024);
- static void DisplayFileEntities(const PFILE_LAYOUT_ENTRY Entry);
- DWORD GetDirectoryItemCount(LPCTSTR dirPath, int nDepth)
- {
- #if defined(RVC_OS_LINUX)
- DIR* d;
- struct dirent* entry;
- struct stat statbuf;
- DWORD result = 0;
- if ((d = opendir(dirPath)) == NULL) {
- Dbg("opendir %s failed: %s", dirPath, strerror(errno));
- return 0;
- }
- struct dirent* dp = NULL;
- while ((dp = readdir(d)) != NULL) {
- if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, ".."))) {
- continue;
- }
- result++;
- continue;
- char tempFilePath[MAX_PATH * 2] = { 0 };
- strcpy(tempFilePath, dirPath);
- if (strlen(tempFilePath) + strlen(dp->d_name) + 3 >= MAX_PATH * 2) {
- Dbg("filePath is too long for current.");
- continue;
- }
- strcat(tempFilePath, "/");
- strcat(tempFilePath, dp->d_name);
- struct stat fileStat;
- if (stat(tempFilePath, &fileStat) < 0) {
- Dbg("stat dir for %s failed: %d ", tempFilePath, errno);
- continue;
- }
- if (S_ISDIR(fileStat.st_mode)) {
- if (nDepth + 1 >= 0) {
- Dbg("exceed the deepest dir, do not recursive at all: %s", tempFilePath);
- } else {
- result += GetDirectoryItemCount(tempFilePath, nDepth + 1);
- }
- }
- }
- closedir(d);
- return result;
- #else
- return 0;
- #endif //RVC_OS_LINUX
- }
- unsigned long long GetDirectorySize(LPCTSTR dirPath, int nDepth)
- {
- #if defined(RVC_OS_LINUX)
- DIR * d;
- struct dirent* entry;
- struct stat statbuf;
- unsigned long long result = 0;
- if ((d = opendir(dirPath)) == NULL) {
- Dbg("opendir %s failed: %s", dirPath, strerror(errno));
- return 0;
- }
- lstat(dirPath, &statbuf);
- result += statbuf.st_size;
- struct dirent* dp = NULL;
- while ((dp = readdir(d)) != NULL) {
- if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, ".."))) {
- continue;
- }
- char tempFilePath[MAX_PATH * 2] = { 0 };
- strcpy(tempFilePath, dirPath);
- if (strlen(tempFilePath) + strlen(dp->d_name) + 3 >= MAX_PATH * 2) {
- Dbg("filePath is too long for current.");
- continue;
- }
- strcat(tempFilePath, "/");
- strcat(tempFilePath, dp->d_name);
- struct stat fileStat;
- if (stat(tempFilePath, &fileStat) < 0) {
- Dbg("stat dir for %s failed: %d ", tempFilePath, errno);
- continue;
- }
- if (S_ISDIR(fileStat.st_mode)) {
- if (nDepth + 1 >= 0) {
- Dbg("exceed the deepest dir, do not recursive at all: %s", tempFilePath);
- } else {
- result += GetDirectorySize(tempFilePath, nDepth + 1);
- }
- } else {
- result += fileStat.st_size;
- }
- }
- closedir(d);
- return result;
- #else
- return 0;
- #endif //RVC_OS_LINUX
- }
- static UINT GetErrorMessage(CSimpleStringA& retMessage, LPCTSTR lpDefault, DWORD error = GetLastError())
- {
- #if defined(_MSC_VER)
- if (error == 0) {
- retMessage = lpDefault;
- return strlen(lpDefault);
- }
- LPVOID lpMsgBuf;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
- | FORMAT_MESSAGE_FROM_SYSTEM
- | FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- error,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0,
- NULL);
- if (lpMsgBuf == NULL) {
- retMessage = lpDefault;
- return strlen(lpDefault);
- }
- retMessage = (LPCTSTR)lpMsgBuf;
- LocalFree((LPVOID)lpMsgBuf);
- return retMessage.GetLength();
- #else
- retMessage = lpDefault;
- return strlen(lpDefault);
- #endif //_MSC_VER
- }
- #if defined(_MSC_VER)
- static void GetTimeFormatStr(LPTSTR lpszString, DWORD dwSize, FILETIME* ftWrite)
- {
- SYSTEMTIME stUTC, stLocal;
- // Convert the last-write time to local time.
- FileTimeToSystemTime(ftWrite, &stUTC);
- SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
- // Build a string showing the date and time.
- sprintf_s(lpszString, dwSize, "%02d/%02d/%d %02d:%02d:%02d",
- stLocal.wMonth, stLocal.wDay, stLocal.wYear,
- stLocal.wHour, stLocal.wMinute, stLocal.wSecond);
- return;
- }
- #else
- static void GetTimeFormatStr(LPTSTR lpszString, DWORD dwSize, const time_t* ftWrite)
- {
- tm* curTime = localtime(ftWrite);
- sprintf(lpszString, "%02d/%02d/%d %02d:%02d:%02d", (1 + curTime->tm_mon),
- curTime->tm_mday, (1900 + curTime->tm_year), curTime->tm_hour, curTime->tm_min, curTime->tm_sec);
- return;
- }
- #endif //_MSC_VER
- static BOOL Append(CAutoBuffer& buffer, const BYTE* const btContent, const DWORD dwSizeInByte, DWORD& dwLocate)
- {
- DWORD dwStart = buffer.GetCount();
- buffer.Append(btContent, 0, dwSizeInByte);
- assert(buffer.GetCount() - dwStart == dwSizeInByte);
- dwLocate = dwStart;
- return TRUE;
- }
- static BOOL GetSubFileName(const BYTE* btBuffer, const DWORD bufSize, CSimpleStringA& filePath, PULARGE_INTEGER pUliOffsetLength)
- {
- if(btBuffer == NULL || bufSize == 0) return FALSE;
- if(pUliOffsetLength == NULL) return FALSE;
- if(bufSize < pUliOffsetLength->u.LowPart + pUliOffsetLength->u.HighPart) return FALSE;
- CSimpleStringA tmpPath((LPCTSTR)btBuffer+pUliOffsetLength->u.LowPart, pUliOffsetLength->u.HighPart);
- //Dbg("GetSubFileName::tmpPath: %d", tmpPath.GetLength());
- filePath = tmpPath;
- return !filePath.IsNullOrEmpty();
- }
- static BOOL GetSubFileName(const PFILE_LAYOUT_ENTRY Entry, int nSubIndex, CSimpleStringA& csOutPath)
- {
- if(Entry == NULL)
- return FALSE;
- if(Entry->FileNamesBuffer.GetCount() == 0)
- return FALSE;
- if(nSubIndex < 0 || nSubIndex >= Entry->SubFiles.GetCount())
- return FALSE;
- const CSimpleFileComponent item = Entry->SubFiles[nSubIndex];
- csOutPath = "";
- if(item.mNameLength != 0)
- {
- ULARGE_INTEGER uliOffsetLength;
- uliOffsetLength.u.LowPart = item.mNameOffset;
- uliOffsetLength.u.HighPart = item.mNameLength;
- GetSubFileName(Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
- csOutPath, &uliOffsetLength);
- }
- return !(csOutPath.IsNullOrEmpty());
- }
- static int GetAttributeFormat(const DWORD& fileAttributes, CSimpleStringA& csAttributes)
- {
- #define ATTR_NUM 17
- static char szAttributes[ATTR_NUM] = {
- 'R', //0x00000001
- 'H', //0x00000002
- 'S', //0x00000004
- '*', //0x00000008
- 'D', //0x00000010
- 'A', //0x00000020
- 'V', //0x00000040
- 'N', //0x00000080
- 'T', //0x00000100
- 'P', //0x00000200
- 'L', //0x00000400
- 'C', //0x00000800
- 'O', //0x00001000
- 'I', //0x00002000
- 'E', //0x00004000
- '#', //0x00008000
- 'U', //0x00010000
- };
- static char szBelongs[ATTR_NUM+1];
- memset(szBelongs, 0, sizeof(szBelongs));
- int cnt = 0;
- DWORD attbitutes = fileAttributes;
- for(int i=0; attbitutes != 0; attbitutes >>=1, ++i)
- {
- if((attbitutes & 0x1))
- {
- szBelongs[cnt++] = szAttributes[i];
- }
- }
- szBelongs[cnt] = '\0';
- csAttributes = szBelongs;
- return cnt;
- }
- static BOOL GetFullFilePath(const PFILE_LAYOUT_ENTRY Entry,
- int nSubIndex, CSimpleStringA& csOutPath)
- {
- if(Entry == NULL)
- return FALSE;
- if(Entry->FileNamesBuffer.GetCount() == 0)
- return FALSE;
- if(nSubIndex < 0 || nSubIndex >= Entry->SubFiles.GetCount())
- return FALSE;
- const CSimpleFileComponent item = Entry->SubFiles[nSubIndex];
- CSimpleStringA csFileName;
- csOutPath = "";
-
- if(item.mNameLength != 0)
- {
- ULARGE_INTEGER uliOffsetLength;
- uliOffsetLength.u.LowPart = item.mNameOffset;
- uliOffsetLength.u.HighPart = item.mNameLength;
- GetSubFileName(Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
- csFileName, &uliOffsetLength);
- }
- if(!csFileName.IsNullOrEmpty())
- {
- CSimpleStringA csParentPath;
- if((const BYTE*)Entry->FileNamesBuffer != NULL)
- {
- csParentPath = CSimpleStringA((LPCTSTR)(const BYTE*)Entry->FileNamesBuffer, Entry->Current.mNameLength);
- }
- if(!csParentPath.IsNullOrEmpty() && (csParentPath.IsEndWith("\\") || csParentPath.IsEndWith("/")))
- csOutPath = csParentPath + csFileName;
- else if(csParentPath.IsNullOrEmpty())
- csOutPath = csFileName;
- else
- csOutPath = csParentPath + SPLIT_SLASH_STR + csFileName;
- }
- return !(csOutPath.IsNullOrEmpty());
- }
- static BOOL GetFullFilePath(const CSimpleStringA& parentPath, const BYTE* btBuffer, const DWORD bufSize,
- CSimpleStringA& fullFilePath, PULARGE_INTEGER pUliOffsetLength)
- {
- CSimpleStringA csFileName;
- Dbg("parentPath: %s", (LPCTSTR)csFileName);
- if(GetSubFileName(btBuffer, bufSize, csFileName, pUliOffsetLength))
- {
- if(!parentPath.IsNullOrEmpty()
- && (
- parentPath[parentPath.GetLength()-1] == '\\'
- || parentPath[parentPath.GetLength()-1] == '/')
- )
- fullFilePath = parentPath + csFileName;
- else if(parentPath.IsNullOrEmpty())
- fullFilePath = csFileName;
- else
- fullFilePath = parentPath + SPLIT_SLASH_STR + csFileName;
- }
- return !(fullFilePath.IsNullOrEmpty());
- }
- static CSimpleFileShell RetriveSubFile(
- const PFILE_LAYOUT_ENTRY Entry,
- int nSubIndex)
- {
- if(Entry == NULL)
- return CSimpleFileShell();
- if(Entry->FileNamesBuffer.GetCount() == 0)
- return CSimpleFileShell();
- if(nSubIndex < 0 || nSubIndex >= Entry->SubFiles.GetCount())
- return CSimpleFileShell();
- return CSimpleFileShell(Entry->SubFiles[nSubIndex]);
- }
- static inline int _GetDirSplitMarkPos(LPCTSTR lpszPath, bool bReverse = false)
- {
- if(lpszPath == NULL) return -1;
- if(!bReverse)
- {
- const char* pch1 = strchr(lpszPath, '\\');
- const char* pch2 = strchr(lpszPath, '/');
- if(pch1 && pch2)
- {
- if(pch2 - pch1 > 0) return (pch1 - lpszPath);
- else return (pch2 - lpszPath);
- }
- else if(pch2) return (pch2 - lpszPath);
- else if(pch1) return (pch1 - lpszPath);
-
- }
- else
- {
- const char* pch1 = strrchr(lpszPath, '\\');
- const char* pch2 = strrchr(lpszPath, '/');
- if(pch1 && pch2)
- {
- if(pch2 - pch1 > 0) return (pch2 - lpszPath);
- else return (pch1 - lpszPath);
- }
- else if(pch2) return (pch2 - lpszPath);
- else if(pch1) return (pch1 - lpszPath);
- }
- return -1;
- }
- static int GetPathDepth(LPCTSTR lpszPath)
- {
- if(lpszPath == NULL || strlen(lpszPath) == 0) return -1;
- int len = strlen(lpszPath);
- #if defined(_MSC_VER)
- if (!((lpszPath[0] <= 'z' && lpszPath[0] >= 'a') || (lpszPath[0] <= 'Z' && lpszPath[0] >= 'A')))
- return -2;
- if ((len == 2 && lpszPath[1] != ':') || (len == 3 && (lpszPath[1] != ':' || (lpszPath[2] != '\\' && lpszPath[2] != '/'))))
- return -3;
- #else
- if (lpszPath[0] != '/') return -2;
- #endif //_MSC_VER
- CSimpleStringA strPath(lpszPath);
- bool bEndWith = (lpszPath[len-1] == '\\' || lpszPath[len-1] == '/') ? true : false;
- int count = 0;
- int pos = _GetDirSplitMarkPos(lpszPath), tmp;
- const char* pch = NULL;
- while(pos != -1)
- {
- //Dbg("Test: %d", pos);
- pch = lpszPath + pos;
- count++;
- if(pos+1 >= len) break;
- tmp = _GetDirSplitMarkPos(pch+1);
- if(tmp == 0) {
- Dbg("Test: %d [%s]", pos, lpszPath);
- return -4;
- }
- pos = tmp > 0 ? tmp + pos + 1 : tmp;
- }
- if(!bEndWith) count++;
- if(count > 0) return count-1;
- return count;
- }
- static DWORD InitialFileEntity(PFILE_LAYOUT_ENTRY Entry, LPCTSTR lpszPath)
- {
- if(lpszPath == NULL || Entry == NULL)
- return 0;
- Entry->SubFiles.Clear();
- Entry->FileNamesBuffer.Clear();
- Entry->Current.Clear();
- DWORD dwLocate;
- Append(Entry->FileNamesBuffer, (PBYTE)lpszPath, strlen(lpszPath), dwLocate);
- Entry->Current.mNameOffset = dwLocate;
- Entry->Current.mNameLength = strlen(lpszPath);
- DWORD dwDir, dwFile;
- GetSubFileInfors(Entry, dwDir, dwFile);
- Dbg("dwDir:%u,dwFile:%u", dwDir, dwFile);
- DisplayFileEntities(Entry);
- return dwFile+dwFile;
- }
- static UINT GetDirSplitPath(LPCTSTR lpszPath, const int back_num, LPTSTR lpszRetPath, const size_t path_max_size)
- {
- if(lpszRetPath == NULL) return FALSE;
- memset(lpszRetPath, 0, path_max_size);
- if(lpszPath == 0 || strlen(lpszPath) == 0) return FALSE;
- int depth = GetPathDepth(lpszPath);
- if(depth < back_num) return FALSE;
- const size_t pathLen = strlen(lpszPath);
- if(pathLen+1 > path_max_size) return FALSE;
- char* pPath = lpszRetPath;
- if(pPath)
- {
- memcpy_s(pPath, path_max_size, lpszPath, pathLen);
- int pos = pathLen-1;
- for(; pos>=0 && (pPath[pos] == '\\' || pPath[pos] == '/'); --pos)
- pPath[pos] = '\0';
- pPath[pos+1] = '\0';
- int len = strlen(pPath);
- Dbg("PathLen(%d) VS RealLen(%d)", pathLen, len);
- int schedule = 0, aim = back_num, maxi = depth + 1;
- char* pch = NULL;
- pos = 0;
- while(schedule < aim && schedule < maxi)
- {
- pos = _GetDirSplitMarkPos(pPath, true);
- LOG_ASSERT(pos != -1);
- pPath[pos] = '\0';
- schedule++;
- }
- }
- return strlen(pPath);
- }
- //UpLevel > 0: means children index for current entry (Warning: the first child index is 1)
- //UpLevel < 0: means track back ancstor for current entry.
- //UpLevel = 0: do nothing.
- //Return true if succeed otherwise failed.
- static BOOL TraceExtend(PFILE_LAYOUT_ENTRY Entry, int UpLevel)
- {
- if(Entry == NULL) return FALSE;
- if(UpLevel == 0) return TRUE;
- if(UpLevel > 0 && UpLevel > Entry->SubFiles.GetCount())
- return FALSE;
- BOOL bRet = FALSE;
- CSimpleStringA strPath;
- CSimpleStringA strParentPath;
- ULARGE_INTEGER uliOffsetLength;
- uliOffsetLength.u.LowPart = 0;
- uliOffsetLength.u.HighPart = Entry->Current.mNameLength;
- if(GetSubFileName(Entry->FileNamesBuffer,
- Entry->FileNamesBuffer.GetCount(), strParentPath, &uliOffsetLength))
- {
- Dbg("TraceExtend::GetSubFileName suc: %d", UpLevel);
- if(UpLevel < 0)
- {
- UpLevel = 0-UpLevel;
- int depth = GetPathDepth(strParentPath);
- if(depth >= 0 && depth + 1 - UpLevel > 0)
- {
- const int pathLen = strParentPath.GetLength();
- char* pPath = new char[pathLen+1];
- if(pPath)
- {
- GetDirSplitPath(strParentPath, UpLevel, pPath, pathLen+1);
- strPath = pPath;
- delete[] pPath;
- pPath = NULL;
- }
- }
- }
- else
- {
- CSimpleFileShell item = RetriveSubFile(Entry, UpLevel-1);
- if((CSimpleFileComponent*)item)
- {
- uliOffsetLength.u.LowPart = item->mNameOffset;
- uliOffsetLength.u.HighPart = item->mNameLength;
- if(GetFullFilePath(strParentPath, Entry->FileNamesBuffer
- ,Entry->FileNamesBuffer.GetCount(), strPath, &uliOffsetLength))
- {
- }
- }
- }
- }
- if(!strPath.IsNullOrEmpty())
- {
- Entry->SubFiles.Clear();
- Entry->FileNamesBuffer.Clear();
- Entry->Current.Clear();
- DWORD dwLocate;
- Append(Entry->FileNamesBuffer, (PBYTE)(LPCTSTR)strPath, strPath.GetLength(), dwLocate);
- assert(dwLocate == 0);
- Dbg("TraceExtend::dwLocate %d", dwLocate);
- Entry->Current.mNameOffset = dwLocate;
- Entry->Current.mNameLength = strPath.GetLength();
- bRet = TRUE;
- DWORD dwDir, dwFile;
- GetSubFileInfors(Entry, dwDir, dwFile);
- Dbg("dwDir:%u,dwFile:%u", dwDir, dwFile);
- DisplayFileEntities(Entry);
- }
- return bRet;
- }
- /*返回该目录下的文件数量(文件+文件夹)*/
- ULONGLONG GetSubFileInfors(PFILE_LAYOUT_ENTRY Entry, DWORD& dwDirCount, DWORD& dwFileCount, const DWORD dwFilterMask)
- {
- dwDirCount = dwFileCount = 0;
- if(Entry == NULL) {
- return 0;
- }
- Dbg("dwFilter: 0x%08X", dwFilterMask);
- const BYTE* buffer = (const BYTE*)Entry->FileNamesBuffer;
- int nLength = Entry->Current.mNameLength;
- int nLengthSuffix = nLength + 3;
- char* pszParentPah = new char[nLengthSuffix];
- if(pszParentPah == NULL) {
- LogWarn(Severity_Middle, Error_Resource, 0, "New char-type buffer failed.");
- return 0;
- }
- ZeroMemory(pszParentPah, nLengthSuffix);
- memcpy_s(pszParentPah, nLength, buffer + Entry->Current.mNameOffset, nLength);
- #if defined(_MSC_VER)
- pszParentPah[nLength] = '\\';
- pszParentPah[nLength + 1] = '\0';
- CSimpleStringA csPath(pszParentPah);
- csPath += "\\*";
- WIN32_FIND_DATA wfd;
- HANDLE hFind;
- hFind = FindFirstFileA(csPath, &wfd);
- if (hFind == INVALID_HANDLE_VALUE) {
- Dbg("FindFirstFile failed GLE = %u.", GetLastError());
- delete[] pszParentPah;
- return 0;
- }
- do {
- if (((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY
- && wfd.cFileName[0] != '.')
- || !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- //Dbg("%s", wfd.cFileName);
- if ((wfd.dwFileAttributes & dwFilterMask) == 0) {
- CSimpleFileComponent folder;
- ULARGE_INTEGER ulTmpValue;
- folder.mAttributes = wfd.dwFileAttributes;
- ulTmpValue.HighPart = wfd.ftLastAccessTime.dwHighDateTime;
- ulTmpValue.LowPart = wfd.ftLastAccessTime.dwLowDateTime;
- folder.mftAccess = ulTmpValue.QuadPart;
- ulTmpValue.HighPart = wfd.ftCreationTime.dwHighDateTime;
- ulTmpValue.LowPart = wfd.ftCreationTime.dwLowDateTime;
- folder.mftCreate = ulTmpValue.QuadPart;
- ulTmpValue.HighPart = wfd.ftLastWriteTime.dwHighDateTime;
- ulTmpValue.LowPart = wfd.ftLastWriteTime.dwLowDateTime;
- folder.mftModified = ulTmpValue.QuadPart;
- ulTmpValue.HighPart = wfd.nFileSizeHigh;
- ulTmpValue.LowPart = wfd.nFileSizeLow;
- folder.mFileSize = ulTmpValue.QuadPart;
- const DWORD dwNameLen = strlen(wfd.cFileName);
- Append(Entry->FileNamesBuffer, (PBYTE)wfd.cFileName, dwNameLen, folder.mNameOffset);
- folder.mNameLength = dwNameLen;
- Entry->SubFiles.Append(&folder, 0, 1);
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) dwDirCount++;
- else dwFileCount++;
- } else {
- Dbg("flag1:%s - 0x%08X", wfd.cFileName, wfd.dwFileAttributes);
- }
- } else {
- Dbg("flag2:%s - 0x%08X", wfd.cFileName, wfd.dwFileAttributes);
- }
- } while (FindNextFileA(hFind, &wfd));
- FindClose(hFind);
- #else
- CSimpleStringA csPath(pszParentPah);
- struct stat fileStat;
- if (stat(csPath, &fileStat) < 0 || !S_ISDIR(fileStat.st_mode)) {
- Dbg("stat for %s failed or is not dir", csPath.GetData());
- delete[] pszParentPah;
- return 0;
- }
- DIR* d = opendir(csPath);
- if (!d) {
- Dbg("opendir %s failed: %s", (LPCTSTR)csPath, strerror(errno));
- delete[] pszParentPah;
- return 0;
- }
- struct dirent* dp = NULL;
- while ((dp = readdir(d)) != NULL) {
- if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, ".."))) {
- continue;
- }
- char tempFilePath[MAX_PATH*2] = { 0 };
- strcpy(tempFilePath, pszParentPah);
- if (strlen(tempFilePath) + strlen(dp->d_name) + 3 >= MAX_PATH * 2) {
- Dbg("filePath is too long for current.");
- continue;
- }
- strcat(tempFilePath, "/");
- strcat(tempFilePath, dp->d_name);
- stat(tempFilePath, &fileStat);
- CSimpleFileComponent folder;
- folder.mAttributes = 0;
- if (S_ISDIR(fileStat.st_mode)) {
- folder.mAttributes |= FILE_ATTRIBUTE_DIRECTORY;
- folder.mFileSize = GetDirectoryItemCount(tempFilePath); //GetDirectorySize(tempFilePath);
- } else {
- folder.mFileSize = fileStat.st_size;
- }
- if (folder.mAttributes == 0)
- folder.mAttributes = FILE_ATTRIBUTE_ARCHIVE;
- if (!(fileStat.st_mode & S_IWUSR))
- folder.mAttributes |= FILE_ATTRIBUTE_READONLY;
- folder.mftAccess = fileStat.st_atime;
- folder.mftCreate = fileStat.st_ctime;
- folder.mftModified = fileStat.st_mtime;
-
- const DWORD dwNameLen = strlen(dp->d_name);
- Append(Entry->FileNamesBuffer, (PBYTE)dp->d_name, dwNameLen, folder.mNameOffset);
- folder.mNameLength = dwNameLen;
- Entry->SubFiles.Append(&folder, 0, 1);
- if (folder.mAttributes & FILE_ATTRIBUTE_DIRECTORY) { dwDirCount++; }
- else dwFileCount++;
- }
- closedir(d);
- #endif //_MSC_VER
- delete[] pszParentPah;
- return ( dwDirCount + dwFileCount);
- }
- void DisplayFileEntities(const PFILE_LAYOUT_ENTRY Entry)
- {
- if(Entry == NULL) return;
- CSimpleStringA csParentName, csFileName, csAttributes, csFilePath;
- ULARGE_INTEGER uliOffsetLength;
- uliOffsetLength.u.LowPart = Entry->Current.mNameOffset;
- uliOffsetLength.u.HighPart = Entry->Current.mNameLength;
- GetSubFileName(Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
- csParentName, &uliOffsetLength);
- char szFormat[128] = {0};
- Dbg("FileCount under [%s]: (%d)", (LPCTSTR)csParentName, Entry->SubFiles.GetCount());
- #if 0
- for(int i=0; i<Entry->SubFiles.GetCount(); ++i)
- {
- Dbg("***********************************************");
- const CSimpleFileComponent& cur = Entry->SubFiles[i];
- uliOffsetLength.LowPart = cur.mNameOffset;
- uliOffsetLength.HighPart = cur.mNameLength;
- Dbg("mNameOffset: %u, mNameLength: %u.", cur.mNameOffset, cur.mNameLength);
- GetSubFileName(Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
- csFileName, &uliOffsetLength);
- Dbg("[%d] %s =>", i, (LPCTSTR)csFileName);
- GetTimeFormatStr(szFormat, 128, (FILETIME*)&cur.mftCreate);
- Dbg("Create: %s", szFormat);
- //GetTimeFormatStr(szFormat, 128, (FILETIME*)&cur.mftModified);
- //Dbg("Modifi: %s", szFormat);
- //GetTimeFormatStr(szFormat, 128, (FILETIME*)&cur.mftAccess);
- //Dbg("Access: %s", szFormat);
- GetAttributeFormat(cur.mAttributes, csAttributes);
- Dbg("Attributes(0x%X): %s", cur.mAttributes, (LPCTSTR)csAttributes);
- GetFullFilePath(Entry, i, csFilePath);
- Dbg("FullPath1: %s", (LPCTSTR)csFilePath);
- //GetFullFilePath(csParentName, Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
- // csFilePath, &uliOffsetLength);
- //Dbg("FullPath2: %s", (LPCTSTR)csFilePath);
- //Dbg("PathDepth: %d", GetPathDepth(csFilePath));
- }
- #endif
- }
- static BOOL IsPathExisted(LPCTSTR lpszPath, FileType& retType)
- {
- retType = FT_Unknown;
- size_t len = 0;
- if (lpszPath == NULL || (len = strlen(lpszPath)) == 0)
- return FALSE;
- #if defined(RVC_OS_WIN)
- if (len == 1) {
- if (!((lpszPath[0] <= 'z' && lpszPath[0] >= 'a') || (lpszPath[0] <= 'Z' && lpszPath[0] >= 'A')))
- return FALSE;
- }
- if (len >= 2 && lpszPath[1] != ':')
- return FALSE;
- if (len >= 3 && (lpszPath[2] != '\\' && lpszPath[2] != '/'))
- return FALSE;
- if (len <= 3) {
- char disk = lpszPath[0];
- if (disk >= 'a' && disk <= 'z') disk -= 32;
- int no = disk - 'A';
- DWORD dwRes = GetLogicalDrives();
- if ((dwRes & (1 << no)) == 0)
- return FALSE;
- retType = FT_Volume;
- return TRUE;
- }
- #else
- if (len == 1 && lpszPath[0] != '/') {
- return FALSE;
- }
- #endif //RVC_OS_WIN
- char* path = new char[len + 1];
- LOG_ASSERT(path != NULL);
- memset(path, 0, sizeof(char) * (len + 1));
- memcpy(path, lpszPath, len);
- path[len] = '\0';
- int pos = len - 1;
- for (; pos >= 0 && (path[pos] == '\\' || path[pos] == '/'); --pos) {
- ;//
- }
- path[pos + 1] = '\0';
- #if defined(_MSC_VER)
- WIN32_FIND_DATA wfd = { 0 };
- HANDLE hFile = FindFirstFileA(path, &wfd);
- if (hFile == INVALID_HANDLE_VALUE) {
- delete[] path;
- return FALSE;
- }
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) retType = FT_Directory;
- else retType = FT_File;
- FindClose(hFile);
- #else
- if (ExistsDirA(path)) {
- retType = FT_Directory;
- } else if (ExistsFileA(path)) {
- retType = FT_File;
- } else {
- delete[] path;
- return FALSE;
- }
- #endif //_MSC_VER
- delete[] path;
- return TRUE;
- }
- static bool _CompareFunc(CSimpleFileShell lhs, CSimpleFileShell rhs) {
- if(lhs->mftModified > rhs->mftModified)
- return true;
- return false;
- }
- #endif //_TWINKLE_CICOMPONENT_INTERFACE_H__
|