|
@@ -1,945 +0,0 @@
|
|
|
-#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) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("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) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("filePath is too long for current.");
|
|
|
- continue;
|
|
|
- }
|
|
|
- strcat(tempFilePath, "/");
|
|
|
- strcat(tempFilePath, dp->d_name);
|
|
|
- struct stat fileStat;
|
|
|
- if (stat(tempFilePath, &fileStat) < 0) {
|
|
|
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("stat dir for %s failed: %d ", tempFilePath, errno);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if (S_ISDIR(fileStat.st_mode)) {
|
|
|
- if (nDepth + 1 >= 0) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("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) {
|
|
|
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("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) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("filePath is too long for current.");
|
|
|
- continue;
|
|
|
- }
|
|
|
- strcat(tempFilePath, "/");
|
|
|
- strcat(tempFilePath, dp->d_name);
|
|
|
- struct stat fileStat;
|
|
|
- if (stat(tempFilePath, &fileStat) < 0) {
|
|
|
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("stat dir for %s failed: %d ", tempFilePath, errno);
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- if (S_ISDIR(fileStat.st_mode)) {
|
|
|
- if (nDepth + 1 >= 0) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("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);
|
|
|
- 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;
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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)
|
|
|
- {
|
|
|
- pch = lpszPath + pos;
|
|
|
- count++;
|
|
|
- if(pos+1 >= len) break;
|
|
|
- tmp = _GetDirSplitMarkPos(pch+1);
|
|
|
- if(tmp == 0) {
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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))
|
|
|
- {
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("TraceExtend::dwLocate %d", dwLocate);
|
|
|
- Entry->Current.mNameOffset = dwLocate;
|
|
|
- Entry->Current.mNameLength = strPath.GetLength();
|
|
|
- bRet = TRUE;
|
|
|
- DWORD dwDir, dwFile;
|
|
|
- GetSubFileInfors(Entry, dwDir, dwFile);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("dwDir:%u,dwFile:%u", dwDir, dwFile);
|
|
|
- DisplayFileEntities(Entry);
|
|
|
- }
|
|
|
- return bRet;
|
|
|
-}
|
|
|
-
|
|
|
-/*return the count of current dir(folder and file)*/
|
|
|
-ULONGLONG GetSubFileInfors(PFILE_LAYOUT_ENTRY Entry, DWORD& dwDirCount, DWORD& dwFileCount, const DWORD dwFilterMask)
|
|
|
-{
|
|
|
- dwDirCount = dwFileCount = 0;
|
|
|
- if(Entry == NULL) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("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)) {
|
|
|
- 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 {
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("flag1:%s - 0x%08X", wfd.cFileName, wfd.dwFileAttributes);
|
|
|
- }
|
|
|
- } else {
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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)) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("stat for %s failed or is not dir", csPath.GetData());
|
|
|
- delete[] pszParentPah;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- DIR* d = opendir(csPath);
|
|
|
- if (!d) {
|
|
|
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("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) {
|
|
|
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("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};
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("FileCount under [%s]: (%d)", (LPCTSTR)csParentName, Entry->SubFiles.GetCount());
|
|
|
-#if 0
|
|
|
- for(int i=0; i<Entry->SubFiles.GetCount(); ++i)
|
|
|
- {
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("***********************************************");
|
|
|
- const CSimpleFileComponent& cur = Entry->SubFiles[i];
|
|
|
- uliOffsetLength.LowPart = cur.mNameOffset;
|
|
|
- uliOffsetLength.HighPart = cur.mNameLength;
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("mNameOffset: %u, mNameLength: %u.", cur.mNameOffset, cur.mNameLength);
|
|
|
- GetSubFileName(Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
|
|
|
- csFileName, &uliOffsetLength);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("[%d] %s =>", i, (LPCTSTR)csFileName);
|
|
|
- GetTimeFormatStr(szFormat, 128, (FILETIME*)&cur.mftCreate);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Create: %s", szFormat);
|
|
|
- //GetTimeFormatStr(szFormat, 128, (FILETIME*)&cur.mftModified);
|
|
|
- //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Modifi: %s", szFormat);
|
|
|
- //GetTimeFormatStr(szFormat, 128, (FILETIME*)&cur.mftAccess);
|
|
|
- //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Access: %s", szFormat);
|
|
|
- GetAttributeFormat(cur.mAttributes, csAttributes);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Attributes(0x%X): %s", cur.mAttributes, (LPCTSTR)csAttributes);
|
|
|
- GetFullFilePath(Entry, i, csFilePath);
|
|
|
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("FullPath1: %s", (LPCTSTR)csFilePath);
|
|
|
- //GetFullFilePath(csParentName, Entry->FileNamesBuffer, Entry->FileNamesBuffer.GetCount(),
|
|
|
- // csFilePath, &uliOffsetLength);
|
|
|
- //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("FullPath2: %s", (LPCTSTR)csFilePath);
|
|
|
- //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("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__
|