projects/guix·blob python-team · refs

389 lines · 9.7 KiB

1Upstream status: Not presented upstream.
2
3From 0cca01b3700b7fb427ac2e9b7a612e8b703cc185 Mon Sep 17 00:00:00 2001
4From: Janneke Nieuwenhuizen <[email protected]>
5Date: Mon, 16 Feb 2026 18:18:27 +0100
6Subject: [PATCH] Add bindings to syscalls for which glibc has symbols.
7
8Using the FFI would have been nice, but that's not an option when using
9a statically-linked Guile in an initrd that doesn't have libc.so around.
10---
11 libguile/posix.c | 362 +++++++++++++++++++++++++++++++++++++++++++++++
12 1 file changed, 362 insertions(+)
13
14diff --git a/libguile/posix.c b/libguile/posix.c
15index 78ce03e68..bcc538b9f 100644
16--- a/libguile/posix.c
17+++ b/libguile/posix.c
18@@ -2595,6 +2595,368 @@ scm_init_popen (void)
19 }
20
21
22+#include "libguile/bytevectors.h"
23+#include "libguile/foreign.h"
24+#include <libguile/variable.h>
25+
26+/* Linux! */
27+#ifdef __linux__
28+
29+#include <sys/mount.h>
30+#include <sys/syscall.h>
31+
32+
33+SCM_DEFINE (scm_mount, "mount", 3, 2, 0,
34+ (SCM source, SCM target, SCM type, SCM flags, SCM data),
35+ "Mount file system of @var{type} specified by @var{source} "
36+ "on @var{target}.")
37+#define FUNC_NAME s_scm_mount
38+{
39+ int err;
40+ char *c_source, *c_target, *c_type, *c_data;
41+ unsigned long c_flags;
42+
43+ c_source = scm_to_locale_string (source);
44+ c_target = scm_to_locale_string (target);
45+ c_type = scm_to_locale_string (type);
46+ c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_ulong (flags);
47+
48+ if (SCM_UNBNDP (data) || scm_is_false (data))
49+ c_data = NULL;
50+ else
51+ c_data = scm_to_locale_string (data);
52+
53+ err = mount (c_source, c_target, c_type, c_flags, c_data);
54+ if (err != 0)
55+ err = errno;
56+
57+ free (c_source);
58+ free (c_target);
59+ free (c_type);
60+
61+ if (c_data != NULL)
62+ free (c_data);
63+
64+ if (err != 0)
65+ {
66+ errno = err;
67+ SCM_SYSERROR;
68+ }
69+
70+ return SCM_UNSPECIFIED;
71+}
72+#undef FUNC_NAME
73+
74+SCM_DEFINE (scm_umount, "umount", 1, 0, 0,
75+ (SCM target),
76+ "Unmount the file system on @var{target}.")
77+#define FUNC_NAME s_scm_umount
78+{
79+ int err;
80+ char *c_target;
81+
82+ c_target = scm_to_locale_string (target);
83+
84+ err = umount (c_target);
85+ if (err != 0)
86+ err = errno;
87+
88+ free (c_target);
89+
90+ if (err != 0)
91+ {
92+ errno = err;
93+ SCM_SYSERROR;
94+ }
95+
96+ return SCM_UNSPECIFIED;
97+}
98+#undef FUNC_NAME
99+
100+/* Linux's module installation syscall. See `kernel/module.c' in Linux;
101+ the function itself is part of the GNU libc.
102+
103+ Load the LEN bytes at MODULE as a kernel module, with arguments from
104+ ARGS, a space-separated list of options. */
105+extern long init_module (void *module, unsigned long len, const char *args);
106+
107+/* Load a kernel module from FD. FLAGS must be a bitwise or of
108+ MODULE_INIT_* constants. The GNU libc doesn't provide a wrapper for
109+ this one so we use 'syscall'. */
110+static int
111+finit_module (int fd, const char *args, int flags)
112+{
113+ return syscall (SYS_finit_module, fd, args, flags);
114+}
115+
116+
117+SCM_DEFINE (scm_load_linux_module, "load-linux-module", 1, 1, 0,
118+ (SCM data, SCM options),
119+ "Load the Linux kernel module whose contents are in bytevector "
120+ "DATA (the contents of a @code{.ko} file), with the arguments "
121+ "from the OPTIONS string.")
122+#define FUNC_NAME s_scm_load_linux_module
123+{
124+ long err;
125+ void *c_data;
126+ unsigned long c_len;
127+ char *c_options;
128+
129+ SCM_VALIDATE_BYTEVECTOR (SCM_ARG1, data);
130+
131+ c_data = SCM_BYTEVECTOR_CONTENTS (data);
132+ c_len = SCM_BYTEVECTOR_LENGTH (data);
133+ c_options =
134+ scm_to_locale_string (SCM_UNBNDP (options) ? scm_nullstr : options);
135+
136+ err = init_module (c_data, c_len, c_options);
137+
138+ free (c_options);
139+
140+ if (err != 0)
141+ SCM_SYSERROR;
142+
143+ return SCM_UNSPECIFIED;
144+}
145+#undef FUNC_NAME
146+
147+SCM_DEFINE (scm_load_linux_module_fd, "load-linux-module/fd", 1, 2, 0,
148+ (SCM fd, SCM options, SCM flags),
149+ "Load the Linux kernel module from the file at FD, "
150+ "with the arguments from the OPTIONS string, and "
151+ "optionally the given FLAGS.")
152+#define FUNC_NAME s_scm_load_linux_module_fd
153+{
154+ long err;
155+ int c_fd, c_flags;
156+ char *c_options;
157+
158+ c_fd = scm_to_int (fd);
159+ c_options =
160+ scm_to_locale_string (SCM_UNBNDP (options) ? scm_nullstr : options);
161+ c_flags = SCM_UNBNDP (flags) ? 0 : scm_to_int (flags);
162+
163+ err = finit_module (c_fd, c_options, c_flags);
164+
165+ free (c_options);
166+
167+ if (err != 0)
168+ SCM_SYSERROR;
169+
170+ return SCM_UNSPECIFIED;
171+}
172+#undef FUNC_NAME
173+
174+
175+/* Rebooting, halting, and all that. */
176+
177+#include <sys/reboot.h>
178+
179+SCM_VARIABLE_INIT (flag_RB_AUTOBOOT, "RB_AUTOBOOT",
180+ scm_from_int (RB_AUTOBOOT));
181+SCM_VARIABLE_INIT (flag_RB_HALT_SYSTEM, "RB_HALT_SYSTEM",
182+ scm_from_int (RB_HALT_SYSTEM));
183+SCM_VARIABLE_INIT (flag_RB_ENABLE_CAD, "RB_ENABLE_CAD",
184+ scm_from_int (RB_ENABLE_CAD));
185+SCM_VARIABLE_INIT (flag_RB_DISABLE_CAD, "RB_DISABLE_CAD",
186+ scm_from_int (RB_DISABLE_CAD));
187+SCM_VARIABLE_INIT (flag_RB_POWER_OFF, "RB_POWER_OFF",
188+ scm_from_int (RB_POWER_OFF));
189+SCM_VARIABLE_INIT (flag_RB_SW_SUSPEND, "RB_SW_SUSPEND",
190+ scm_from_int (RB_SW_SUSPEND));
191+SCM_VARIABLE_INIT (flag_RB_KEXEC, "RB_KEXEC",
192+ scm_from_int (RB_KEXEC));
193+
194+SCM_DEFINE (scm_reboot, "reboot", 0, 1, 0,
195+ (SCM command),
196+ "Reboot the system. @var{command} must be one of the @code{RB_} "
197+ "constants; if omitted, @var{RB_AUTOBOOT} is used, thus "
198+ "performing a hard reset.")
199+#define FUNC_NAME s_scm_reboot
200+{
201+ int c_command;
202+
203+ if (SCM_UNBNDP (command))
204+ c_command = RB_AUTOBOOT;
205+ else
206+ c_command = scm_to_int (command);
207+
208+ reboot (c_command);
209+
210+ return SCM_UNSPECIFIED; /* likely unreached */
211+}
212+#undef FUNC_NAME
213+
214+/* Linux network interfaces. See <linux/if.h>. */
215+
216+#include <linux/if.h>
217+#include <linux/sockios.h>
218+#include "libguile/socket.h"
219+
220+SCM_VARIABLE_INIT (flag_IFF_UP, "IFF_UP",
221+ scm_from_int (IFF_UP));
222+SCM_VARIABLE_INIT (flag_IFF_BROADCAST, "IFF_BROADCAST",
223+ scm_from_int (IFF_BROADCAST));
224+SCM_VARIABLE_INIT (flag_IFF_DEBUG, "IFF_DEBUG",
225+ scm_from_int (IFF_DEBUG));
226+SCM_VARIABLE_INIT (flag_IFF_LOOPBACK, "IFF_LOOPBACK",
227+ scm_from_int (IFF_LOOPBACK));
228+SCM_VARIABLE_INIT (flag_IFF_POINTOPOINT, "IFF_POINTOPOINT",
229+ scm_from_int (IFF_POINTOPOINT));
230+SCM_VARIABLE_INIT (flag_IFF_NOTRAILERS, "IFF_NOTRAILERS",
231+ scm_from_int (IFF_NOTRAILERS));
232+SCM_VARIABLE_INIT (flag_IFF_RUNNING, "IFF_RUNNING",
233+ scm_from_int (IFF_RUNNING));
234+SCM_VARIABLE_INIT (flag_IFF_NOARP, "IFF_NOARP",
235+ scm_from_int (IFF_NOARP));
236+SCM_VARIABLE_INIT (flag_IFF_PROMISC, "IFF_PROMISC",
237+ scm_from_int (IFF_PROMISC));
238+SCM_VARIABLE_INIT (flag_IFF_ALLMULTI, "IFF_ALLMULTI",
239+ scm_from_int (IFF_ALLMULTI));
240+
241+SCM_DEFINE (scm_set_network_interface_address, "set-network-interface-address",
242+ 3, 0, 0,
243+ (SCM socket, SCM name, SCM address),
244+ "Configure network interface @var{name}.")
245+#define FUNC_NAME s_scm_set_network_interface_address
246+{
247+ char *c_name;
248+ struct ifreq ifr;
249+ struct sockaddr *c_address;
250+ size_t sa_len;
251+ int fd, err;
252+
253+ socket = SCM_COERCE_OUTPORT (socket);
254+ SCM_VALIDATE_OPFPORT (1, socket);
255+ fd = SCM_FPORT_FDES (socket);
256+
257+ memset (&ifr, 0, sizeof ifr);
258+ c_name = scm_to_locale_string (name);
259+ c_address = scm_to_sockaddr (address, &sa_len);
260+
261+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
262+ memcpy (&ifr.ifr_addr, c_address, sa_len);
263+
264+ err = ioctl (fd, SIOCSIFADDR, &ifr);
265+ if (err != 0)
266+ err = errno;
267+
268+ free (c_name);
269+ free (c_address);
270+
271+ if (err != 0)
272+ {
273+ errno = err;
274+ SCM_SYSERROR;
275+ }
276+
277+ return SCM_UNSPECIFIED;
278+}
279+#undef FUNC_NAME
280+
281+SCM_DEFINE (scm_set_network_interface_flags, "set-network-interface-flags",
282+ 3, 0, 0,
283+ (SCM socket, SCM name, SCM flags),
284+ "Change the flags of network interface @var{name} to "
285+ "@var{flags}.")
286+#define FUNC_NAME s_scm_set_network_interface_flags
287+{
288+ struct ifreq ifr;
289+ char *c_name;
290+ int fd, err;
291+
292+ socket = SCM_COERCE_OUTPORT (socket);
293+ SCM_VALIDATE_OPFPORT (1, socket);
294+ fd = SCM_FPORT_FDES (socket);
295+
296+ memset (&ifr, 0, sizeof ifr);
297+ c_name = scm_to_locale_string (name);
298+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
299+ ifr.ifr_flags = scm_to_short (flags);
300+
301+ err = ioctl (fd, SIOCSIFFLAGS, &ifr);
302+ if (err != 0)
303+ err = errno;
304+
305+ free (c_name);
306+
307+ if (err != 0)
308+ {
309+ errno = err;
310+ SCM_SYSERROR;
311+ }
312+
313+ return SCM_UNSPECIFIED;
314+}
315+#undef FUNC_NAME
316+
317+SCM_DEFINE (scm_network_interface_flags, "network-interface-flags",
318+ 2, 0, 0,
319+ (SCM socket, SCM name),
320+ "Return the flags of network interface @var{name}.")
321+#define FUNC_NAME s_scm_network_interface_flags
322+{
323+ struct ifreq ifr;
324+ char *c_name;
325+ int fd, err;
326+
327+ socket = SCM_COERCE_OUTPORT (socket);
328+ SCM_VALIDATE_OPFPORT (1, socket);
329+ fd = SCM_FPORT_FDES (socket);
330+
331+ memset (&ifr, 0, sizeof ifr);
332+ c_name = scm_to_locale_string (name);
333+ strncpy (ifr.ifr_name, c_name, sizeof ifr.ifr_name - 1);
334+
335+ err = ioctl (fd, SIOCGIFFLAGS, &ifr);
336+ if (err != 0)
337+ err = errno;
338+
339+ free (c_name);
340+
341+ if (err != 0)
342+ {
343+ errno = err;
344+ SCM_SYSERROR;
345+ }
346+
347+ return scm_from_short (ifr.ifr_flags);
348+}
349+#undef FUNC_NAME
350+#endif
351+
352+#include <sys/statfs.h>
353+
354+SCM_DEFINE (scm_statfs_raw, "statfs-raw", 1, 0, 0,
355+ (SCM filesystem),
356+ "Return a bytevector describing @var{filesystem}")
357+#define FUNC_NAME s_scm_statfs_raw
358+{
359+ int err;
360+ char *c_filesystem;
361+ SCM bv;
362+
363+ c_filesystem = scm_to_locale_string (filesystem);
364+
365+ bv = scm_c_make_bytevector (sizeof (struct statfs));
366+ struct statfs *bv_pointer = scm_to_pointer (scm_bytevector_to_pointer (bv, scm_from_int (0)));
367+
368+ err = statfs (c_filesystem, bv_pointer);
369+ if (err != 0)
370+ err = errno;
371+
372+ free (c_filesystem);
373+
374+ if (err != 0)
375+ {
376+ errno = err;
377+ SCM_SYSERROR;
378+ }
379+
380+ return bv;
381+}
382+#undef FUNC_NAME
383+
384 void
385 scm_init_posix ()
386 {
387--
3882.52.0
389