📄 update.cpp
字号:
outStream = volStreamSpec;
volStreamSpec->Sizes = volumesSizes;
volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
volStreamSpec->TempFiles = &tempFiles;
volStreamSpec->Init();
/*
updateCallbackSpec->VolumesSizes = volumesSizes;
updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
if (!archivePath.VolExtension.IsEmpty())
updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
*/
}
RINOK(SetProperties(outArchive, compressionMethod.Properties));
if (sfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
if (!sfxStreamSpec->Open(sfxModule))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"Can't open sfx module";
errorInfo.FileName = sfxModule;
return E_FAIL;
}
CMyComPtr<ISequentialOutStream> sfxOutStream;
COutFileStream *outStreamSpec = NULL;
if (volumesSizes.Size() == 0)
sfxOutStream = outStream;
else
{
outStreamSpec = new COutFileStream;
sfxOutStream = outStreamSpec;
UString realPath = archivePath.GetFinalPath();
if (!outStreamSpec->Create(realPath, false))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.FileName = realPath;
errorInfo.Message = L"Can not open file";
return E_FAIL;
}
}
RINOK(CopyBlock(sfxStream, sfxOutStream));
if (outStreamSpec)
{
RINOK(outStreamSpec->Close());
}
}
HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updateCallback);
callback->Finilize();
RINOK(result);
if (outStreamSpec)
result = outStreamSpec->Close();
else if (volStreamSpec)
result = volStreamSpec->Close();
return result;
}
HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
CObjectVector<CArcItem> &arcItems)
{
arcItems.Clear();
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
arcItems.Reserve(numItems);
for (UInt32 i = 0; i < numItems; i++)
{
CArcItem ai;
RINOK(GetArchiveItemPath(archive, i, ai.Name));
// check it: defaultItemName !!!
if (ai.Name.IsEmpty())
ai.Name = defaultItemName;
RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));
ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);
RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime));
{
CPropVariant prop;
RINOK(archive->GetProperty(i, kpidSize, &prop));
ai.SizeDefined = (prop.vt != VT_EMPTY);
if (ai.SizeDefined)
ai.Size = ConvertPropVariantToUInt64(prop);
}
{
CPropVariant prop;
RINOK(archive->GetProperty(i, kpidTimeType, &prop));
if (prop.vt == VT_UI4)
{
ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
switch(ai.TimeType)
{
case NFileTimeType::kWindows:
case NFileTimeType::kUnix:
case NFileTimeType::kDOS:
break;
default:
return E_FAIL;
}
}
}
ai.IndexInServer = i;
arcItems.Add(ai);
}
return S_OK;
}
static HRESULT UpdateWithItemLists(
CCodecs *codecs,
CUpdateOptions &options,
IInArchive *archive,
const CObjectVector<CArcItem> &arcItems,
CDirItems &dirItems,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI2 *callback)
{
for(int i = 0; i < options.Commands.Size(); i++)
{
CUpdateArchiveCommand &command = options.Commands[i];
if (options.StdOutMode)
{
RINOK(callback->StartArchive(0, archive != 0));
}
else
{
RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
i == 0 && options.UpdateArchiveItself && archive != 0));
}
RINOK(Compress(
codecs,
command.ActionSet, archive,
options.MethodMode,
command.ArchivePath,
arcItems,
options.OpenShareForWrite,
options.StdInMode,
/* options.StdInFileName, */
options.StdOutMode,
dirItems,
options.SfxMode, options.SfxModule,
options.VolumesSizes,
tempFiles,
errorInfo, callback));
RINOK(callback->FinishArchive());
}
return S_OK;
}
#ifdef _WIN32
class CCurrentDirRestorer
{
UString m_CurrentDirectory;
public:
CCurrentDirRestorer()
{ NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
~CCurrentDirRestorer()
{ RestoreDirectory();}
bool RestoreDirectory()
{ return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirectory)); }
};
#endif
struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
{
IUpdateCallbackUI2 *Callback;
HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)
{
return Callback->ScanProgress(numFolders, numFiles, path);
}
};
#ifdef _WIN32
typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(
ULONG_PTR ulUIParam,
LPSTR lpszDelimChar,
LPSTR lpszFilePaths,
LPSTR lpszFileNames,
ULONG ulReserved
);
typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;
#endif
HRESULT UpdateArchive(
CCodecs *codecs,
const NWildcard::CCensor &censor,
CUpdateOptions &options,
CUpdateErrorInfo &errorInfo,
IOpenCallbackUI *openCallback,
IUpdateCallbackUI2 *callback)
{
if (options.StdOutMode && options.EMailMode)
return E_FAIL;
if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
return E_NOTIMPL;
if (options.SfxMode)
{
CProperty property;
property.Name = L"rsfx";
property.Value = L"on";
options.MethodMode.Properties.Add(property);
if (options.SfxModule.IsEmpty())
{
errorInfo.Message = L"sfx file is not specified";
return E_FAIL;
}
UString name = options.SfxModule;
if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
{
errorInfo.Message = L"can't find specified sfx module";
return E_FAIL;
}
}
const UString archiveName = options.ArchivePath.GetFinalPath();
UString defaultItemName;
NFind::CFileInfoW archiveFileInfo;
CArchiveLink archiveLink;
IInArchive *archive = 0;
if (NFind::FindFile(archiveName, archiveFileInfo))
{
if (archiveFileInfo.IsDir())
throw "there is no such archive";
if (options.VolumesSizes.Size() > 0)
return E_NOTIMPL;
CIntVector formatIndices;
if (options.MethodMode.FormatIndex >= 0)
formatIndices.Add(options.MethodMode.FormatIndex);
HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLink, openCallback);
if (result == E_ABORT)
return result;
RINOK(callback->OpenResult(archiveName, result));
RINOK(result);
if (archiveLink.VolumePaths.Size() > 1)
{
errorInfo.SystemError = (DWORD)E_NOTIMPL;
errorInfo.Message = L"Updating for multivolume archives is not implemented";
return E_NOTIMPL;
}
archive = archiveLink.GetArchive();
defaultItemName = archiveLink.GetDefaultItemName();
}
else
{
/*
if (archiveType.IsEmpty())
throw "type of archive is not specified";
*/
}
CDirItems dirItems;
if (options.StdInMode)
{
CDirItem di;
di.Name = options.StdInFileName;
di.Size = (UInt64)(Int64)-1;
di.Attrib = 0;
NTime::GetCurUtcFileTime(di.MTime);
di.CTime = di.ATime = di.MTime;
dirItems.Items.Add(di);
}
else
{
bool needScanning = false;
for(int i = 0; i < options.Commands.Size(); i++)
if (options.Commands[i].ActionSet.NeedScanning())
needScanning = true;
if (needScanning)
{
CEnumDirItemUpdateCallback enumCallback;
enumCallback.Callback = callback;
RINOK(callback->StartScanning());
UStringVector errorPaths;
CRecordVector<DWORD> errorCodes;
HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);
for (int i = 0; i < errorPaths.Size(); i++)
{
RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));
}
if (res != S_OK)
{
if (res != E_ABORT)
errorInfo.Message = L"Scanning error";
// errorInfo.FileName = errorPath;
return res;
}
RINOK(callback->FinishScanning());
}
}
UString tempDirPrefix;
bool usesTempDir = false;
#ifdef _WIN32
NDirectory::CTempDirectoryW tempDirectory;
if (options.EMailMode && options.EMailRemoveAfter)
{
tempDirectory.Create(kTempFolderPrefix);
tempDirPrefix = tempDirectory.GetPath();
NormalizeDirPathPrefix(tempDirPrefix);
usesTempDir = true;
}
#endif
CTempFiles tempFiles;
bool createTempFile = false;
if(!options.StdOutMode && options.UpdateArchiveItself)
{
CArchivePath &ap = options.Commands[0].ArchivePath;
ap = options.ArchivePath;
// if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && options.VolumesSizes.Size() == 0)
{
createTempFile = true;
ap.Temp = true;
if (!options.WorkingDir.IsEmpty())
{
ap.TempPrefix = options.WorkingDir;
NormalizeDirPathPrefix(ap.TempPrefix);
}
}
}
for(int i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
if (usesTempDir)
{
// Check it
ap.Prefix = tempDirPrefix;
// ap.Temp = true;
// ap.TempPrefix = tempDirPrefix;
}
if (i > 0 || !createTempFile)
{
const UString &path = ap.GetFinalPath();
if (NFind::DoesFileExist(path))
{
errorInfo.SystemError = 0;
errorInfo.Message = L"File already exists";
errorInfo.FileName = path;
return E_FAIL;
}
}
}
CObjectVector<CArcItem> arcItems;
if (archive != NULL)
{
RINOK(EnumerateInArchiveItems(censor,
archive, defaultItemName, archiveFileInfo, arcItems));
}
RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems,
tempFiles, errorInfo, callback));
if (archive != NULL)
{
RINOK(archiveLink.Close());
archiveLink.Release();
}
tempFiles.Paths.Clear();
if(createTempFile)
{
try
{
CArchivePath &ap = options.Commands[0].ArchivePath;
const UString &tempPath = ap.GetTempPath();
if (archive != NULL)
if (!NDirectory::DeleteFileAlways(archiveName))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"delete file error";
errorInfo.FileName = archiveName;
return E_FAIL;
}
if (!NDirectory::MyMoveFile(tempPath, archiveName))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"move file error";
errorInfo.FileName = tempPath;
errorInfo.FileName2 = archiveName;
return E_FAIL;
}
}
catch(...)
{
throw;
}
}
#ifdef _WIN32
if (options.EMailMode)
{
NDLL::CLibrary mapiLib;
if (!mapiLib.Load(TEXT("Mapi32.dll")))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"can not load Mapi32.dll";
return E_FAIL;
}
MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)
mapiLib.GetProcAddress("MAPISendDocuments");
if (fnSend == 0)
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"can not find MAPISendDocuments function";
return E_FAIL;
}
UStringVector fullPaths;
int i;
for(i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
UString arcPath;
if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
{
errorInfo.SystemError = ::GetLastError();
return E_FAIL;
}
fullPaths.Add(arcPath);
}
CCurrentDirRestorer curDirRestorer;
for(i = 0; i < fullPaths.Size(); i++)
{
UString arcPath = fullPaths[i];
UString fileName = ExtractFileNameFromPath(arcPath);
AString path = GetAnsiString(arcPath);
AString name = GetAnsiString(fileName);
// Warning!!! MAPISendDocuments function changes Current directory
fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
}
}
#endif
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -