Skip to content

Commit

Permalink
Get the host name from uname method to avoid read the file
Browse files Browse the repository at this point in the history
  • Loading branch information
lindexi committed Nov 11, 2024
1 parent 486f46e commit e64354a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 8 deletions.
105 changes: 105 additions & 0 deletions src/Avalonia.X11/UtsName.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace Avalonia.X11;

internal struct UtsName : IDisposable
{
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/utsname.h
/*
#define __NEW_UTS_LEN 64
struct new_utsname
{
char sysname[__NEW_UTS_LEN + 1];
char nodename[__NEW_UTS_LEN + 1];
char release[__NEW_UTS_LEN + 1];
char version[__NEW_UTS_LEN + 1];
char machine[__NEW_UTS_LEN + 1];
char domainname[__NEW_UTS_LEN + 1];
};
*/

private UtsName(IntPtr buffer)
{
_buffer = buffer;
}

public static UtsName GetUtsName()
{
var ntsNameStructSize = (UtsLength + 1) * FieldCount;

IntPtr buffer = Marshal.AllocHGlobal(ntsNameStructSize);
try
{
if (uname(buffer) != 0)
{
throw new InvalidOperationException("uname failed");
}

return new UtsName(buffer);
}
catch
{
Marshal.FreeHGlobal(buffer);
throw;
}
}

private const int SystemNameFieldIndex = 0;
public Span<byte> SystemNameSpan => GetValue(SystemNameFieldIndex);
public string SystemName => Encoding.UTF8.GetString(SystemNameSpan);

private const int NodeNameFieldIndex = 1;
public Span<byte> NodeNameSpan => GetValue(NodeNameFieldIndex);
public string NodeName => Encoding.UTF8.GetString(NodeNameSpan);

private const int ReleaseFieldIndex = 2;
public Span<byte> ReleaseSpan => GetValue(ReleaseFieldIndex);
public string Release => Encoding.UTF8.GetString(ReleaseSpan);

private const int VersionFieldIndex = 3;
public Span<byte> VersionSpan => GetValue(VersionFieldIndex);
public string Version => Encoding.UTF8.GetString(VersionSpan);

private const int MachineFieldIndex = 4;
public Span<byte> MachineSpan => GetValue(MachineFieldIndex);
public string Machine => Encoding.UTF8.GetString(MachineSpan);

private const int DomainNameFieldIndex = 5;
public Span<byte> DomainNameSpan => GetValue(DomainNameFieldIndex);
public string DomainName => Encoding.UTF8.GetString(DomainNameSpan);

private const int UtsLength = 64;

private const int FieldCount = 6;

private Span<byte> GetValue(int fieldIndex)
{
var startOffset = (UtsLength + 1) * fieldIndex;
var length = 0;
while (Marshal.ReadByte(_buffer, startOffset + length) != 0)
{
length++;
}

unsafe
{
return new Span<byte>((byte*)_buffer + startOffset, length);
}
}

[DllImport("libc")]
private static extern int uname(IntPtr buf);

private readonly IntPtr _buffer;

public void Dispose()
{
Marshal.FreeHGlobal(_buffer);
}
}
23 changes: 15 additions & 8 deletions src/Avalonia.X11/X11Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
using System.Runtime.InteropServices;
using Avalonia.Dialogs;
using Avalonia.Platform.Storage.FileIO;
using System.Reflection.Metadata;

// ReSharper disable IdentifierTypo
// ReSharper disable StringLiteralTypo
Expand Down Expand Up @@ -343,20 +344,26 @@ private void AppendPid(IntPtr windowXId)
_x11.Atoms._NET_WM_PID, _x11.Atoms.XA_CARDINAL, 32,
PropertyMode.Replace, ref pid, 1);

// If _NET_WM_PID is set, the ICCCM-specified property WM_CLIENT_MACHINE MUST also be set.
var hostNameFilePath = "cat /proc/sys/kernel/hostname";
if (File.Exists(hostNameFilePath))
{
var WM_CLIENT_MACHINE = XInternAtom(_x11.Display, "WM_CLIENT_MACHINE", false);
var hostName = File.ReadAllText(hostNameFilePath);
var stringToHGlobalAnsi = Marshal.StringToHGlobalAnsi(hostName);
// If _NET_WM_PID is set, the ICCCM-specified property WM_CLIENT_MACHINE MUST also be set.
// the hostname can change, so we can't cache it
// gethostname(3) on Linux just calls uname(2), so do it ourselves
// and avoid a memcpy
using var utsName = UtsName.GetUtsName();

var WM_CLIENT_MACHINE = XInternAtom(_x11.Display, "WM_CLIENT_MACHINE", false);

var nodeNameSpan = utsName.NodeNameSpan;
fixed (byte* pNodeName = &nodeNameSpan.GetPinnableReference())
{
XChangeProperty(_x11.Display, windowXId,
WM_CLIENT_MACHINE, _x11.Atoms.XA_STRING, 8,
PropertyMode.Replace, ref stringToHGlobalAnsi, (int)hostName.Length);
PropertyMode.Replace, pNodeName, nodeNameSpan.Length);
}
}

[DllImport("libc")]
static extern int uname(IntPtr buf);

private static readonly int s_pid = GetProcessId();

private static int GetProcessId()
Expand Down

0 comments on commit e64354a

Please sign in to comment.