Skip to content

Commit 8438a62

Browse files
committed
Get the host name from uname method to avoid read the file
1 parent 486f46e commit 8438a62

File tree

2 files changed

+116
-9
lines changed

2 files changed

+116
-9
lines changed

src/Avalonia.X11/UtsName.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace Avalonia.X11;
9+
10+
internal struct UtsName : IDisposable
11+
{
12+
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/utsname.h
13+
/*
14+
#define __NEW_UTS_LEN 64
15+
16+
struct new_utsname
17+
{
18+
char sysname[__NEW_UTS_LEN + 1];
19+
char nodename[__NEW_UTS_LEN + 1];
20+
char release[__NEW_UTS_LEN + 1];
21+
char version[__NEW_UTS_LEN + 1];
22+
char machine[__NEW_UTS_LEN + 1];
23+
char domainname[__NEW_UTS_LEN + 1];
24+
};
25+
*/
26+
27+
private UtsName(IntPtr buffer)
28+
{
29+
_buffer = buffer;
30+
}
31+
32+
public static UtsName GetUtsName()
33+
{
34+
var ntsNameStructSize = (UtsLength + 1) * FieldCount;
35+
36+
IntPtr buffer = Marshal.AllocHGlobal(ntsNameStructSize);
37+
try
38+
{
39+
if (uname(buffer) != 0)
40+
{
41+
throw new InvalidOperationException("uname failed");
42+
}
43+
44+
return new UtsName(buffer);
45+
}
46+
catch
47+
{
48+
Marshal.FreeHGlobal(buffer);
49+
throw;
50+
}
51+
}
52+
53+
private const int SystemNameFieldIndex = 0;
54+
public Span<byte> SystemNameSpan => GetValue(SystemNameFieldIndex);
55+
public string SystemName => Encoding.UTF8.GetString(SystemNameSpan);
56+
57+
private const int NodeNameFieldIndex = 1;
58+
public Span<byte> NodeNameSpan => GetValue(NodeNameFieldIndex);
59+
public string NodeName => Encoding.UTF8.GetString(NodeNameSpan);
60+
61+
private const int ReleaseFieldIndex = 2;
62+
public Span<byte> ReleaseSpan => GetValue(ReleaseFieldIndex);
63+
public string Release => Encoding.UTF8.GetString(ReleaseSpan);
64+
65+
private const int VersionFieldIndex = 3;
66+
public Span<byte> VersionSpan => GetValue(VersionFieldIndex);
67+
public string Version => Encoding.UTF8.GetString(VersionSpan);
68+
69+
private const int MachineFieldIndex = 4;
70+
public Span<byte> MachineSpan => GetValue(MachineFieldIndex);
71+
public string Machine => Encoding.UTF8.GetString(MachineSpan);
72+
73+
private const int DomainNameFieldIndex = 5;
74+
public Span<byte> DomainNameSpan => GetValue(DomainNameFieldIndex);
75+
public string DomainName => Encoding.UTF8.GetString(DomainNameSpan);
76+
77+
private const int UtsLength = 64;
78+
79+
private const int FieldCount = 6;
80+
81+
private Span<byte> GetValue(int fieldIndex)
82+
{
83+
var startOffset = (UtsLength + 1) * fieldIndex;
84+
var length = 0;
85+
while (Marshal.ReadByte(_buffer, startOffset + length) != 0)
86+
{
87+
length++;
88+
}
89+
90+
unsafe
91+
{
92+
return new Span<byte>((byte*)_buffer + startOffset, length);
93+
}
94+
}
95+
96+
[DllImport("libc")]
97+
private static extern int uname(IntPtr buf);
98+
99+
private readonly IntPtr _buffer;
100+
101+
public void Dispose()
102+
{
103+
Marshal.FreeHGlobal(_buffer);
104+
}
105+
}

src/Avalonia.X11/X11Window.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Diagnostics;
4-
using System.IO;
54
using System.Linq;
65
using Avalonia.Reactive;
76
using System.Text;
@@ -343,17 +342,20 @@ private void AppendPid(IntPtr windowXId)
343342
_x11.Atoms._NET_WM_PID, _x11.Atoms.XA_CARDINAL, 32,
344343
PropertyMode.Replace, ref pid, 1);
345344

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

353+
var nodeNameSpan = utsName.NodeNameSpan;
354+
fixed (byte* pNodeName = &nodeNameSpan.GetPinnableReference())
355+
{
354356
XChangeProperty(_x11.Display, windowXId,
355357
WM_CLIENT_MACHINE, _x11.Atoms.XA_STRING, 8,
356-
PropertyMode.Replace, ref stringToHGlobalAnsi, (int)hostName.Length);
358+
PropertyMode.Replace, pNodeName, nodeNameSpan.Length);
357359
}
358360
}
359361

0 commit comments

Comments
 (0)