Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1671)

Side by Side Diff: third_party/lzma/v4_65/files/CPP/7zip/UI/Common/Update.cpp

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Update.cpp
2
3 #include "StdAfx.h"
4
5 #include "Update.h"
6
7 #include "Common/IntToString.h"
8 #include "Common/StringConvert.h"
9
10 #ifdef _WIN32
11 #include "Windows/DLL.h"
12 #endif
13
14 #include "Windows/FileDir.h"
15 #include "Windows/FileFind.h"
16 #include "Windows/FileName.h"
17 #include "Windows/PropVariant.h"
18 #include "Windows/PropVariantConversions.h"
19 #include "Windows/Time.h"
20
21 #include "../../Common/FileStreams.h"
22
23 #include "../../Compress/CopyCoder.h"
24
25 #include "../Common/DirItem.h"
26 #include "../Common/EnumDirItems.h"
27 #include "../Common/OpenArchive.h"
28 #include "../Common/UpdateProduce.h"
29
30 #include "EnumDirItems.h"
31 #include "SetProperties.h"
32 #include "TempFiles.h"
33 #include "UpdateCallback.h"
34
35 static const char *kUpdateIsNotSupoorted =
36 "update operations are not supported for this archive";
37
38 using namespace NWindows;
39 using namespace NCOM;
40 using namespace NFile;
41 using namespace NName;
42
43 static const wchar_t *kTempFolderPrefix = L"7zE";
44
45 using namespace NUpdateArchive;
46
47 static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *ou tStream)
48 {
49 CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
50 return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
51 }
52
53 class COutMultiVolStream:
54 public IOutStream,
55 public CMyUnknownImp
56 {
57 int _streamIndex; // required stream
58 UInt64 _offsetPos; // offset from start of _streamIndex index
59 UInt64 _absPos;
60 UInt64 _length;
61
62 struct CSubStreamInfo
63 {
64 COutFileStream *StreamSpec;
65 CMyComPtr<IOutStream> Stream;
66 UString Name;
67 UInt64 Pos;
68 UInt64 RealSize;
69 };
70 CObjectVector<CSubStreamInfo> Streams;
71 public:
72 // CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
73 CRecordVector<UInt64> Sizes;
74 UString Prefix;
75 CTempFiles *TempFiles;
76
77 void Init()
78 {
79 _streamIndex = 0;
80 _offsetPos = 0;
81 _absPos = 0;
82 _length = 0;
83 }
84
85 HRESULT Close();
86
87 MY_UNKNOWN_IMP1(IOutStream)
88
89 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
90 STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
91 STDMETHOD(SetSize)(Int64 newSize);
92 };
93
94 // static NSynchronization::CCriticalSection g_TempPathsCS;
95
96 HRESULT COutMultiVolStream::Close()
97 {
98 HRESULT res = S_OK;
99 for (int i = 0; i < Streams.Size(); i++)
100 {
101 CSubStreamInfo &s = Streams[i];
102 if (s.StreamSpec)
103 {
104 HRESULT res2 = s.StreamSpec->Close();
105 if (res2 != S_OK)
106 res = res2;
107 }
108 }
109 return res;
110 }
111
112 STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *pr ocessedSize)
113 {
114 if(processedSize != NULL)
115 *processedSize = 0;
116 while(size > 0)
117 {
118 if (_streamIndex >= Streams.Size())
119 {
120 CSubStreamInfo subStream;
121
122 wchar_t temp[32];
123 ConvertUInt64ToString(_streamIndex + 1, temp);
124 UString res = temp;
125 while (res.Length() < 3)
126 res = UString(L'0') + res;
127 UString name = Prefix + res;
128 subStream.StreamSpec = new COutFileStream;
129 subStream.Stream = subStream.StreamSpec;
130 if(!subStream.StreamSpec->Create(name, false))
131 return ::GetLastError();
132 {
133 // NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
134 TempFiles->Paths.Add(name);
135 }
136
137 subStream.Pos = 0;
138 subStream.RealSize = 0;
139 subStream.Name = name;
140 Streams.Add(subStream);
141 continue;
142 }
143 CSubStreamInfo &subStream = Streams[_streamIndex];
144
145 int index = _streamIndex;
146 if (index >= Sizes.Size())
147 index = Sizes.Size() - 1;
148 UInt64 volSize = Sizes[index];
149
150 if (_offsetPos >= volSize)
151 {
152 _offsetPos -= volSize;
153 _streamIndex++;
154 continue;
155 }
156 if (_offsetPos != subStream.Pos)
157 {
158 // CMyComPtr<IOutStream> outStream;
159 // RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
160 RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
161 subStream.Pos = _offsetPos;
162 }
163
164 UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
165 UInt32 realProcessed;
166 RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
167 data = (void *)((Byte *)data + realProcessed);
168 size -= realProcessed;
169 subStream.Pos += realProcessed;
170 _offsetPos += realProcessed;
171 _absPos += realProcessed;
172 if (_absPos > _length)
173 _length = _absPos;
174 if (_offsetPos > subStream.RealSize)
175 subStream.RealSize = _offsetPos;
176 if(processedSize != NULL)
177 *processedSize += realProcessed;
178 if (subStream.Pos == volSize)
179 {
180 _streamIndex++;
181 _offsetPos = 0;
182 }
183 if (realProcessed == 0 && curSize != 0)
184 return E_FAIL;
185 break;
186 }
187 return S_OK;
188 }
189
190 STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *n ewPosition)
191 {
192 if(seekOrigin >= 3)
193 return STG_E_INVALIDFUNCTION;
194 switch(seekOrigin)
195 {
196 case STREAM_SEEK_SET:
197 _absPos = offset;
198 break;
199 case STREAM_SEEK_CUR:
200 _absPos += offset;
201 break;
202 case STREAM_SEEK_END:
203 _absPos = _length + offset;
204 break;
205 }
206 _offsetPos = _absPos;
207 if (newPosition != NULL)
208 *newPosition = _absPos;
209 _streamIndex = 0;
210 return S_OK;
211 }
212
213 STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize)
214 {
215 if (newSize < 0)
216 return E_INVALIDARG;
217 int i = 0;
218 while (i < Streams.Size())
219 {
220 CSubStreamInfo &subStream = Streams[i++];
221 if ((UInt64)newSize < subStream.RealSize)
222 {
223 RINOK(subStream.Stream->SetSize(newSize));
224 subStream.RealSize = newSize;
225 break;
226 }
227 newSize -= subStream.RealSize;
228 }
229 while (i < Streams.Size())
230 {
231 {
232 CSubStreamInfo &subStream = Streams.Back();
233 subStream.Stream.Release();
234 NDirectory::DeleteFileAlways(subStream.Name);
235 }
236 Streams.DeleteBack();
237 }
238 _offsetPos = _absPos;
239 _streamIndex = 0;
240 _length = newSize;
241 return S_OK;
242 }
243
244 static const wchar_t *kDefaultArchiveType = L"7z";
245 static const wchar_t *kSFXExtension =
246 #ifdef _WIN32
247 L"exe";
248 #else
249 L"";
250 #endif
251
252 bool CUpdateOptions::Init(const CCodecs *codecs, const CIntVector &formatIndices , const UString &arcPath)
253 {
254 if (formatIndices.Size() > 1)
255 return false;
256 int arcTypeIndex = -1;
257 if (formatIndices.Size() != 0)
258 arcTypeIndex = formatIndices[0];
259 if (arcTypeIndex >= 0)
260 MethodMode.FormatIndex = arcTypeIndex;
261 else
262 {
263 MethodMode.FormatIndex = codecs->FindFormatForArchiveName(arcPath);
264 if (MethodMode.FormatIndex < 0)
265 MethodMode.FormatIndex = codecs->FindFormatForArchiveType(kDefaultArchiveT ype);
266 }
267 if (MethodMode.FormatIndex < 0)
268 return false;
269 const CArcInfoEx &arcInfo = codecs->Formats[MethodMode.FormatIndex];
270 if (!arcInfo.UpdateEnabled)
271 return false;
272 UString typeExt = arcInfo.GetMainExt();
273 UString ext = typeExt;
274 if (SfxMode)
275 ext = kSFXExtension;
276 ArchivePath.BaseExtension = ext;
277 ArchivePath.VolExtension = typeExt;
278 ArchivePath.ParseFromPath(arcPath);
279 for (int i = 0; i < Commands.Size(); i++)
280 {
281 CUpdateArchiveCommand &uc = Commands[i];
282 uc.ArchivePath.BaseExtension = ext;
283 uc.ArchivePath.VolExtension = typeExt;
284 uc.ArchivePath.ParseFromPath(uc.UserArchivePath);
285 }
286 return true;
287 }
288
289 /*
290 struct CUpdateProduceCallbackImp: public IUpdateProduceCallback
291 {
292 const CObjectVector<CArcItem> *_arcItems;
293 IUpdateCallbackUI *_callback;
294
295 CUpdateProduceCallbackImp(const CObjectVector<CArcItem> *a,
296 IUpdateCallbackUI *callback): _arcItems(a), _callback(callback) {}
297 virtual HRESULT ShowDeleteFile(int arcIndex);
298 };
299
300 HRESULT CUpdateProduceCallbackImp::ShowDeleteFile(int arcIndex)
301 {
302 return _callback->ShowDeleteFile((*_arcItems)[arcIndex].Name);
303 }
304 */
305
306 static HRESULT Compress(
307 CCodecs *codecs,
308 const CActionSet &actionSet,
309 IInArchive *archive,
310 const CCompressionMethodMode &compressionMethod,
311 CArchivePath &archivePath,
312 const CObjectVector<CArcItem> &arcItems,
313 bool shareForWrite,
314 bool stdInMode,
315 /* const UString & stdInFileName, */
316 bool stdOutMode,
317 const CDirItems &dirItems,
318 bool sfxMode,
319 const UString &sfxModule,
320 const CRecordVector<UInt64> &volumesSizes,
321 CTempFiles &tempFiles,
322 CUpdateErrorInfo &errorInfo,
323 IUpdateCallbackUI *callback)
324 {
325 CMyComPtr<IOutArchive> outArchive;
326 if(archive != NULL)
327 {
328 CMyComPtr<IInArchive> archive2 = archive;
329 HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
330 if(result != S_OK)
331 throw kUpdateIsNotSupoorted;
332 }
333 else
334 {
335 RINOK(codecs->CreateOutArchive(compressionMethod.FormatIndex, outArchive));
336
337 #ifdef EXTERNAL_CODECS
338 {
339 CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
340 outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompres sCodecsInfo);
341 if (setCompressCodecsInfo)
342 {
343 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs));
344 }
345 }
346 #endif
347 }
348 if (outArchive == 0)
349 throw kUpdateIsNotSupoorted;
350
351 NFileTimeType::EEnum fileTimeType;
352 UInt32 value;
353 RINOK(outArchive->GetFileTimeType(&value));
354
355 switch(value)
356 {
357 case NFileTimeType::kWindows:
358 case NFileTimeType::kUnix:
359 case NFileTimeType::kDOS:
360 fileTimeType = (NFileTimeType::EEnum)value;
361 break;
362 default:
363 return E_FAIL;
364 }
365
366 CRecordVector<CUpdatePair2> updatePairs2;
367
368 {
369 CRecordVector<CUpdatePair> updatePairs;
370 GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs); // mus t be done only once!!!
371 // CUpdateProduceCallbackImp upCallback(&arcItems, callback);
372 UpdateProduce(updatePairs, actionSet, updatePairs2, NULL /* &upCallback */);
373 }
374
375 UInt32 numFiles = 0;
376 for (int i = 0; i < updatePairs2.Size(); i++)
377 if (updatePairs2[i].NewData)
378 numFiles++;
379
380 RINOK(callback->SetNumFiles(numFiles));
381
382
383 CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
384 CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
385
386 updateCallbackSpec->ShareForWrite = shareForWrite;
387 updateCallbackSpec->StdInMode = stdInMode;
388 updateCallbackSpec->Callback = callback;
389 updateCallbackSpec->DirItems = &dirItems;
390 updateCallbackSpec->ArcItems = &arcItems;
391 updateCallbackSpec->UpdatePairs = &updatePairs2;
392
393 CMyComPtr<ISequentialOutStream> outStream;
394
395 const UString &archiveName = archivePath.GetFinalPath();
396 if (!stdOutMode)
397 {
398 UString resultPath;
399 int pos;
400 if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
401 throw 1417161;
402 NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
403 }
404
405 COutFileStream *outStreamSpec = NULL;
406 COutMultiVolStream *volStreamSpec = NULL;
407
408 if (volumesSizes.Size() == 0)
409 {
410 if (stdOutMode)
411 outStream = new CStdOutFileStream;
412 else
413 {
414 outStreamSpec = new COutFileStream;
415 outStream = outStreamSpec;
416 bool isOK = false;
417 UString realPath;
418 for (int i = 0; i < (1 << 16); i++)
419 {
420 if (archivePath.Temp)
421 {
422 if (i > 0)
423 {
424 wchar_t s[32];
425 ConvertUInt64ToString(i, s);
426 archivePath.TempPostfix = s;
427 }
428 realPath = archivePath.GetTempPath();
429 }
430 else
431 realPath = archivePath.GetFinalPath();
432 if (outStreamSpec->Create(realPath, false))
433 {
434 tempFiles.Paths.Add(realPath);
435 isOK = true;
436 break;
437 }
438 if (::GetLastError() != ERROR_FILE_EXISTS)
439 break;
440 if (!archivePath.Temp)
441 break;
442 }
443 if (!isOK)
444 {
445 errorInfo.SystemError = ::GetLastError();
446 errorInfo.FileName = realPath;
447 errorInfo.Message = L"Can not open file";
448 return E_FAIL;
449 }
450 }
451 }
452 else
453 {
454 if (stdOutMode)
455 return E_FAIL;
456 volStreamSpec = new COutMultiVolStream;
457 outStream = volStreamSpec;
458 volStreamSpec->Sizes = volumesSizes;
459 volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
460 volStreamSpec->TempFiles = &tempFiles;
461 volStreamSpec->Init();
462
463 /*
464 updateCallbackSpec->VolumesSizes = volumesSizes;
465 updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
466 if (!archivePath.VolExtension.IsEmpty())
467 updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
468 */
469 }
470
471 RINOK(SetProperties(outArchive, compressionMethod.Properties));
472
473 if (sfxMode)
474 {
475 CInFileStream *sfxStreamSpec = new CInFileStream;
476 CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
477 if (!sfxStreamSpec->Open(sfxModule))
478 {
479 errorInfo.SystemError = ::GetLastError();
480 errorInfo.Message = L"Can't open sfx module";
481 errorInfo.FileName = sfxModule;
482 return E_FAIL;
483 }
484
485 CMyComPtr<ISequentialOutStream> sfxOutStream;
486 COutFileStream *outStreamSpec = NULL;
487 if (volumesSizes.Size() == 0)
488 sfxOutStream = outStream;
489 else
490 {
491 outStreamSpec = new COutFileStream;
492 sfxOutStream = outStreamSpec;
493 UString realPath = archivePath.GetFinalPath();
494 if (!outStreamSpec->Create(realPath, false))
495 {
496 errorInfo.SystemError = ::GetLastError();
497 errorInfo.FileName = realPath;
498 errorInfo.Message = L"Can not open file";
499 return E_FAIL;
500 }
501 }
502 RINOK(CopyBlock(sfxStream, sfxOutStream));
503 if (outStreamSpec)
504 {
505 RINOK(outStreamSpec->Close());
506 }
507 }
508
509 HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(), updat eCallback);
510 callback->Finilize();
511 RINOK(result);
512 if (outStreamSpec)
513 result = outStreamSpec->Close();
514 else if (volStreamSpec)
515 result = volStreamSpec->Close();
516 return result;
517 }
518
519 HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
520 IInArchive *archive,
521 const UString &defaultItemName,
522 const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
523 CObjectVector<CArcItem> &arcItems)
524 {
525 arcItems.Clear();
526 UInt32 numItems;
527 RINOK(archive->GetNumberOfItems(&numItems));
528 arcItems.Reserve(numItems);
529 for (UInt32 i = 0; i < numItems; i++)
530 {
531 CArcItem ai;
532
533 RINOK(GetArchiveItemPath(archive, i, ai.Name));
534 // check it: defaultItemName !!!
535 if (ai.Name.IsEmpty())
536 ai.Name = defaultItemName;
537 RINOK(IsArchiveItemFolder(archive, i, ai.IsDir));
538 ai.Censored = censor.CheckPath(ai.Name, !ai.IsDir);
539 RINOK(GetArchiveItemFileTime(archive, i, archiveFileInfo.MTime, ai.MTime));
540
541 {
542 CPropVariant prop;
543 RINOK(archive->GetProperty(i, kpidSize, &prop));
544 ai.SizeDefined = (prop.vt != VT_EMPTY);
545 if (ai.SizeDefined)
546 ai.Size = ConvertPropVariantToUInt64(prop);
547 }
548
549 {
550 CPropVariant prop;
551 RINOK(archive->GetProperty(i, kpidTimeType, &prop));
552 if (prop.vt == VT_UI4)
553 {
554 ai.TimeType = (int)(NFileTimeType::EEnum)prop.ulVal;
555 switch(ai.TimeType)
556 {
557 case NFileTimeType::kWindows:
558 case NFileTimeType::kUnix:
559 case NFileTimeType::kDOS:
560 break;
561 default:
562 return E_FAIL;
563 }
564 }
565 }
566
567 ai.IndexInServer = i;
568 arcItems.Add(ai);
569 }
570 return S_OK;
571 }
572
573
574 static HRESULT UpdateWithItemLists(
575 CCodecs *codecs,
576 CUpdateOptions &options,
577 IInArchive *archive,
578 const CObjectVector<CArcItem> &arcItems,
579 CDirItems &dirItems,
580 CTempFiles &tempFiles,
581 CUpdateErrorInfo &errorInfo,
582 IUpdateCallbackUI2 *callback)
583 {
584 for(int i = 0; i < options.Commands.Size(); i++)
585 {
586 CUpdateArchiveCommand &command = options.Commands[i];
587 if (options.StdOutMode)
588 {
589 RINOK(callback->StartArchive(0, archive != 0));
590 }
591 else
592 {
593 RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
594 i == 0 && options.UpdateArchiveItself && archive != 0));
595 }
596
597 RINOK(Compress(
598 codecs,
599 command.ActionSet, archive,
600 options.MethodMode,
601 command.ArchivePath,
602 arcItems,
603 options.OpenShareForWrite,
604 options.StdInMode,
605 /* options.StdInFileName, */
606 options.StdOutMode,
607 dirItems,
608 options.SfxMode, options.SfxModule,
609 options.VolumesSizes,
610 tempFiles,
611 errorInfo, callback));
612
613 RINOK(callback->FinishArchive());
614 }
615 return S_OK;
616 }
617
618 #ifdef _WIN32
619 class CCurrentDirRestorer
620 {
621 UString m_CurrentDirectory;
622 public:
623 CCurrentDirRestorer()
624 { NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
625 ~CCurrentDirRestorer()
626 { RestoreDirectory();}
627 bool RestoreDirectory()
628 { return BOOLToBool(NFile::NDirectory::MySetCurrentDirectory(m_CurrentDirect ory)); }
629 };
630 #endif
631
632 struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
633 {
634 IUpdateCallbackUI2 *Callback;
635 HRESULT ScanProgress(UInt64 numFolders, UInt64 numFiles, const wchar_t *path)
636 {
637 return Callback->ScanProgress(numFolders, numFiles, path);
638 }
639 };
640
641 #ifdef _WIN32
642 typedef ULONG (FAR PASCAL MY_MAPISENDDOCUMENTS)(
643 ULONG_PTR ulUIParam,
644 LPSTR lpszDelimChar,
645 LPSTR lpszFilePaths,
646 LPSTR lpszFileNames,
647 ULONG ulReserved
648 );
649 typedef MY_MAPISENDDOCUMENTS FAR *MY_LPMAPISENDDOCUMENTS;
650 #endif
651
652 HRESULT UpdateArchive(
653 CCodecs *codecs,
654 const NWildcard::CCensor &censor,
655 CUpdateOptions &options,
656 CUpdateErrorInfo &errorInfo,
657 IOpenCallbackUI *openCallback,
658 IUpdateCallbackUI2 *callback)
659 {
660 if (options.StdOutMode && options.EMailMode)
661 return E_FAIL;
662
663 if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
664 return E_NOTIMPL;
665
666 if (options.SfxMode)
667 {
668 CProperty property;
669 property.Name = L"rsfx";
670 property.Value = L"on";
671 options.MethodMode.Properties.Add(property);
672 if (options.SfxModule.IsEmpty())
673 {
674 errorInfo.Message = L"sfx file is not specified";
675 return E_FAIL;
676 }
677 UString name = options.SfxModule;
678 if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
679 {
680 errorInfo.Message = L"can't find specified sfx module";
681 return E_FAIL;
682 }
683 }
684
685 const UString archiveName = options.ArchivePath.GetFinalPath();
686
687 UString defaultItemName;
688 NFind::CFileInfoW archiveFileInfo;
689
690 CArchiveLink archiveLink;
691 IInArchive *archive = 0;
692 if (NFind::FindFile(archiveName, archiveFileInfo))
693 {
694 if (archiveFileInfo.IsDir())
695 throw "there is no such archive";
696 if (options.VolumesSizes.Size() > 0)
697 return E_NOTIMPL;
698 CIntVector formatIndices;
699 if (options.MethodMode.FormatIndex >= 0)
700 formatIndices.Add(options.MethodMode.FormatIndex);
701 HRESULT result = MyOpenArchive(codecs, formatIndices, archiveName, archiveLi nk, openCallback);
702 if (result == E_ABORT)
703 return result;
704 RINOK(callback->OpenResult(archiveName, result));
705 RINOK(result);
706 if (archiveLink.VolumePaths.Size() > 1)
707 {
708 errorInfo.SystemError = (DWORD)E_NOTIMPL;
709 errorInfo.Message = L"Updating for multivolume archives is not implemented ";
710 return E_NOTIMPL;
711 }
712 archive = archiveLink.GetArchive();
713 defaultItemName = archiveLink.GetDefaultItemName();
714 }
715 else
716 {
717 /*
718 if (archiveType.IsEmpty())
719 throw "type of archive is not specified";
720 */
721 }
722
723 CDirItems dirItems;
724 if (options.StdInMode)
725 {
726 CDirItem di;
727 di.Name = options.StdInFileName;
728 di.Size = (UInt64)(Int64)-1;
729 di.Attrib = 0;
730 NTime::GetCurUtcFileTime(di.MTime);
731 di.CTime = di.ATime = di.MTime;
732 dirItems.Items.Add(di);
733 }
734 else
735 {
736 bool needScanning = false;
737 for(int i = 0; i < options.Commands.Size(); i++)
738 if (options.Commands[i].ActionSet.NeedScanning())
739 needScanning = true;
740 if (needScanning)
741 {
742 CEnumDirItemUpdateCallback enumCallback;
743 enumCallback.Callback = callback;
744 RINOK(callback->StartScanning());
745 UStringVector errorPaths;
746 CRecordVector<DWORD> errorCodes;
747 HRESULT res = EnumerateItems(censor, dirItems, &enumCallback, errorPaths, errorCodes);
748 for (int i = 0; i < errorPaths.Size(); i++)
749 {
750 RINOK(callback->CanNotFindError(errorPaths[i], errorCodes[i]));
751 }
752 if (res != S_OK)
753 {
754 if (res != E_ABORT)
755 errorInfo.Message = L"Scanning error";
756 // errorInfo.FileName = errorPath;
757 return res;
758 }
759 RINOK(callback->FinishScanning());
760 }
761 }
762
763 UString tempDirPrefix;
764 bool usesTempDir = false;
765
766 #ifdef _WIN32
767 NDirectory::CTempDirectoryW tempDirectory;
768 if (options.EMailMode && options.EMailRemoveAfter)
769 {
770 tempDirectory.Create(kTempFolderPrefix);
771 tempDirPrefix = tempDirectory.GetPath();
772 NormalizeDirPathPrefix(tempDirPrefix);
773 usesTempDir = true;
774 }
775 #endif
776
777 CTempFiles tempFiles;
778
779 bool createTempFile = false;
780 if(!options.StdOutMode && options.UpdateArchiveItself)
781 {
782 CArchivePath &ap = options.Commands[0].ArchivePath;
783 ap = options.ArchivePath;
784 // if ((archive != 0 && !usesTempDir) || !options.WorkingDir.IsEmpty())
785 if ((archive != 0 || !options.WorkingDir.IsEmpty()) && !usesTempDir && optio ns.VolumesSizes.Size() == 0)
786 {
787 createTempFile = true;
788 ap.Temp = true;
789 if (!options.WorkingDir.IsEmpty())
790 {
791 ap.TempPrefix = options.WorkingDir;
792 NormalizeDirPathPrefix(ap.TempPrefix);
793 }
794 }
795 }
796
797 for(int i = 0; i < options.Commands.Size(); i++)
798 {
799 CArchivePath &ap = options.Commands[i].ArchivePath;
800 if (usesTempDir)
801 {
802 // Check it
803 ap.Prefix = tempDirPrefix;
804 // ap.Temp = true;
805 // ap.TempPrefix = tempDirPrefix;
806 }
807 if (i > 0 || !createTempFile)
808 {
809 const UString &path = ap.GetFinalPath();
810 if (NFind::DoesFileExist(path))
811 {
812 errorInfo.SystemError = 0;
813 errorInfo.Message = L"File already exists";
814 errorInfo.FileName = path;
815 return E_FAIL;
816 }
817 }
818 }
819
820 CObjectVector<CArcItem> arcItems;
821 if (archive != NULL)
822 {
823 RINOK(EnumerateInArchiveItems(censor,
824 archive, defaultItemName, archiveFileInfo, arcItems));
825 }
826
827 RINOK(UpdateWithItemLists(codecs, options, archive, arcItems, dirItems,
828 tempFiles, errorInfo, callback));
829
830 if (archive != NULL)
831 {
832 RINOK(archiveLink.Close());
833 archiveLink.Release();
834 }
835
836 tempFiles.Paths.Clear();
837 if(createTempFile)
838 {
839 try
840 {
841 CArchivePath &ap = options.Commands[0].ArchivePath;
842 const UString &tempPath = ap.GetTempPath();
843 if (archive != NULL)
844 if (!NDirectory::DeleteFileAlways(archiveName))
845 {
846 errorInfo.SystemError = ::GetLastError();
847 errorInfo.Message = L"delete file error";
848 errorInfo.FileName = archiveName;
849 return E_FAIL;
850 }
851 if (!NDirectory::MyMoveFile(tempPath, archiveName))
852 {
853 errorInfo.SystemError = ::GetLastError();
854 errorInfo.Message = L"move file error";
855 errorInfo.FileName = tempPath;
856 errorInfo.FileName2 = archiveName;
857 return E_FAIL;
858 }
859 }
860 catch(...)
861 {
862 throw;
863 }
864 }
865
866 #ifdef _WIN32
867 if (options.EMailMode)
868 {
869 NDLL::CLibrary mapiLib;
870 if (!mapiLib.Load(TEXT("Mapi32.dll")))
871 {
872 errorInfo.SystemError = ::GetLastError();
873 errorInfo.Message = L"can not load Mapi32.dll";
874 return E_FAIL;
875 }
876 MY_LPMAPISENDDOCUMENTS fnSend = (MY_LPMAPISENDDOCUMENTS)
877 mapiLib.GetProcAddress("MAPISendDocuments");
878 if (fnSend == 0)
879 {
880 errorInfo.SystemError = ::GetLastError();
881 errorInfo.Message = L"can not find MAPISendDocuments function";
882 return E_FAIL;
883 }
884 UStringVector fullPaths;
885 int i;
886 for(i = 0; i < options.Commands.Size(); i++)
887 {
888 CArchivePath &ap = options.Commands[i].ArchivePath;
889 UString arcPath;
890 if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
891 {
892 errorInfo.SystemError = ::GetLastError();
893 return E_FAIL;
894 }
895 fullPaths.Add(arcPath);
896 }
897 CCurrentDirRestorer curDirRestorer;
898 for(i = 0; i < fullPaths.Size(); i++)
899 {
900 UString arcPath = fullPaths[i];
901 UString fileName = ExtractFileNameFromPath(arcPath);
902 AString path = GetAnsiString(arcPath);
903 AString name = GetAnsiString(fileName);
904 // Warning!!! MAPISendDocuments function changes Current directory
905 fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
906 }
907 }
908 #endif
909 return S_OK;
910 }
911
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698