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