Setup.ExtractFileFunc.pas 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. unit Setup.ExtractFileFunc;
  2. {
  3. Inno Setup
  4. Copyright (C) 1997-2025 Jordan Russell
  5. Portions by Martijn Laan
  6. For conditions of distribution and use, see LICENSE.TXT.
  7. Installation procedures: ExtractTemporaryFile
  8. }
  9. interface
  10. procedure ExtractTemporaryFile(const BaseName: String);
  11. function ExtractTemporaryFiles(const Pattern: String): Integer;
  12. implementation
  13. uses
  14. Windows, SysUtils,
  15. PathFunc,
  16. Shared.CommonFunc, Shared.FileClass, Shared.Struct,
  17. Setup.RedirFunc, Setup.InstFunc, Setup.FileExtractor, Setup.LoggingFunc, Setup.MainFunc;
  18. procedure InternalExtractTemporaryFile(const DestName: String;
  19. const CurFile: PSetupFileEntry; const CurFileLocation: PSetupFileLocationEntry;
  20. const CreateDirs: Boolean);
  21. var
  22. DestFile: String;
  23. DestF: TFile;
  24. CurFileDate: TFileTime;
  25. begin
  26. DestFile := AddBackslash(TempInstallDir) + DestName;
  27. Log('Extracting temporary file: ' + DestFile);
  28. { Does not disable FS redirection, like everything else working on the temp dir }
  29. if CreateDirs then
  30. ForceDirectories(False, PathExtractPath(DestFile));
  31. DestF := TFile.Create(DestFile, fdCreateAlways, faWrite, fsNone);
  32. try
  33. try
  34. FileExtractor.SeekTo(CurFileLocation^, nil);
  35. FileExtractor.DecompressFile(CurFileLocation^, DestF, nil,
  36. not (foDontVerifyChecksum in CurFile^.Options));
  37. if floTimeStampInUTC in CurFileLocation^.Flags then
  38. CurFileDate := CurFileLocation^.SourceTimeStamp
  39. else
  40. LocalFileTimeToFileTime(CurFileLocation^.SourceTimeStamp, CurFileDate);
  41. SetFileTime(DestF.Handle, nil, nil, @CurFileDate);
  42. finally
  43. DestF.Free;
  44. end;
  45. except
  46. DeleteFile(DestFile);
  47. raise;
  48. end;
  49. AddAttributesToFile(False, DestFile, CurFile^.Attribs);
  50. end;
  51. procedure ExtractTemporaryFile(const BaseName: String);
  52. function EscapeBraces(const S: String): String;
  53. { Changes all '{' to '{{'. Uses ConstLeadBytes^ for the lead byte table. }
  54. var
  55. I: Integer;
  56. begin
  57. Result := S;
  58. I := 1;
  59. while I <= Length(Result) do begin
  60. if Result[I] = '{' then begin
  61. Insert('{', Result, I);
  62. Inc(I);
  63. end;
  64. Inc(I);
  65. end;
  66. end;
  67. var
  68. EscapedBaseName: String;
  69. CurFileNumber: Integer;
  70. CurFile: PSetupFileEntry;
  71. begin
  72. { We compare BaseName to the filename portion of TSetupFileEntry.DestName
  73. which has braces escaped, but BaseName does not; escape it to match }
  74. EscapedBaseName := EscapeBraces(BaseName);
  75. for CurFileNumber := 0 to Entries[seFile].Count-1 do begin
  76. CurFile := PSetupFileEntry(Entries[seFile][CurFileNumber]);
  77. if (CurFile^.LocationEntry <> -1) and (CompareText(PathExtractName(CurFile^.DestName), EscapedBaseName) = 0) then begin
  78. InternalExtractTemporaryFile(BaseName, CurFile, Entries[seFileLocation][CurFile^.LocationEntry], False);
  79. Exit;
  80. end;
  81. end;
  82. InternalErrorFmt('ExtractTemporaryFile: The file "%s" was not found', [BaseName]);
  83. end;
  84. function ExtractTemporaryFiles(const Pattern: String): Integer;
  85. var
  86. LowerPattern, DestName: String;
  87. CurFileNumber: Integer;
  88. CurFile: PSetupFileEntry;
  89. begin
  90. if Length(Pattern) >= MAX_PATH then
  91. InternalError('ExtractTemporaryFiles: Pattern too long');
  92. LowerPattern := PathLowercase(Pattern);
  93. Result := 0;
  94. for CurFileNumber := 0 to Entries[seFile].Count-1 do begin
  95. CurFile := PSetupFileEntry(Entries[seFile][CurFileNumber]);
  96. if CurFile^.LocationEntry <> -1 then begin
  97. { Use ExpandConstEx2 to unescape any braces not in an embedded constant,
  98. while leaving constants unexpanded }
  99. DestName := ExpandConstEx2(CurFile^.DestName, [''], False);
  100. if WildcardMatch(PChar(PathLowercase(DestName)), PChar(LowerPattern)) then begin
  101. Delete(DestName, 1, PathDrivePartLengthEx(DestName, True)); { Remove any drive part }
  102. if Pos('{tmp}\', DestName) = 1 then
  103. Delete(DestName, 1, Length('{tmp}\'));
  104. if Pos(':', DestName) <> 0 then
  105. InternalError('ExtractTemporaryFiles: Invalid character in matched file name');
  106. InternalExtractTemporaryFile(DestName, CurFile, Entries[seFileLocation][CurFile^.LocationEntry], True);
  107. Inc(Result);
  108. end;
  109. end;
  110. end;
  111. if Result = 0 then
  112. InternalErrorFmt('ExtractTemporaryFiles: No files matching "%s" found', [Pattern]);
  113. end;
  114. end.