-
Notifications
You must be signed in to change notification settings - Fork 844
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
VCST-1438: Fix 32/64 bit conflict when copying DLL files (#2811)
Co-authored-by: Oleg Zhuk <zhukoo@gmail.com> Co-authored-by: artem-dudarev <ad@virtoway.com>
- Loading branch information
1 parent
a287d2d
commit e7dc6b4
Showing
10 changed files
with
442 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
src/VirtoCommerce.Platform.Core/Modularity/FileCompareResult.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace VirtoCommerce.Platform.Core.Modularity; | ||
|
||
public class FileCompareResult | ||
{ | ||
public bool NewFile { get; set; } | ||
public bool NewDate { get; set; } | ||
|
||
public bool SameVersion { get; set; } | ||
public bool NewVersion { get; set; } | ||
public bool SameOrNewVersion => SameVersion || NewVersion; | ||
|
||
public bool CompatibleArchitecture { get; set; } | ||
public bool SameArchitecture { get; set; } | ||
public bool NewArchitecture { get; set; } | ||
public bool SameOrNewArchitecture => SameArchitecture || NewArchitecture; | ||
} |
8 changes: 8 additions & 0 deletions
8
src/VirtoCommerce.Platform.Core/Modularity/IFileCopyPolicy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using System.Runtime.InteropServices; | ||
|
||
namespace VirtoCommerce.Platform.Core.Modularity; | ||
|
||
public interface IFileCopyPolicy | ||
{ | ||
bool IsCopyRequired(Architecture environment, string sourceFilePath, string targetFilePath, out FileCompareResult result); | ||
} |
13 changes: 13 additions & 0 deletions
13
src/VirtoCommerce.Platform.Core/Modularity/IFileMetadataProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace VirtoCommerce.Platform.Core.Modularity | ||
{ | ||
public interface IFileMetadataProvider | ||
{ | ||
bool Exists(string filePath); | ||
DateTime? GetDate(string filePath); | ||
Version GetVersion(string filePath); | ||
Architecture? GetArchitecture(string filePath); | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
src/VirtoCommerce.Platform.Modules/Local/FileCopyPolicy.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using System.Runtime.InteropServices; | ||
using VirtoCommerce.Platform.Core.Modularity; | ||
|
||
namespace VirtoCommerce.Platform.Modules.Local; | ||
|
||
public class FileCopyPolicy : IFileCopyPolicy | ||
{ | ||
private readonly IFileMetadataProvider _metadataProvider; | ||
|
||
public FileCopyPolicy(IFileMetadataProvider metadataProvider) | ||
{ | ||
_metadataProvider = metadataProvider; | ||
} | ||
|
||
public bool IsCopyRequired(Architecture environment, string sourceFilePath, string targetFilePath, out FileCompareResult result) | ||
{ | ||
result = new FileCompareResult | ||
{ | ||
NewFile = !_metadataProvider.Exists(targetFilePath), | ||
}; | ||
|
||
CompareDates(sourceFilePath, targetFilePath, result); | ||
CompareVersions(sourceFilePath, targetFilePath, result); | ||
CompareArchitecture(sourceFilePath, targetFilePath, environment, result); | ||
|
||
return result.NewFile && result.CompatibleArchitecture || | ||
result.NewVersion && result.SameOrNewArchitecture || | ||
result.NewArchitecture && result.SameOrNewVersion || | ||
result.NewDate && result.SameOrNewArchitecture && result.SameOrNewVersion; | ||
} | ||
|
||
private void CompareDates(string sourceFilePath, string targetFilePath, FileCompareResult result) | ||
{ | ||
var sourceDate = _metadataProvider.GetDate(sourceFilePath); | ||
var targetDate = _metadataProvider.GetDate(targetFilePath); | ||
|
||
result.NewDate = sourceDate > targetDate; | ||
} | ||
|
||
private void CompareVersions(string sourceFilePath, string targetFilePath, FileCompareResult result) | ||
{ | ||
var sourceVersion = _metadataProvider.GetVersion(sourceFilePath); | ||
var targetVersion = _metadataProvider.GetVersion(targetFilePath); | ||
|
||
result.SameVersion = sourceVersion == targetVersion; | ||
result.NewVersion = targetVersion is not null && sourceVersion > targetVersion; | ||
} | ||
|
||
private void CompareArchitecture(string sourceFilePath, string targetFilePath, Architecture environment, FileCompareResult result) | ||
{ | ||
var sourceArchitecture = _metadataProvider.GetArchitecture(sourceFilePath); | ||
var targetArchitecture = _metadataProvider.GetArchitecture(targetFilePath); | ||
|
||
result.CompatibleArchitecture = sourceArchitecture == targetArchitecture || | ||
sourceArchitecture == environment || | ||
sourceArchitecture == Architecture.X86 && environment == Architecture.X64; | ||
|
||
if (result.CompatibleArchitecture) | ||
{ | ||
result.SameArchitecture = sourceArchitecture == targetArchitecture; | ||
result.NewArchitecture = sourceArchitecture == environment && targetArchitecture != environment; | ||
} | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
src/VirtoCommerce.Platform.Modules/Local/FileMetadataProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
using System; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.InteropServices; | ||
using Microsoft.Extensions.Options; | ||
using VirtoCommerce.Platform.Core.Modularity; | ||
|
||
namespace VirtoCommerce.Platform.Modules.Local; | ||
|
||
public class FileMetadataProvider : IFileMetadataProvider | ||
{ | ||
private readonly LocalStorageModuleCatalogOptions _options; | ||
|
||
public FileMetadataProvider(IOptions<LocalStorageModuleCatalogOptions> options) | ||
{ | ||
_options = options.Value; | ||
} | ||
|
||
public bool Exists(string filePath) | ||
{ | ||
return File.Exists(filePath); | ||
} | ||
|
||
public DateTime? GetDate(string filePath) | ||
{ | ||
if (!File.Exists(filePath)) | ||
{ | ||
return null; | ||
} | ||
|
||
var fileInfo = new FileInfo(filePath); | ||
|
||
return fileInfo.LastWriteTimeUtc; | ||
} | ||
|
||
public Version GetVersion(string filePath) | ||
{ | ||
if (!File.Exists(filePath)) | ||
{ | ||
return null; | ||
} | ||
|
||
var fileVersionInfo = FileVersionInfo.GetVersionInfo(filePath); | ||
|
||
return new Version( | ||
fileVersionInfo.FileMajorPart, | ||
fileVersionInfo.FileMinorPart, | ||
fileVersionInfo.FileBuildPart, | ||
fileVersionInfo.FilePrivatePart); | ||
} | ||
|
||
public Architecture? GetArchitecture(string filePath) | ||
{ | ||
if (!_options.AssemblyFileExtensions.Any(x => filePath.EndsWith(x, StringComparison.OrdinalIgnoreCase))) | ||
{ | ||
return null; | ||
} | ||
|
||
const int startPosition = 0x3C; | ||
const int peSignature = 0x00004550; | ||
|
||
var fileInfo = new FileInfo(filePath); | ||
if (!fileInfo.Exists || fileInfo.Length < startPosition + sizeof(uint)) | ||
{ | ||
return null; | ||
} | ||
|
||
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); | ||
using var reader = new BinaryReader(stream); | ||
|
||
stream.Seek(startPosition, SeekOrigin.Begin); | ||
var peOffset = reader.ReadUInt32(); | ||
|
||
if (fileInfo.Length < peOffset + sizeof(uint) + sizeof(ushort)) | ||
{ | ||
return null; | ||
} | ||
|
||
stream.Seek(peOffset, SeekOrigin.Begin); | ||
var peHead = reader.ReadUInt32(); | ||
|
||
if (peHead != peSignature) | ||
{ | ||
return null; | ||
} | ||
|
||
var machineType = reader.ReadUInt16(); | ||
|
||
// https://stackoverflow.com/questions/480696/how-to-find-if-a-native-dll-file-is-compiled-as-x64-or-x86 | ||
return machineType switch | ||
{ | ||
0x8664 => Architecture.X64, | ||
0xAA64 => Architecture.Arm64, | ||
0x1C0 => Architecture.Arm, | ||
0x14C => Architecture.X86, | ||
_ => null | ||
}; | ||
} | ||
} |
Oops, something went wrong.