void CDirItems::EnumerateDirItems2(const FString &phyPrefix, const UString &logPrefix, const FStringVector &filePaths, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, fs2us(phyPrefix)); int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); for (int i = 0; i < filePaths.Size(); i++) { const FString &filePath = filePaths[i]; NFind::CFileInfo fi; const FString phyPath = phyPrefix + filePath; if (!fi.Find(phyPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPath); continue; } int delimiter = filePath.ReverseFind(FCHAR_PATH_SEPARATOR); FString phyPrefixCur; int phyParentCur = phyParent; if (delimiter >= 0) { phyPrefixCur = filePath.Left(delimiter + 1); phyParentCur = AddPrefix(phyParent, logParent, fs2us(phyPrefixCur)); } AddDirFileInfo(phyParentCur, logParent, fi, Items); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; int parent = AddPrefix(phyParentCur, logParent, fs2us(name2)); EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); } } ReserveDown(); }
HRESULT CDirEnumerator::GetNextFile(NFind::CFileInfo &fileInfo, bool &filled, FString &resPath) { filled = false; for (;;) { if (Enumerators.IsEmpty()) { if (Index >= FileNames.Size()) return S_OK; const FString &path = FileNames[Index]; int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); resPath.Empty(); if (pos >= 0) resPath = path.Left(pos + 1); #ifdef _WIN32 // it's for "c:" paths/ if (BasePrefix.IsEmpty() && path.Length() == 2 && path[1] == ':') { fileInfo.Name = path; fileInfo.Attrib = FILE_ATTRIBUTE_DIRECTORY; fileInfo.Size = 0; } else #endif if (!fileInfo.Find(BasePrefix + path)) { WRes errorCode = GetNormalizedError(); resPath = path; return errorCode; } Index++; break; } bool found; if (!Enumerators.Back().Next(fileInfo, found)) { HRESULT errorCode = GetNormalizedError(); resPath = Prefixes.Back(); return errorCode; } if (found) { resPath = Prefixes.Back(); break; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fileInfo.Name; if (!FlatMode && fileInfo.IsDir()) { FString prefix = resPath + FCHAR_PATH_SEPARATOR; Enumerators.Add(NFind::CEnumerator(BasePrefix + prefix + FCHAR_ANY_MASK)); Prefixes.Add(prefix); } filled = true; return S_OK; }
STDMETHODIMP CFSDrives::LoadItems() { _drives.Clear(); FStringVector driveStrings; MyGetLogicalDriveStrings(driveStrings); for (int i = 0; i < driveStrings.Size(); i++) { CDriveInfo di; const FString &driveName = driveStrings[i]; di.FullSystemName = driveName; if (!driveName.IsEmpty()) di.Name = driveName.Left(driveName.Length() - 1); di.ClusterSize = 0; di.DriveSize = 0; di.FreeSpace = 0; di.DriveType = NFile::NSystem::MyGetDriveType(driveName); bool needRead = true; if (di.DriveType == DRIVE_CDROM || di.DriveType == DRIVE_REMOVABLE) { /* DWORD dwSerialNumber;` if (!::GetVolumeInformation(di.FullSystemName, NULL, 0, &dwSerialNumber, NULL, NULL, NULL, 0)) */ di.KnownSizes = false; { needRead = false; } } if (needRead) { DWORD volumeSerialNumber, maximumComponentLength, fileSystemFlags; NFile::NSystem::MyGetVolumeInformation(driveName, di.VolumeName, &volumeSerialNumber, &maximumComponentLength, &fileSystemFlags, di.FileSystemName); NFile::NSystem::MyGetDiskFreeSpace(driveName, di.ClusterSize, di.DriveSize, di.FreeSpace); di.KnownSizes = true; } _drives.Add(di); } return S_OK; }
void CDirItems::EnumerateDirectory(int phyParent, int logParent, const FString &phyPrefix, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (;;) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); return; } if (!found) break; AddDirFileInfo(phyParent, logParent, fi, Items); if (fi.IsDir()) { const FString name2 = fi.Name + FCHAR_PATH_SEPARATOR; int parent = AddPrefix(phyParent, logParent, fs2us(name2)); EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); } } }
bool CPanel::OnComboBoxCommand(UINT code, LPARAM /* param */, LRESULT &result) { result = FALSE; switch (code) { case CBN_DROPDOWN: { ComboBoxPaths.Clear(); _headerComboBox.ResetContent(); unsigned i; UStringVector pathParts; SplitPathToParts(_currentFolderPrefix, pathParts); UString sumPass; if (!pathParts.IsEmpty()) pathParts.DeleteBack(); for (i = 0; i < pathParts.Size(); i++) { UString name = pathParts[i]; sumPass += name; sumPass.Add_PathSepar(); CFileInfo info; DWORD attrib = FILE_ATTRIBUTE_DIRECTORY; if (info.Find(us2fs(sumPass))) attrib = info.Attrib; AddComboBoxItem(name.IsEmpty() ? L"\\" : name, GetRealIconIndex(us2fs(sumPass), attrib), i, false); ComboBoxPaths.Add(sumPass); } #ifndef UNDER_CE int iconIndex; UString name; name = RootFolder_GetName_Documents(iconIndex); AddComboBoxItem(name, iconIndex, 0, true); name = RootFolder_GetName_Computer(iconIndex); AddComboBoxItem(name, iconIndex, 0, true); FStringVector driveStrings; MyGetLogicalDriveStrings(driveStrings); for (i = 0; i < driveStrings.Size(); i++) { FString s = driveStrings[i]; ComboBoxPaths.Add(fs2us(s)); int iconIndex = GetRealIconIndex(s, 0); if (s.Len() > 0 && s.Back() == FCHAR_PATH_SEPARATOR) s.DeleteBack(); AddComboBoxItem(fs2us(s), iconIndex, 1, false); } name = RootFolder_GetName_Network(iconIndex); AddComboBoxItem(name, iconIndex, 0, true); #endif return false; } case CBN_SELENDOK: { code = code; int index = _headerComboBox.GetCurSel(); if (index >= 0) { UString pass = ComboBoxPaths[index]; _headerComboBox.SetCurSel(-1); // _headerComboBox.SetText(pass); // it's fix for seclecting by mouse. if (BindToPathAndRefresh(pass) == S_OK) { PostMsg(kSetFocusToListView); #ifdef UNDER_CE PostMsg(kRefresh_HeaderComboBox); #endif return true; } } return false; } /* case CBN_CLOSEUP: { LoadFullPathAndShow(); true; } case CBN_SELCHANGE: { // LoadFullPathAndShow(); return true; } */ } return false; }
static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, int phyParent, int logParent, const FString &phyPrefix, const UStringVector &addArchivePrefix, // prefix from curNode CDirItems &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, FStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); // try direct_names case at first if (addArchivePrefix.IsEmpty() && !enterToSubFolders) { // check that all names are direct int i; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; if (item.Recursive || item.PathParts.Size() != 1) break; const UString &name = item.PathParts.Front(); if (name.IsEmpty() || DoesNameContainWildCard(name)) break; } if (i == curNode.IncludeItems.Size()) { // all names are direct (no wildcards) // so we don't need file_system's dir enumerator CRecordVector<bool> needEnterVector; for (i = 0; i < curNode.IncludeItems.Size(); i++) { const NWildcard::CItem &item = curNode.IncludeItems[i]; const UString &name = item.PathParts.Front(); const FString fullPath = phyPrefix + us2fs(name); NFind::CFileInfo fi; if (!fi.Find(fullPath)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fi.IsDir(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } { UStringVector pathParts; pathParts.Add(fs2us(fi.Name)); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (!isDir) continue; UStringVector addArchivePrefixNew; const NWildcard::CCensorNode *nextNode = 0; int index = curNode.FindSubNode(name); if (index >= 0) { for (int t = needEnterVector.Size(); t <= index; t++) needEnterVector.Add(true); needEnterVector[index] = false; nextNode = &curNode.SubNodes[index]; } else { nextNode = &curNode; addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); } for (i = 0; i < curNode.SubNodes.Size(); i++) { if (i < needEnterVector.Size()) if (!needEnterVector[i]) continue; const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; const FString fullPath = phyPrefix + us2fs(nextNode.Name); NFind::CFileInfo fi; if (!fi.Find(fullPath)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fi.IsDir()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumerator enumerator(phyPrefix + FCHAR_ANY_MASK); for (int ttt = 0; ; ttt++) { NFind::CFileInfo fi; bool found; if (!enumerator.Next(fi, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(phyPrefix); break; } if (!found) break; if (callback && (ttt & 0xFF) == 0xFF) RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), fs2us(phyPrefix))); const UString &name = fs2us(fi.Name); bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) { AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); if (fi.IsDir()) enterToSubFolders2 = true; } if (!fi.IsDir()) continue; const NWildcard::CCensorNode *nextNode = 0; if (addArchivePrefix.IsEmpty()) { int index = curNode.FindSubNode(name); if (index >= 0) nextNode = &curNode.SubNodes[index]; } if (!enterToSubFolders2 && nextNode == 0) continue; addArchivePrefixNew = addArchivePrefix; if (nextNode == 0) { nextNode = &curNode; addArchivePrefixNew.Add(name); } RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; }
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath) { filled = false; resPath.Empty(); for (;;) { #if defined(_WIN32) && !defined(UNDER_CE) bool isRootPrefix = (BasePrefix.IsEmpty() || (NName::IsSuperPath(BasePrefix) && BasePrefix[NName::kSuperPathPrefixSize] == 0)); #endif if (Enumerators.IsEmpty()) { if (Index >= FilePaths.Size()) return S_OK; const FString &path = FilePaths[Index++]; int pos = path.ReverseFind_PathSepar(); if (pos >= 0) resPath.SetFrom(path, pos + 1); #if defined(_WIN32) && !defined(UNDER_CE) if (isRootPrefix && path.Len() == 2 && NName::IsDrivePath2(path)) { // we use "c:" item as directory item fi.ClearBase(); fi.Name = path; fi.SetAsDir(); fi.Size = 0; } else #endif if (!fi.Find(BasePrefix + path)) { DWORD error = GetNormalizedError(); resPath = path; return error; } break; } bool found; if (Enumerators.Back().Next(fi, found)) { if (found) { resPath = Prefixes.Back(); break; } } else { DWORD error = GetNormalizedError(); resPath = Prefixes.Back(); Enumerators.DeleteBack(); Prefixes.DeleteBack(); return error; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fi.Name; if (EnterToDirs && fi.IsDir()) { FString s = resPath; s.Add_PathSepar(); Prefixes.Add(s); s += FCHAR_ANY_MASK; Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } filled = true; return S_OK; }
void CDirEnumerator::Init() { Enumerators.Clear(); Prefixes.Clear(); Index = 0; }
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath) { filled = false; resPath.Empty(); for (;;) { if (Enumerators.IsEmpty()) { if (Index >= FilePaths.Size()) return S_OK; const FString &path = FilePaths[Index++]; int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos >= 0) resPath.SetFrom(path, pos + 1); #ifdef _WIN32 if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':') { // we use "c:" item as directory item fi.Clear(); fi.Name = path; fi.SetAsDir(); fi.Size = 0; } else #endif if (!fi.Find(BasePrefix + path)) { DWORD error = GetNormalizedError(); resPath = path; return error; } break; } bool found; if (Enumerators.Back().Next(fi, found)) { if (found) { resPath = Prefixes.Back(); break; } } else { DWORD error = GetNormalizedError(); resPath = Prefixes.Back(); Enumerators.DeleteBack(); Prefixes.DeleteBack(); return error; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fi.Name; if (EnterToDirs && fi.IsDir()) { FString s = resPath; s += FCHAR_PATH_SEPARATOR; Prefixes.Add(s); s += FCHAR_ANY_MASK; Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } filled = true; return S_OK; }
HRESULT CAgentFolder::CommonUpdateOperation( AGENT_OP operation, bool moveMode, const wchar_t *newItemName, const NUpdateArchive::CActionSet *actionSet, const UInt32 *indices, UInt32 numItems, IProgress *progress) { if (!_agentSpec->CanUpdate()) return E_NOTIMPL; CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100; if (progress) progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100); try { RINOK(_agentSpec->SetFolder(this)); // ---------- Save FolderItem ---------- UStringVector pathParts; bool isAltStreamFolder = false; GetPathParts(pathParts, isAltStreamFolder); FStringVector requestedPaths; FStringVector processedPaths; CWorkDirTempFile tempFile; RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath))); { CMyComPtr<IOutStream> tailStream; const CArc &arc = *_agentSpec->_archiveLink.GetArc(); if (arc.ArcStreamOffset == 0) tailStream = tempFile.OutStream; else { if (arc.Offset < 0) return E_NOTIMPL; RINOK(arc.InStream->Seek(0, STREAM_SEEK_SET, NULL)); RINOK(NCompress::CopyStream_ExactSize(arc.InStream, tempFile.OutStream, arc.ArcStreamOffset, NULL)); CTailOutStream *tailStreamSpec = new CTailOutStream; tailStream = tailStreamSpec; tailStreamSpec->Stream = tempFile.OutStream; tailStreamSpec->Offset = arc.ArcStreamOffset; tailStreamSpec->Init(); } HRESULT result; switch (operation) { case AGENT_OP_Delete: result = _agentSpec->DeleteItems(tailStream, indices, numItems, updateCallback100); break; case AGENT_OP_CreateFolder: result = _agentSpec->CreateFolder(tailStream, newItemName, updateCallback100); break; case AGENT_OP_Rename: result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100); break; case AGENT_OP_Comment: result = _agentSpec->CommentItem(tailStream, indices, numItems, newItemName, updateCallback100); break; case AGENT_OP_CopyFromFile: result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100); break; case AGENT_OP_Uni: { Byte actionSetByte[NUpdateArchive::NPairState::kNumValues]; for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++) actionSetByte[i] = (Byte)actionSet->StateActions[i]; result = _agentSpec->DoOperation2( moveMode ? &requestedPaths : NULL, moveMode ? &processedPaths : NULL, tailStream, actionSetByte, NULL, updateCallback100); break; } default: return E_FAIL; } RINOK(result); } _agentSpec->KeepModeForNextOpen(); _agentSpec->Close(); // before 9.26: if there was error for MoveToOriginal archive was closed. // now: we reopen archive after close // m_FolderItem = NULL; HRESULT res = tempFile.MoveToOriginal(true); // RINOK(res); if (res == S_OK) { if (moveMode) { unsigned i; for (i = 0; i < processedPaths.Size(); i++) { DeleteFileAlways(processedPaths[i]); } for (i = 0; i < requestedPaths.Size(); i++) { const FString &fs = requestedPaths[i]; if (NFind::DoesDirExist(fs)) DeleteEmptyFolderAndEmptySubFolders(fs); } } } { CMyComPtr<IArchiveOpenCallback> openCallback; if (updateCallback100) updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback); RINOK(_agentSpec->ReOpen(openCallback)); } // CAgent::ReOpen() deletes _proxy and _proxy2 _items.Clear(); _proxy = NULL; _proxy2 = NULL; _proxyDirIndex = k_Proxy_RootDirIndex; _isAltStreamFolder = false; // ---------- Restore FolderItem ---------- CMyComPtr<IFolderFolder> archiveFolder; RINOK(_agentSpec->BindToRootFolder(&archiveFolder)); // CAgent::BindToRootFolder() changes _proxy and _proxy2 _proxy = _agentSpec->_proxy; _proxy2 = _agentSpec->_proxy2; if (_proxy) { FOR_VECTOR (i, pathParts) { int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]); if (next < 0) break; _proxyDirIndex = next; } } if (_proxy2) { if (pathParts.IsEmpty() && isAltStreamFolder) { _proxyDirIndex = k_Proxy2_AltRootDirIndex; } else FOR_VECTOR (i, pathParts) { bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder); int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly); if (index < 0) break; const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]]; if (dirOnly) _proxyDirIndex = file.DirIndex; else { if (file.AltDirIndex >= 0) _proxyDirIndex = file.AltDirIndex; break; } } }