refactor(a2a-client): no runtime-internal native calls for attachments
This commit is contained in:
@@ -285,7 +285,7 @@ internal sealed class A2ATool(A2AClientSettings settings, string target, A2AWatc
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the attachments: regular workspace files (symlinks resolved and confined), together at most
|
||||
/// Reads the attachments: workspace files (symlinks resolved and confined), together at most
|
||||
/// <see cref="A2AClientSettings.MaxFileBytes"/>, each read through one opened stream so a file growing meanwhile is
|
||||
/// still capped.
|
||||
/// </summary>
|
||||
@@ -297,7 +297,7 @@ internal sealed class A2ATool(A2AClientSettings settings, string target, A2AWatc
|
||||
{
|
||||
var full = ConfinedPath(workspace, path);
|
||||
if (Directory.Exists(full) || !File.Exists(full)) throw new ArgumentException($"{path} does not exist or is not a file.");
|
||||
if (!IsRegularFile(full)) throw new ArgumentException($"{path} is not a regular file.");
|
||||
// Special files (FIFOs, devices) aren't detected: a FIFO would block here until the run is aborted.
|
||||
byte[] bytes;
|
||||
await using (var stream = new FileStream(full, new FileStreamOptions
|
||||
{ Mode = FileMode.Open, Access = FileAccess.Read, Share = FileShare.Read, Options = FileOptions.Asynchronous }))
|
||||
@@ -321,29 +321,6 @@ internal sealed class A2ATool(A2AClientSettings settings, string target, A2AWatc
|
||||
return parts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// False for FIFOs, sockets and devices, which could block or never end. Unix: the runtime's own stat (the managed
|
||||
/// API reports every non-directory as a file); elsewhere every existing file counts as regular.
|
||||
/// </summary>
|
||||
private static bool IsRegularFile(string path)
|
||||
{
|
||||
if (OperatingSystem.IsWindows()) return true;
|
||||
try
|
||||
{
|
||||
var status = new byte[512]; // FileStatus is ~120 bytes; Mode is the second int32
|
||||
if (SystemNativeStat(path, status) != 0) return false;
|
||||
const int typeMask = 0xF000, regular = 0x8000;
|
||||
return (BitConverter.ToInt32(status, 4) & typeMask) == regular;
|
||||
}
|
||||
catch (Exception ex) when (ex is DllNotFoundException or EntryPointNotFoundException)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("libSystem.Native", EntryPoint = "SystemNative_Stat")]
|
||||
private static extern int SystemNativeStat([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPUTF8Str)] string path, byte[] status);
|
||||
|
||||
/// <summary>The real path of a workspace file: inside the workspace lexically and after every symlink is resolved.</summary>
|
||||
internal static string ConfinedPath(string workspace, string path)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user