gnu: Add kafs-client
[jackhill/guix/guix.git] / gnu / packages / patches / guile-3.0-linux-syscalls.patch
1 This patch adds bindings to Linux syscalls for which glibc has symbols.
2
3 Using the FFI would have been nice, but that's not an option when using
4 a statically-linked Guile in an initrd that doesn't have libc.so around.
5
6 diff --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 {