void EnumerateDirItems( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UStringVector &fileNames, // names relative to baseFolderPrefix const UString &archiveNamePrefix, CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { for(int i = 0; i < fileNames.Size(); i++) { const UString &fileName = fileNames[i]; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(baseFolderPrefix + fileName, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + fileName); continue; } AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter), archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } }
static void EnumerateDirectory( const UString &baseFolderPrefix, // base (disk) prefix for scanning const UString &directory, // additional disk prefix starting from baseFolderPrefix const UString &prefix, // logical prefix CObjectVector<CDirItem> &dirItems, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(baseFolderPrefix + directory); return; } if (!found) break; AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems); if (fileInfo.IsDirectory()) { EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter), prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems, errorPaths, errorCodes); } } }
bool CDirEnumerator::GetNextFile(NFind::CFileInfoW &fileInfo, bool &filled, UString &resPath, DWORD &errorCode) { filled = false; for (;;) { if (Enumerators.IsEmpty()) { if (Index >= FileNames.Size()) return true; const UString &path = FileNames[Index]; int pos = path.ReverseFind('\\'); resPath.Empty(); if (pos >= 0) resPath = path.Left(pos + 1); if (!NFind::FindFile(BasePrefix + path, fileInfo)) { errorCode = ::GetLastError(); resPath = path; return false; } Index++; break; } bool found; if (!Enumerators.Back().Next(fileInfo, found)) { errorCode = ::GetLastError(); resPath = Prefixes.Back(); return false; } if (found) { resPath = Prefixes.Back(); break; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fileInfo.Name; if (!FlatMode && fileInfo.IsDirectory()) { UString prefix = resPath + (UString)(wchar_t)kDirDelimiter; Enumerators.Add(NFind::CEnumeratorW(BasePrefix + prefix + (UString)(wchar_t)kAnyStringWildcard)); Prefixes.Add(prefix); } filled = true; return true; }
static UString GetBaseFolderPrefixFromRegistry() { UString moduleFolderPrefix = GetModuleFolderPrefix(); NFind::CFileInfoW fileInfo; if (NFind::FindFile(moduleFolderPrefix + kFormatFolderName, fileInfo)) if (fileInfo.IsDirectory()) return moduleFolderPrefix; UString path; #ifdef _WIN32 if(ReadPathFromRegistry(HKEY_CURRENT_USER, path)) return path; if(ReadPathFromRegistry(HKEY_LOCAL_MACHINE, path)) return path; #endif return moduleFolderPrefix; }
static HRESULT EnumerateDirItems( const NWildcard::CCensorNode &curNode, const UString &diskPrefix, // full disk path prefix const UString &archivePrefix, // prefix from root const UStringVector &addArchivePrefix, // prefix from curNode CObjectVector<CDirItem> &dirItems, bool enterToSubFolders, IEnumDirItemCallback *callback, UStringVector &errorPaths, CRecordVector<DWORD> &errorCodes) { if (!enterToSubFolders) if (curNode.NeedCheckSubDirs()) enterToSubFolders = true; if (callback) RINOK(callback->CheckBreak()); // 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 UString fullPath = diskPrefix + name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } bool isDir = fileInfo.IsDirectory(); if (isDir && !item.ForDir || !isDir && !item.ForFile) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } const UString realName = fileInfo.getFileName(); const UString realDiskPath = diskPrefix + realName; { UStringVector pathParts; pathParts.Add(fileInfo.getFileName()); if (curNode.CheckPathToRoot(false, pathParts, !isDir)) continue; } AddDirFileInfo(archivePrefix, realDiskPath, fileInfo, dirItems); 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 realName. It's for shortnames support } RINOK(EnumerateDirItems(*nextNode, realDiskPath + wchar_t(kDirDelimiter), archivePrefix + realName + wchar_t(kDirDelimiter), 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 UString fullPath = diskPrefix + nextNode.Name; NFind::CFileInfoW fileInfo; if (!NFind::FindFile(fullPath, fileInfo)) { if (!nextNode.AreThereIncludeItems()) continue; errorCodes.Add(::GetLastError()); errorPaths.Add(fullPath); continue; } if (!fileInfo.IsDirectory()) { errorCodes.Add((DWORD)E_FAIL); errorPaths.Add(fullPath); continue; } RINOK(EnumerateDirItems(nextNode, diskPrefix + fileInfo.getFileName() + wchar_t(kDirDelimiter), archivePrefix + fileInfo.getFileName() + wchar_t(kDirDelimiter), UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); } return S_OK; } } NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard)); for (;;) { NFind::CFileInfoW fileInfo; bool found; if (!enumerator.Next(fileInfo, found)) { errorCodes.Add(::GetLastError()); errorPaths.Add(diskPrefix); break; } if (!found) break; if (callback) RINOK(callback->CheckBreak()); const UString &name = fileInfo.getFileName(); bool enterToSubFolders2 = enterToSubFolders; UStringVector addArchivePrefixNew = addArchivePrefix; addArchivePrefixNew.Add(name); { UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fileInfo.IsDirectory())) continue; } if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fileInfo.IsDirectory())) { AddDirFileInfo(archivePrefix, diskPrefix + name, fileInfo, dirItems); if (fileInfo.IsDirectory()) enterToSubFolders2 = true; } if (!fileInfo.IsDirectory()) 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(*nextNode, diskPrefix + name + wchar_t(kDirDelimiter), archivePrefix + name + wchar_t(kDirDelimiter), addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); } return S_OK; }
void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers) { archivers.Clear(); #ifdef EXCLUDE_COM #ifdef FORMAT_7Z { CArchiverInfo item; item.UpdateEnabled = true; item.Name = L"7z"; item.Extensions.Add(CArchiverExtInfo(L"7z")); #ifndef _SFX const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C}; SetBuffer(item.StartSignature, kSig, 6); #endif archivers.Add(item); } #endif #ifdef FORMAT_BZIP2 { CArchiverInfo item; item.UpdateEnabled = true; item.KeepName = true; item.Name = L"BZip2"; item.Extensions.Add(CArchiverExtInfo(L"bz2")); item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar")); #ifndef _SFX const unsigned char sig[] = {'B' , 'Z', 'h' }; SetBuffer(item.StartSignature, sig, 3); #endif archivers.Add(item); } #endif #ifdef FORMAT_GZIP { CArchiverInfo item; item.UpdateEnabled = true; item.Name = L"GZip"; item.Extensions.Add(CArchiverExtInfo(L"gz")); item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar")); #ifndef _SFX const unsigned char sig[] = { 0x1F, 0x8B }; SetBuffer(item.StartSignature, sig, 2); #endif archivers.Add(item); } #endif #ifdef FORMAT_SPLIT { CArchiverInfo item; item.UpdateEnabled = false; item.KeepName = true; item.Name = L"Split"; item.Extensions.Add(CArchiverExtInfo(L"001")); archivers.Add(item); } #endif #ifdef FORMAT_TAR { CArchiverInfo item; item.UpdateEnabled = true; item.Name = L"Tar"; item.Extensions.Add(CArchiverExtInfo(L"tar")); archivers.Add(item); } #endif #ifdef FORMAT_ZIP { CArchiverInfo item; item.UpdateEnabled = true; item.Name = L"Zip"; item.Extensions.Add(CArchiverExtInfo(L"zip")); #ifndef _SFX const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 }; SetBuffer(item.StartSignature, sig, 4); #endif archivers.Add(item); } #endif #ifdef FORMAT_CPIO { CArchiverInfo item; item.Name = L"Cpio"; item.Extensions.Add(CArchiverExtInfo(L"cpio")); archivers.Add(item); } #endif #ifdef FORMAT_RPM { CArchiverInfo item; item.Name = L"Rpm"; item.Extensions.Add(CArchiverExtInfo(L"rpm", L".cpio.gz")); archivers.Add(item); } #endif #ifdef FORMAT_ARJ { CArchiverInfo item; item.Name = L"Arj"; item.Extensions.Add(CArchiverExtInfo(L"arj")); #ifndef _SFX const unsigned char sig[] = { 0x60, 0xEA }; SetBuffer(item.StartSignature, sig, 2); #endif archivers.Add(item); } #endif #ifdef FORMAT_Z { CArchiverInfo item; item.Name = L"Z"; item.Extensions.Add(CArchiverExtInfo(L"Z")); #ifndef _SFX const unsigned char sig[] = { 0x1F, 0x9D }; SetBuffer(item.StartSignature, sig, 2); #endif archivers.Add(item); } #endif #else UString folderPath = GetBaseFolderPrefixFromRegistry() + (UString)kFormatFolderName + (UString)WSTRING_PATH_SEPARATOR; NFind::CEnumeratorW enumerator(folderPath + L"*"); NFind::CFileInfoW fileInfo; while (enumerator.Next(fileInfo)) { if (fileInfo.IsDirectory()) continue; UString filePath = folderPath + fileInfo.Name; { NDLL::CLibrary library; if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE)) continue; } NDLL::CLibrary library; if (!library.Load(filePath)) continue; GetHandlerPropertyFunc getHandlerProperty = (GetHandlerPropertyFunc) library.GetProcAddress("GetHandlerProperty"); if (getHandlerProperty == NULL) continue; CArchiverInfo item; item.FilePath = filePath; NWindows::NCOM::CPropVariant prop; if (getHandlerProperty(NArchive::kName, &prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.Name = prop.bstrVal; prop.Clear(); if (getHandlerProperty(NArchive::kClassID, &prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; item.ClassID = *(const GUID *)prop.bstrVal; prop.Clear(); if (getHandlerProperty(NArchive::kExtension, &prop) != S_OK) continue; if (prop.vt != VT_BSTR) continue; UString ext = prop.bstrVal; UString addExt; prop.Clear(); if (getHandlerProperty(NArchive::kAddExtension, &prop) != S_OK) continue; if (prop.vt == VT_BSTR) { addExt = prop.bstrVal; } else if (prop.vt != VT_EMPTY) continue; prop.Clear(); UStringVector exts, addExts; SplitString(ext, exts); SplitString(addExt, addExts); prop.Clear(); for (int i = 0; i < exts.Size(); i++) { CArchiverExtInfo extInfo; extInfo.Ext = exts[i]; if (addExts.Size() > 0) extInfo.AddExt = addExts[i]; if (extInfo.AddExt == L"*") extInfo.AddExt.Empty(); item.Extensions.Add(extInfo); } if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK) if (prop.vt == VT_BOOL) item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal); prop.Clear(); if (item.UpdateEnabled) { if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK) if (prop.vt == VT_BOOL) item.KeepName = VARIANT_BOOLToBool(prop.boolVal); prop.Clear(); } if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK) { if (prop.vt == VT_BSTR) { UINT len = ::SysStringByteLen(prop.bstrVal); item.StartSignature.SetCapacity(len); memmove(item.StartSignature, prop.bstrVal, len); } } prop.Clear(); if (getHandlerProperty(NArchive::kAssociate, &prop) == S_OK) if (prop.vt == VT_BOOL) item.Associate = VARIANT_BOOLToBool(prop.boolVal); prop.Clear(); archivers.Add(item); } #endif }
static HRESULT ShowDialog( CCodecs *codecs, const NWildcard::CCensor &censor, CUpdateOptions &options, CUpdateCallbackGUI *callback) { if (options.Commands.Size() != 1) throw "It must be one command"; UString currentDirPrefix; { if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix)) return E_FAIL; NName::NormalizeDirPathPrefix(currentDirPrefix); } bool oneFile = false; NFind::CFileInfoW fileInfo; if (censor.Pairs.Size() > 0) { const NWildcard::CPair &pair = censor.Pairs[0]; if (pair.Head.IncludeItems.Size() > 0) { const NWildcard::CItem &item = pair.Head.IncludeItems[0]; if (item.ForFile) { UString name = pair.Prefix; for (int i = 0; i < item.PathParts.Size(); i++) { if (i > 0) name += L'\\'; name += item.PathParts[i]; } if (NFind::FindFile(name, fileInfo)) { if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1) oneFile = !fileInfo.IsDirectory(); } } } } CCompressDialog dialog; NCompressDialog::CInfo &di = dialog.Info; for(int i = 0; i < codecs->Formats.Size(); i++) { const CArcInfoEx &ai = codecs->Formats[i]; if (ai.UpdateEnabled && (oneFile || !ai.KeepName)) dialog.m_ArchiverInfoList.Add(ai); } if(dialog.m_ArchiverInfoList.Size() == 0) { MyMessageBox(L"No Update Engines"); return E_FAIL; } // di.ArchiveName = options.ArchivePath.GetFinalPath(); di.ArchiveName = options.ArchivePath.GetPathWithoutExt(); dialog.OriginalFileName = fileInfo.Name; di.CurrentDirPrefix = currentDirPrefix; di.SFXMode = options.SfxMode; di.OpenShareForWrite = options.OpenShareForWrite; if (callback->PasswordIsDefined) di.Password = callback->Password; di.KeepName = !oneFile; if(dialog.Create(0) != IDOK) return E_ABORT; options.VolumesSizes = di.VolumeSizes; /* if (di.VolumeSizeIsDefined) { MyMessageBox(L"Splitting to volumes is not supported"); return E_FAIL; } */ NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet; switch(di.UpdateMode) { case NCompressDialog::NUpdateMode::kAdd: actionSet = NUpdateArchive::kAddActionSet; break; case NCompressDialog::NUpdateMode::kUpdate: actionSet = NUpdateArchive::kUpdateActionSet; break; case NCompressDialog::NUpdateMode::kFresh: actionSet = NUpdateArchive::kFreshActionSet; break; case NCompressDialog::NUpdateMode::kSynchronize: actionSet = NUpdateArchive::kSynchronizeActionSet; break; default: throw 1091756; } const CArcInfoEx &archiverInfo = dialog.m_ArchiverInfoList[di.ArchiverInfoIndex]; callback->PasswordIsDefined = (!di.Password.IsEmpty()); if (callback->PasswordIsDefined) callback->Password = di.Password; options.MethodMode.Properties.Clear(); bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0; bool methodOverride = IsThereMethodOverride(is7z, di.Options); SetOutProperties( options.MethodMode.Properties, is7z, di.Level, !methodOverride, di.Method, di.Dictionary, di.OrderMode, di.Order, di.SolidIsSpecified, di.SolidBlockSize, di.MultiThreadIsAllowed, di.NumThreads, di.EncryptionMethod, di.EncryptHeadersIsAllowed, di.EncryptHeaders, di.SFXMode); options.OpenShareForWrite = di.OpenShareForWrite; ParseAndAddPropertires(options.MethodMode.Properties, di.Options); if (di.SFXMode) options.SfxMode = true; options.MethodMode.FormatIndex = archiverInfo.FormatIndex; options.ArchivePath.VolExtension = archiverInfo.GetMainExt(); if(di.SFXMode) options.ArchivePath.BaseExtension = kSFXExtension; else options.ArchivePath.BaseExtension = options.ArchivePath.VolExtension; options.ArchivePath.ParseFromPath(di.ArchiveName); NWorkDir::CInfo workDirInfo; ReadWorkDirInfo(workDirInfo); options.WorkingDir.Empty(); if (workDirInfo.Mode != NWorkDir::NMode::kCurrent) { UString fullPath; NDirectory::MyGetFullPathName(di.ArchiveName, fullPath); options.WorkingDir = GetWorkDir(workDirInfo, fullPath); NFile::NDirectory::CreateComplexDirectory(options.WorkingDir); } return S_OK; }