Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Framework/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 10 additions & 9 deletions src/Tasks.UnitTests/Copy_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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) };

Expand All @@ -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"
Expand Down
12 changes: 8 additions & 4 deletions src/Tasks/Copy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down
31 changes: 16 additions & 15 deletions src/Tasks/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#endif
using System.Text.RegularExpressions;
using System.Runtime.Versioning;
using Microsoft.Build.Utilities;

#nullable disable

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -521,7 +522,7 @@ internal struct PROCESS_INFORMATION
/// </summary>
internal static class NativeMethods
{
#region Constants
#region Constants

internal static readonly IntPtr NullPtr = IntPtr.Zero;
internal static readonly IntPtr InvalidIntPtr = new IntPtr(-1);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This resource doesn't seem to exist?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's awkward. Will fix—thanks for pointing that out!

}

return hardLinkCreated;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
/// <summary>
/// Given a pointer to a metadata blob, read the string parameter from it. Returns true if
Expand Down Expand Up @@ -1233,8 +1234,8 @@ internal static unsafe int CorSigUncompressData(IntPtr data, out int uncompresse

return count;
}
#endregion
#region InternalClass
#endregion
#region InternalClass
/// <summary>
/// This class is a wrapper over the native GAC enumeration API.
/// </summary>
Expand Down Expand Up @@ -1472,6 +1473,6 @@ public static string AssemblyPathFromStrongName(string strongName)
return null;
}
}
#endregion
#endregion
}
}
3 changes: 3 additions & 0 deletions src/Tasks/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@

If this bucket overflows, pls. contact 'vsppbdev'.
-->
<data name="Copy.NonWindowsLinkErrorMessage">
<value>The {0} library call failed with the following error code: {1}.</value>
</data>
<data name="Copy.CreatesDirectory">
<value>Creating directory "{0}".</value>
</data>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading