diff --git a/src/Framework/NativeMethods.cs b/src/Framework/NativeMethods.cs index 68fd42df662..43b8c91651d 100644 --- a/src/Framework/NativeMethods.cs +++ b/src/Framework/NativeMethods.cs @@ -1152,7 +1152,7 @@ internal static bool MakeSymbolicLink(string newFileName, string exitingFileName else { symbolicLinkCreated = symlink(exitingFileName, newFileName) == 0; - errorMessage = symbolicLinkCreated ? null : "The link() library call failed with the following error code: " + Marshal.GetLastWin32Error(); + errorMessage = symbolicLinkCreated ? null : Marshal.GetLastWin32Error().ToString(); } return symbolicLinkCreated; diff --git a/src/Tasks.UnitTests/Copy_Tests.cs b/src/Tasks.UnitTests/Copy_Tests.cs index c5e6153dcf7..4477c7e5432 100644 --- a/src/Tasks.UnitTests/Copy_Tests.cs +++ b/src/Tasks.UnitTests/Copy_Tests.cs @@ -2313,15 +2313,6 @@ public void CopyToDestinationFolderWithHardLinkFallbackTooManyLinks() Directory.CreateDirectory(destFolder); - // Exhaust the number (1024) of directory entries that can be created for a file - // This is 1 + (1 x hard links) - // We need to test the fallback code path when we're out of directory entries for a file.. - for (int n = 0; n < 1025 /* make sure */; n++) - { - string destLink = Path.Combine(destFolder, Path.GetFileNameWithoutExtension(sourceFile) + "." + n); - string linkError = String.Empty; - Tasks.NativeMethods.MakeHardLink(destLink, sourceFile, ref linkError); - } ITaskItem[] sourceFiles = { new TaskItem(sourceFile) }; @@ -2336,6 +2327,16 @@ public void CopyToDestinationFolderWithHardLinkFallbackTooManyLinks() SkipUnchangedFiles = true }; + // Exhaust the number (1024) of directory entries that can be created for a file + // This is 1 + (1 x hard links) + // We need to test the fallback code path when we're out of directory entries for a file.. + for (int n = 0; n < 1025 /* make sure */; n++) + { + string destLink = Path.Combine(destFolder, Path.GetFileNameWithoutExtension(sourceFile) + "." + n); + string linkError = String.Empty; + Tasks.NativeMethods.MakeHardLink(destLink, sourceFile, ref linkError, t.Log); + } + bool success = t.Execute(); Assert.True(success); // "success" diff --git a/src/Tasks/Copy.cs b/src/Tasks/Copy.cs index 48e28ca03dc..dab3ddb553a 100644 --- a/src/Tasks/Copy.cs +++ b/src/Tasks/Copy.cs @@ -283,10 +283,10 @@ FileState destinationFileState // The destination file // Create hard links if UseHardlinksIfPossible is true if (UseHardlinksIfPossible) { - TryCopyViaLink(HardLinkComment, MessageImportance.Normal, sourceFileState, destinationFileState, ref destinationFileExists, out hardLinkCreated, ref errorMessage, (source, destination, errMessage) => NativeMethods.MakeHardLink(destination, source, ref errorMessage)); - if(!hardLinkCreated) + TryCopyViaLink(HardLinkComment, MessageImportance.Normal, sourceFileState, destinationFileState, ref destinationFileExists, out hardLinkCreated, ref errorMessage, (source, destination, errMessage) => NativeMethods.MakeHardLink(destination, source, ref errorMessage, Log)); + if (!hardLinkCreated) { - if(UseSymboliclinksIfPossible) + if (UseSymboliclinksIfPossible) { // This is a message for fallback to SymbolicLinks if HardLinks fail when UseHardlinksIfPossible and UseSymboliclinksIfPossible are true Log.LogMessage(MessageImportance.Normal, RetryingAsSymbolicLink, sourceFileState.Name, destinationFileState.Name, errorMessage); @@ -302,7 +302,11 @@ FileState destinationFileState // The destination file if (!hardLinkCreated && UseSymboliclinksIfPossible) { TryCopyViaLink(SymbolicLinkComment, MessageImportance.Normal, sourceFileState, destinationFileState, ref destinationFileExists, out symbolicLinkCreated, ref errorMessage, (source, destination, errMessage) => NativeMethodsShared.MakeSymbolicLink(destination, source, ref errorMessage)); - if(!symbolicLinkCreated) + if (!NativeMethodsShared.IsWindows) + { + errorMessage = Log.FormatResourceString("Copy.NonWindowsLinkErrorMessage", "symlink()", errorMessage); + } + if (!symbolicLinkCreated) { Log.LogMessage(MessageImportance.Normal, RetryingAsFileCopy, sourceFileState.Name, destinationFileState.Name, errorMessage); } diff --git a/src/Tasks/NativeMethods.cs b/src/Tasks/NativeMethods.cs index b7f212ebe43..a100afbb4e7 100644 --- a/src/Tasks/NativeMethods.cs +++ b/src/Tasks/NativeMethods.cs @@ -18,6 +18,7 @@ #endif using System.Text.RegularExpressions; using System.Runtime.Versioning; +using Microsoft.Build.Utilities; #nullable disable @@ -96,7 +97,7 @@ internal interface IMetaDataDispenser object DefineScope([In] ref Guid rclsid, [In] UInt32 dwCreateFlags, [In] ref Guid riid); [return: MarshalAs(UnmanagedType.Interface)] - object OpenScope([In][MarshalAs(UnmanagedType.LPWStr)] string szScope, [In] UInt32 dwOpenFlags, [In] ref Guid riid); + object OpenScope([In][MarshalAs(UnmanagedType.LPWStr)] string szScope, [In] UInt32 dwOpenFlags, [In] ref Guid riid); [return: MarshalAs(UnmanagedType.Interface)] object OpenScopeOnMemory([In] IntPtr pData, [In] UInt32 cbData, [In] UInt32 dwOpenFlags, [In] ref Guid riid); @@ -521,7 +522,7 @@ internal struct PROCESS_INFORMATION /// internal static class NativeMethods { -#region Constants + #region Constants internal static readonly IntPtr NullPtr = IntPtr.Zero; internal static readonly IntPtr InvalidIntPtr = new IntPtr(-1); @@ -626,9 +627,9 @@ internal enum MoveFileFlags MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020 } -#endregion + #endregion -#region NT header stuff + #region NT header stuff internal const uint IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b; internal const uint IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b; @@ -779,9 +780,9 @@ internal struct CRYPTOAPI_BLOB internal IntPtr pbData; } -#endregion + #endregion -#region PInvoke + #region PInvoke private const string Crypt32DLL = "crypt32.dll"; private const string Advapi32DLL = "advapi32.dll"; #if !RUNTIME_TYPE_NETCORE @@ -797,7 +798,7 @@ internal struct CRYPTOAPI_BLOB [DllImport("libc", SetLastError = true)] internal static extern int link(string oldpath, string newpath); - internal static bool MakeHardLink(string newFileName, string exitingFileName, ref string errorMessage) + internal static bool MakeHardLink(string newFileName, string exitingFileName, ref string errorMessage, TaskLoggingHelper log) { bool hardLinkCreated; if (NativeMethodsShared.IsWindows) @@ -808,7 +809,7 @@ internal static bool MakeHardLink(string newFileName, string exitingFileName, re else { hardLinkCreated = link(exitingFileName, newFileName) == 0; - errorMessage = hardLinkCreated ? null : "The link() library call failed with the following error code: " + Marshal.GetLastWin32Error(); + errorMessage = hardLinkCreated ? null : log.FormatResourceString("Copy.LinklibraryFailedPrefix", "link()", Marshal.GetLastWin32Error()); } return hardLinkCreated; @@ -1048,13 +1049,13 @@ internal static extern int CreateAssemblyNameObject( //------------------------------------------------------------------------------ [DllImport(Crypt32DLL, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool CertCloseStore([In] IntPtr CertStore, CertStoreClose Flags); + internal static extern bool CertCloseStore([In] IntPtr CertStore, CertStoreClose Flags); //------------------------------------------------------------------------------ // CertEnumCertificatesInStore //------------------------------------------------------------------------------ [DllImport(Crypt32DLL, SetLastError = true)] - internal static extern IntPtr CertEnumCertificatesInStore([In] IntPtr CertStore, [In] IntPtr PrevCertContext); + internal static extern IntPtr CertEnumCertificatesInStore([In] IntPtr CertStore, [In] IntPtr PrevCertContext); //------------------------------------------------------------------------------ // CryptAcquireCertificatePrivateKey @@ -1110,9 +1111,9 @@ internal static extern int CreateAssemblyNameObject( [DllImport(MscoreeDLL, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern unsafe uint GetFileVersion([MarshalAs(UnmanagedType.LPWStr)] string szFileName, [Out] char* szBuffer, int cchBuffer, out int dwLength); #endif -#endregion + #endregion -#region Methods + #region Methods #if FEATURE_HANDLEPROCESSCORRUPTEDSTATEEXCEPTIONS /// /// Given a pointer to a metadata blob, read the string parameter from it. Returns true if @@ -1233,8 +1234,8 @@ internal static unsafe int CorSigUncompressData(IntPtr data, out int uncompresse return count; } -#endregion -#region InternalClass + #endregion + #region InternalClass /// /// This class is a wrapper over the native GAC enumeration API. /// @@ -1472,6 +1473,6 @@ public static string AssemblyPathFromStrongName(string strongName) return null; } } -#endregion + #endregion } } diff --git a/src/Tasks/Resources/Strings.resx b/src/Tasks/Resources/Strings.resx index d824b1f8d91..b5be0e8c979 100644 --- a/src/Tasks/Resources/Strings.resx +++ b/src/Tasks/Resources/Strings.resx @@ -221,6 +221,9 @@ If this bucket overflows, pls. contact 'vsppbdev'. --> + + The {0} library call failed with the following error code: {1}. + Creating directory "{0}". diff --git a/src/Tasks/Resources/xlf/Strings.cs.xlf b/src/Tasks/Resources/xlf/Strings.cs.xlf index 37e133a2806..6016ad0d72a 100644 --- a/src/Tasks/Resources/xlf/Strings.cs.xlf +++ b/src/Tasks/Resources/xlf/Strings.cs.xlf @@ -186,6 +186,11 @@ MSB3893: Nedá se použít odkaz pro kopírování {0} do {1}. {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Nedá se použít odkaz pro kopírování {0} do {1}. Místo toho se kopíruje soubor. {2} diff --git a/src/Tasks/Resources/xlf/Strings.de.xlf b/src/Tasks/Resources/xlf/Strings.de.xlf index 4c37c0de5e9..31b05a8bf07 100644 --- a/src/Tasks/Resources/xlf/Strings.de.xlf +++ b/src/Tasks/Resources/xlf/Strings.de.xlf @@ -186,6 +186,11 @@ MSB3893: Es konnte kein Link verwendet werden, um "{0}" in "{1}" zu kopieren. {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Es konnte kein Link verwendet werden, um "{0}" in "{1}" zu kopieren. Stattdessen wird die Datei kopiert. {2} diff --git a/src/Tasks/Resources/xlf/Strings.es.xlf b/src/Tasks/Resources/xlf/Strings.es.xlf index c777b61b72a..3c0ca91734d 100644 --- a/src/Tasks/Resources/xlf/Strings.es.xlf +++ b/src/Tasks/Resources/xlf/Strings.es.xlf @@ -186,6 +186,11 @@ MSB3893: No se puede usar un vínculo para copiar "{0}" en "{1}". {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} No se puede usar un vínculo para copiar "{0}" en "{1}". En su lugar se copiará el archivo. {2} diff --git a/src/Tasks/Resources/xlf/Strings.fr.xlf b/src/Tasks/Resources/xlf/Strings.fr.xlf index c2b46ad0e05..b1472cd4dc5 100644 --- a/src/Tasks/Resources/xlf/Strings.fr.xlf +++ b/src/Tasks/Resources/xlf/Strings.fr.xlf @@ -186,6 +186,11 @@ MSB3893: impossible d'utiliser un lien pour copier "{0}" vers "{1}". {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Impossible d'utiliser un lien pour copier "{0}" vers "{1}". Copie du fichier à la place. {2} diff --git a/src/Tasks/Resources/xlf/Strings.it.xlf b/src/Tasks/Resources/xlf/Strings.it.xlf index cc7bc3dca94..686122b27f8 100644 --- a/src/Tasks/Resources/xlf/Strings.it.xlf +++ b/src/Tasks/Resources/xlf/Strings.it.xlf @@ -186,6 +186,11 @@ MSB3893: non è stato possibile usare un collegamento per copiare "{0}" in "{1}". {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Non è stato possibile usare un collegamento per copiare "{0}" in "{1}". Al suo posto verrà copiato il file. {2} diff --git a/src/Tasks/Resources/xlf/Strings.ja.xlf b/src/Tasks/Resources/xlf/Strings.ja.xlf index 6d2d47ce825..c3238f3accf 100644 --- a/src/Tasks/Resources/xlf/Strings.ja.xlf +++ b/src/Tasks/Resources/xlf/Strings.ja.xlf @@ -186,6 +186,11 @@ MSB3893: リンクを使用して "{0}" を "{1}" にコピーできませんでした。 {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} リンクを使用して "{0}" を "{1}" にコピーできませんでした。代わりにファイルをコピーしています。{2} diff --git a/src/Tasks/Resources/xlf/Strings.ko.xlf b/src/Tasks/Resources/xlf/Strings.ko.xlf index b9e078753f1..69dfedb671e 100644 --- a/src/Tasks/Resources/xlf/Strings.ko.xlf +++ b/src/Tasks/Resources/xlf/Strings.ko.xlf @@ -186,6 +186,11 @@ MSB3893: 링크를 사용하여 "{0}"을(를) "{1}"에 복사할 수 없습니다. {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} "{0}"을(를) "{1}"(으)로 복사하는 데 링크를 사용할 수 없습니다. 대신 파일을 복사합니다. {2} diff --git a/src/Tasks/Resources/xlf/Strings.pl.xlf b/src/Tasks/Resources/xlf/Strings.pl.xlf index 527cad494c5..5431f8d0577 100644 --- a/src/Tasks/Resources/xlf/Strings.pl.xlf +++ b/src/Tasks/Resources/xlf/Strings.pl.xlf @@ -186,6 +186,11 @@ MSB3893: Nie można użyć linku w celu skopiowania ścieżki „{0}” do ścieżki „{1}”. {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Nie można użyć linku w celu skopiowania „{0}” do „{1}”. W zamian zostanie skopiowany plik. {2} diff --git a/src/Tasks/Resources/xlf/Strings.pt-BR.xlf b/src/Tasks/Resources/xlf/Strings.pt-BR.xlf index 14a8a58fd48..d5a715545ff 100644 --- a/src/Tasks/Resources/xlf/Strings.pt-BR.xlf +++ b/src/Tasks/Resources/xlf/Strings.pt-BR.xlf @@ -186,6 +186,11 @@ MSB3893: Não foi possível usar um link para copiar "{0}" para "{1}". {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Não foi possível usar um link para copiar "{0}" em "{1}". Copiando o arquivo. {2} diff --git a/src/Tasks/Resources/xlf/Strings.ru.xlf b/src/Tasks/Resources/xlf/Strings.ru.xlf index 2c1b47e4804..6a3ad5c684d 100644 --- a/src/Tasks/Resources/xlf/Strings.ru.xlf +++ b/src/Tasks/Resources/xlf/Strings.ru.xlf @@ -186,6 +186,11 @@ MSB3893: не удалось использовать связь для копирования "{0}" в "{1}". {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} Не удалось использовать связь для копирования "{0}" в "{1}". Вместо этого копируется файл. {2} diff --git a/src/Tasks/Resources/xlf/Strings.tr.xlf b/src/Tasks/Resources/xlf/Strings.tr.xlf index 33d1387e148..a4946c05c56 100644 --- a/src/Tasks/Resources/xlf/Strings.tr.xlf +++ b/src/Tasks/Resources/xlf/Strings.tr.xlf @@ -186,6 +186,11 @@ MSB3893: "{0}" dosyasını "{1}" yoluna kopyalama bağlantısı kullanılamadı. {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} "{0}" dosyasını "{1}" yoluna kopyalamak için bağlantı kullanılamadı. Bunun yerine dosya kopyalanıyor. {2} diff --git a/src/Tasks/Resources/xlf/Strings.zh-Hans.xlf b/src/Tasks/Resources/xlf/Strings.zh-Hans.xlf index 5979367e5cd..f92848862b3 100644 --- a/src/Tasks/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/Tasks/Resources/xlf/Strings.zh-Hans.xlf @@ -186,6 +186,11 @@ MSB3893: 无法使用链接将“{0}”复制到“{1}”。 {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} 未能使用链接将“{0}”复制到“{1}”。请改为复制文件。{2} diff --git a/src/Tasks/Resources/xlf/Strings.zh-Hant.xlf b/src/Tasks/Resources/xlf/Strings.zh-Hant.xlf index 8f0aef6d180..b3c34645eeb 100644 --- a/src/Tasks/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/Tasks/Resources/xlf/Strings.zh-Hant.xlf @@ -186,6 +186,11 @@ MSB3893: 無法使用連結將 "{0}" 複製到 "{1}"。 {StrBegin="MSB3893: "} LOCALIZATION: {0} and {1} are paths. + + The {0} library call failed with the following error code: {1}. + The {0} library call failed with the following error code: {1}. + + Could not use a link to copy "{0}" to "{1}". Copying the file instead. {2} 無法使用連結將 "{0}" 複製到 "{1}"。改為複製檔案。{2}