1 ;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil -*-
3 ;;; --- *UNIX foreign function definitions.
6 (in-package :iolib.syscalls
)
8 ;;; Needed for clock_gettime() and friends.
9 #+linux
(load-foreign-library "librt.so")
12 ;;;-------------------------------------------------------------------------
13 ;;; ERRNO-related functions
14 ;;;-------------------------------------------------------------------------
16 (defentrypoint (setf %sys-errno
) (value)
17 (%%sys-set-errno value
))
19 (defentrypoint %sys-strerror
(&optional
(err (%sys-errno
)))
20 "Look up the error message string for ERRNO. (reentrant)"
23 (foreign-enum-value 'errno-values err
)
25 (with-foreign-pointer-as-string ((buf bufsiz
) 1024)
26 (%sys-strerror-r errno buf bufsiz
))))
28 (defmethod print-object ((posix-error posix-error
) stream
)
29 (print-unreadable-object (posix-error stream
:type nil
:identity nil
)
30 (let ((code (code-of posix-error
))
31 (identifier (identifier-of posix-error
)))
32 (format stream
"POSIX Error ~A code: ~S ~S"
33 identifier
(or code
"[No code]")
34 (or (%sys-strerror code
) "[Can't get error string.]")))))
37 ;;;-------------------------------------------------------------------------
38 ;;; Memory manipulation
39 ;;;-------------------------------------------------------------------------
41 (defcfun* ("memset" %sys-memset
) :pointer
46 (defentrypoint %sys-bzero
(buffer length
)
47 (%sys-memset buffer
0 length
))
49 (defcfun* ("memcpy" %sys-memcpy
) :pointer
54 (defcfun* ("memmove" %sys-memmove
) :pointer
60 ;;;-------------------------------------------------------------------------
62 ;;;-------------------------------------------------------------------------
64 (defsyscall* ("read" %sys-read
) ssize-t
65 "Read at most COUNT bytes from FD into the foreign area BUF."
70 (defsyscall* ("write" %sys-write
) ssize-t
71 "Write at most COUNT bytes to FD from the foreign area BUF."
77 ;;;-------------------------------------------------------------------------
79 ;;;-------------------------------------------------------------------------
81 (defsyscall* ("open" %%sys-open
) :int
82 (pathname filename-designator
)
86 (defvar *default-open-mode
* #o666
)
88 (defentrypoint %sys-open
(pathname flags
&optional
(mode *default-open-mode
*))
89 (%%sys-open pathname flags mode
))
91 (defsyscall* ("creat" %sys-creat
) :int
92 (pathname filename-designator
)
95 (defsyscall ("pipe" %%sys-pipe
) :int
98 (defentrypoint %sys-pipe
()
99 "Create pipe, returns two values with the new FDs."
100 (with-foreign-object (filedes :int
2)
102 (values (mem-aref filedes
:int
0)
103 (mem-aref filedes
:int
1))))
105 (defsyscall ("mkfifo" %sys-mkfifo
) :int
106 "Create a FIFO (named pipe)."
107 (path filename-designator
)
110 (defsyscall "umask" mode-t
111 "Sets the umask and returns the old one"
114 (defsyscall ("access" %sys-access
) :int
115 (path filename-designator
)
118 (defsyscall ("rename" %sys-rename
) :int
120 (old filename-designator
)
121 (new filename-designator
))
123 (defsyscall ("link" %sys-link
) :int
124 (path1 filename-designator
)
125 (path2 filename-designator
))
127 (defsyscall ("symlink" %sys-symlink
) :int
128 "Creates a symbolic link"
129 (name1 filename-designator
)
130 (name2 filename-designator
))
132 (defsyscall ("readlink" %%sys-readlink
) ssize-t
133 (path filename-designator
)
137 (defentrypoint %sys-readlink
(path)
138 "Read value of a symbolic link."
139 (with-foreign-pointer (buf 4096 bufsize
)
140 (let ((count (%%sys-readlink path buf bufsize
)))
141 (values (foreign-string-to-lisp buf
:count count
)))))
143 (defsyscall ("unlink" %sys-unlink
) :int
144 (path filename-designator
))
146 (defsyscall* ("chown" %sys-chown
) :int
147 "Change ownership of a file."
148 (path filename-designator
)
152 (defsyscall* ("fchown" %sys-fchown
) :int
153 "Change ownership of an open file."
158 (defsyscall* ("lchown" %sys-lchown
) :int
159 "Change ownership of a file or symlink."
160 (path filename-designator
)
164 (defsyscall* ("chmod" %sys-chmod
) :int
165 (path filename-designator
)
168 (defsyscall* ("fchmod" %sys-fchmod
) :int
174 (define-c-struct-wrapper stat
())
176 (defconstant +stat-version-linux
+ 3)
178 ;;; If necessary for performance reasons, we can add an optional
179 ;;; argument to this function and use that to reuse a wrapper object.
180 (defentrypoint funcall-stat
(fn arg
)
181 (with-foreign-object (buf 'stat
)
183 (make-instance 'stat
:pointer buf
)))
185 (defentrypoint %sys-stat
(path)
186 "Get information about a file."
187 (funcall-stat #'%%sys-stat path
))
189 (defentrypoint %sys-fstat
(fd)
190 "Get information about a file descriptor"
191 (funcall-stat #'%%sys-fstat fd
))
193 (defentrypoint %sys-lstat
(path)
194 "Get information about a file or symlink."
195 (funcall-stat #'%%sys-lstat path
))
197 (defsyscall ("sync" %sys-sync
) :void
198 "Schedule all file system buffers to be written to disk.")
200 (defsyscall* ("fsync" %sys-fsync
) :int
203 (defsyscall ("mkstemp" %%sys-mkstemp
) :int
204 (template filename-designator
))
206 (defentrypoint %sys-mkstemp
(&optional
(template ""))
207 (let ((template (concatenate 'string template
"XXXXXX")))
208 (with-foreign-string (ptr (filename template
))
209 (values (%%sys-mkstemp ptr
) (foreign-string-to-lisp ptr
)))))
212 ;;;-------------------------------------------------------------------------
214 ;;;-------------------------------------------------------------------------
216 (defsyscall "mkdir" :int
217 "Create a directory."
218 (path filename-designator
)
221 (defsyscall ("rmdir" %sys-rmdir
) :int
222 (path filename-designator
))
224 (defsyscall ("chdir" %sys-chdir
) :int
225 "Changes the current working directory"
226 (path filename-designator
))
228 (defsyscall* ("fchdir" %sys-fchdir
) :int
231 (defsyscall ("getcwd" %%sys-getcwd
) :string
235 (defentrypoint %sys-getcwd
()
236 "Returns the current working directory as a string."
237 (with-foreign-pointer (buf path-max size
)
238 (%%sys-getcwd buf size
)))
240 (defsyscall ("mkdtemp" %%sys-mkdtemp
) :int
241 (template filename-designator
))
243 (defentrypoint %sys-mkdtemp
(&optional
(template ""))
244 (let ((template (concatenate 'string template
"XXXXXX")))
245 (with-foreign-string (ptr (filename template
))
246 (values (%%sys-mkdtemp ptr
) (foreign-string-to-lisp ptr
)))))
249 ;;;-------------------------------------------------------------------------
251 ;;;-------------------------------------------------------------------------
253 (defsyscall ("close" %sys-close
) :int
254 "Close an open file descriptor."
257 (defsyscall ("dup" %sys-dup
) :int
260 (defsyscall* ("dup2" %sys-dup2
) :int
264 (defsyscall* ("ioctl" %sys-ioctl
/2) :int
268 (defsyscall* ("ioctl" %sys-ioctl
/3) :int
273 (defentrypoint %sys-fd-open-p
(fd)
274 (not (minusp (%sys-fstat fd
))))
277 ;;;-------------------------------------------------------------------------
278 ;;; File descriptor polling
279 ;;;-------------------------------------------------------------------------
281 ;;; FIXME: Until a way to autodetect platform features is implemented
282 #+(or darwin freebsd
)
283 (defconstant pollrdhup
0)
285 (defsyscall ("poll" %sys-poll
) :int
286 "Scan for I/O activity on multiple file descriptors."
292 ;;;-------------------------------------------------------------------------
294 ;;;-------------------------------------------------------------------------
296 (defsyscall ("munmap" %sys-munmap
) :int
297 "Unmap pages of memory."
302 ;;;-------------------------------------------------------------------------
303 ;;; Process creation and info
304 ;;;-------------------------------------------------------------------------
306 (defsyscall ("fork" %sys-fork
) pid-t
307 "Create a child process.")
309 (defsyscall ("getpid" %sys-getpid
) pid-t
310 "Returns the process id of the current process")
312 (defsyscall ("getppid" %sys-getppid
) pid-t
313 "Returns the process id of the current process's parent")
315 (defsyscall ("getuid" %sys-getuid
) uid-t
316 "Get real user id of the current process.")
318 (defsyscall ("setuid" %sys-setuid
) :int
319 "Set real user id of the current process."
322 (defsyscall ("geteuid" %sys-geteuid
) uid-t
323 "Get effective user id of the current process.")
325 (defsyscall ("seteuid" %sys-seteuid
) :int
326 "Set effective user id of the current process."
329 (defsyscall ("getgid" %sys-getgid
) gid-t
330 "Get real group id of the current process.")
332 (defsyscall ("setgid" %sys-setgid
) :int
333 "Set real group id of the current process."
336 (defsyscall ("getegid" %sys-getegid
) gid-t
337 "Get effective group id of the current process.")
339 (defsyscall ("setegid" %sys-setegid
) :int
340 "Set effective group id of the current process."
343 (defsyscall ("setreuid" %sys-setreuid
) :int
344 "Set real and effective user id of the current process."
348 (defsyscall ("setregid" %sys-setregid
) :int
349 "Set real and effective group id of the current process."
353 (defsyscall ("getpgid" %sys-getpgid
) pid-t
354 "Get process group id of a process."
357 (defsyscall ("setpgid" %sys-setpgid
) :int
358 "Set process group id of a process."
362 (defsyscall ("getpgrp" %sys-getpgrp
) pid-t
363 "Get process group id of the current process.")
365 (defsyscall ("setpgrp" %sys-setpgrp
) pid-t
366 "Set process group id of the current process.")
368 (defsyscall ("setsid" %sys-setsid
) pid-t
369 "Create session and set process group id of the current process.")
371 (defentrypoint %sys-getrlimit
(resource)
372 (with-foreign-object (rl 'rlimit
)
373 (with-foreign-slots ((cur max
) rl rlimit
)
374 (%%sys-getrlimit resource rl
)
377 (defentrypoint %sys-setrlimit
(resource soft-limit hard-limit
)
378 (with-foreign-object (rl 'rlimit
)
379 (with-foreign-slots ((cur max
) rl rlimit
)
382 (%%sys-setrlimit resource rl
))))
384 (defsyscall ("getrusage" %%sys-getrusage
) :int
388 ;;; TODO: it might be more convenient to return a wrapper object here
389 ;;; instead like we do in STAT.
390 (defentrypoint %sys-getrusage
(who)
391 (with-foreign-object (ru 'rusage
)
392 (%%sys-getrusage who ru
)
393 (with-foreign-slots ((maxrss ixrss idrss isrss minflt majflt nswap inblock
394 oublock msgsnd msgrcv nsignals nvcsw nivcsw
)
396 (values (foreign-slot-value (foreign-slot-pointer ru
'rusage
'utime
)
398 (foreign-slot-value (foreign-slot-pointer ru
'rusage
'utime
)
400 (foreign-slot-value (foreign-slot-pointer ru
'rusage
'stime
)
402 (foreign-slot-value (foreign-slot-pointer ru
'rusage
'stime
)
404 maxrss ixrss idrss isrss minflt majflt
405 nswap inblock oublock msgsnd
406 msgrcv nsignals nvcsw nivcsw
))))
408 (defsyscall ("getpriority" %sys-getpriority
) :int
412 (defsyscall ("setpriority" %sys-setpriority
) :int
417 (defentrypoint %sys-nice
(&optional
(increment 0))
418 "Get or set process priority."
419 ;; FIXME: race condition. might need WITHOUT-INTERRUPTS on some impl.s
420 (setf (%sys-errno
) 0)
421 (let ((r (foreign-funcall "nice" :int increment
:int
)))
422 (if (and (= r -
1) (/= (%sys-errno
) 0))
423 (signal-posix-error r
)
427 ;;;-------------------------------------------------------------------------
429 ;;;-------------------------------------------------------------------------
431 (defsyscall* ("usleep" %sys-usleep
) :int
432 (useconds useconds-t
))
434 (defsyscall ("time" %%sys-time
) time-t
437 (defentrypoint %sys-time
()
438 (%%sys-time
(null-pointer)))
440 (defsyscall ("gettimeofday" %%sys-gettimeofday
) :int
444 (defentrypoint %sys-gettimeofday
()
445 "Return the time in seconds and microseconds."
446 (with-foreign-object (tv 'timeval
)
447 (with-foreign-slots ((sec usec
) tv timeval
)
448 (%%sys-gettimeofday tv
(null-pointer))
451 ;;; FIXME: or we can implement this through the MACH functions.
454 (defctype kern-return-t
:int
)
455 (defctype clock-res-t
:int
)
456 (defctype clock-id-t
:int
)
457 (defctype port-t
:unsigned-int
) ; not sure
458 (defctype clock-serv-t port
)
460 (defconstant kern-success
0)
462 (defconstant system-clock
0)
463 (defconstant calendar-clock
1)
464 (defconstant realtime-clock
0)
466 (defsyscall ("mach_host_self" %sys-mach-host-self
) port-t
)
468 (defsyscall ("host_get_clock_service" %%sys-host-get-clock-service
) kern-return-t
471 (clock-name (:pointer clock-serv-t
)))
473 (defentrypoint %sys-host-get-clock-service
(id &optional
(host (%sys-mach-host-self
)))
474 (with-foreign-object (clock 'clock-serv-t
)
475 (%%sys-host-get-clock-service host id clock
)
476 (mem-ref clock
:int
)))
478 (defsyscall ("clock_get_time" %clock-get-time
) kern-return-t
479 (clock-serv clock-serv-t
)
482 (defentrypoint clock-get-time
(clock-service)
483 (with-foreign-object (time 'timespec
)
484 (%clock-get-time clock-service time
)
485 (with-foreign-slots ((tv-sec tv-nsec
) time timespec
)
486 (values tv-sec tv-nsec
)))))
490 (defsyscall ("clock_getres" %%sys-clock-getres
) :int
491 "Returns the resolution of the clock CLOCKID."
495 (defentrypoint %sys-clock-getres
(clock-id)
496 (with-foreign-object (ts 'timespec
)
497 (with-foreign-slots ((sec nsec
) ts timespec
)
498 (%%sys-clock-getres clock-id ts
)
501 (defsyscall ("clock_gettime" %%sys-clock-gettime
) :int
505 (defentrypoint %sys-clock-gettime
(clock-id)
506 "Returns the time of the clock CLOCKID."
507 (with-foreign-object (ts 'timespec
)
508 (with-foreign-slots ((sec nsec
) ts timespec
)
509 (%%sys-clock-gettime clock-id ts
)
512 (defsyscall ("clock_settime" %%sys-clock-settime
) :int
516 (defentrypoint %sys-clock-settime
(clock-id)
517 "Sets the time of the clock CLOCKID."
518 (with-foreign-object (ts 'timespec
)
519 (with-foreign-slots ((sec nsec
) ts timespec
)
520 (%%sys-clock-settime clock-id ts
)
521 (values sec nsec
)))))
523 (defentrypoint %sys-get-monotonic-time
()
524 "Gets current time in seconds from a system's monotonic clock."
525 (multiple-value-bind (seconds nanoseconds
)
526 #-darwin
(%sys-clock-gettime clock-monotonic
)
527 #+darwin
(%sys-clock-get-time
(%sys-host-get-clock-service system-clock
))
528 (+ seconds
(/ nanoseconds
1d9
))))
531 ;;;-------------------------------------------------------------------------
533 ;;;-------------------------------------------------------------------------
535 (defcvar ("environ" :read-only t
) (:pointer
:string
))
537 (defsyscall ("getenv" %sys-getenv
) :string
538 "Returns the value of an environment variable"
541 (defsyscall ("setenv" %sys-setenv
) :int
542 "Changes the value of an environment variable"
545 (overwrite bool-designator
))
547 (defsyscall ("unsetenv" %sys-unsetenv
) :int
548 "Removes the binding of an environment variable"
552 ;;;-------------------------------------------------------------------------
554 ;;;-------------------------------------------------------------------------
556 (defsyscall ("gethostname" %%sys-gethostname
) :int
560 (defentrypoint %sys-gethostname
()
561 (with-foreign-pointer-as-string ((cstr size
) 256)
562 (%%sys-gethostname cstr size
)))
564 (defsyscall ("getdomainname" %%sys-getdomainname
) :int
568 (defentrypoint %sys-getdomainname
()
569 (with-foreign-pointer-as-string ((cstr size
) 256)
570 (%%sys-getdomainname cstr size
)))