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 %sys-strerror
(&optional
(err (get-errno)))
17 "Look up the error message string for ERRNO. (reentrant)"
20 (foreign-enum-value 'errno-values err
)
22 (with-foreign-pointer-as-string ((buf bufsiz
) 1024)
23 (%sys-strerror-r errno buf bufsiz
))))
25 (defmethod print-object ((posix-error posix-error
) stream
)
26 (print-unreadable-object (posix-error stream
:type nil
:identity nil
)
27 (let ((code (code-of posix-error
))
28 (identifier (identifier-of posix-error
)))
29 (format stream
"POSIX Error ~A code: ~S ~S"
30 identifier
(or code
"[No code]")
31 (or (%sys-strerror code
) "[Can't get error string.]")))))
34 ;;;-----------------------------------------------------------------------------
35 ;;; Memory manipulation
36 ;;;-----------------------------------------------------------------------------
38 (defcfun* ("memset" %sys-memset
) :pointer
43 (defentrypoint %sys-bzero
(buffer length
)
44 (%sys-memset buffer
0 length
))
46 (defcfun* ("memcpy" %sys-memcpy
) :pointer
51 (defcfun* ("memmove" %sys-memmove
) :pointer
57 ;;;-----------------------------------------------------------------------------
59 ;;;-----------------------------------------------------------------------------
61 (defsyscall* ("read" %sys-read
) ssize-t
62 "Read at most COUNT bytes from FD into the foreign area BUF."
67 (defsyscall* ("write" %sys-write
) ssize-t
68 "Write at most COUNT bytes to FD from the foreign area BUF."
74 ;;;-----------------------------------------------------------------------------
76 ;;;-----------------------------------------------------------------------------
78 (defsyscall* ("open" %%sys-open
) :int
79 (pathname filename-designator
)
83 (defvar *default-open-mode
* #o666
)
85 (defentrypoint %sys-open
(pathname flags
&optional
(mode *default-open-mode
*))
86 (%%sys-open pathname flags mode
))
88 (defsyscall* ("creat" %sys-creat
) :int
89 (pathname filename-designator
)
92 (defsyscall ("pipe" %%sys-pipe
) :int
95 (defentrypoint %sys-pipe
()
96 "Create pipe, returns two values with the new FDs."
97 (with-foreign-object (filedes :int
2)
99 (values (mem-aref filedes
:int
0)
100 (mem-aref filedes
:int
1))))
102 (defsyscall ("mkfifo" %sys-mkfifo
) :int
103 "Create a FIFO (named pipe)."
104 (path filename-designator
)
107 (defsyscall "umask" mode-t
108 "Sets the umask and returns the old one"
111 (defsyscall ("access" %sys-access
) :int
112 (path filename-designator
)
115 (defsyscall ("rename" %sys-rename
) :int
117 (old filename-designator
)
118 (new filename-designator
))
120 (defsyscall ("link" %sys-link
) :int
121 (path1 filename-designator
)
122 (path2 filename-designator
))
124 (defsyscall ("symlink" %sys-symlink
) :int
125 "Creates a symbolic link"
126 (name1 filename-designator
)
127 (name2 filename-designator
))
129 (defsyscall ("readlink" %%sys-readlink
) ssize-t
130 (path filename-designator
)
134 (defentrypoint %sys-readlink
(path)
135 "Read value of a symbolic link."
136 (with-foreign-pointer (buf 4096 bufsize
)
137 (let ((count (%%sys-readlink path buf bufsize
)))
138 (values (foreign-string-to-lisp buf
:count count
)))))
140 (defsyscall ("unlink" %sys-unlink
) :int
141 (path filename-designator
))
143 (defsyscall* ("chown" %sys-chown
) :int
144 "Change ownership of a file."
145 (path filename-designator
)
149 (defsyscall* ("fchown" %sys-fchown
) :int
150 "Change ownership of an open file."
155 (defsyscall* ("lchown" %sys-lchown
) :int
156 "Change ownership of a file or symlink."
157 (path filename-designator
)
161 (defsyscall* ("chmod" %sys-chmod
) :int
162 (path filename-designator
)
165 (defsyscall* ("fchmod" %sys-fchmod
) :int
171 (define-c-struct-wrapper stat
())
173 (defconstant +stat-version-linux
+ 3)
175 ;;; If necessary for performance reasons, we can add an optional
176 ;;; argument to this function and use that to reuse a wrapper object.
177 (defentrypoint funcall-stat
(fn arg
)
178 (with-foreign-object (buf 'stat
)
180 (make-instance 'stat
:pointer buf
)))
182 (defentrypoint %sys-stat
(path)
183 "Get information about a file."
184 (funcall-stat #'%%sys-stat path
))
186 (defentrypoint %sys-fstat
(fd)
187 "Get information about a file descriptor"
188 (funcall-stat #'%%sys-fstat fd
))
190 (defentrypoint %sys-lstat
(path)
191 "Get information about a file or symlink."
192 (funcall-stat #'%%sys-lstat path
))
194 (defsyscall ("sync" %sys-sync
) :void
195 "Schedule all file system buffers to be written to disk.")
197 (defsyscall* ("fsync" %sys-fsync
) :int
200 (defsyscall ("mkstemp" %%sys-mkstemp
) :int
201 (template filename-designator
))
203 (defentrypoint %sys-mkstemp
(&optional
(template ""))
204 (let ((template (concatenate 'string template
"XXXXXX")))
205 (with-foreign-string (ptr (filename template
))
206 (values (%%sys-mkstemp ptr
) (foreign-string-to-lisp ptr
)))))
209 ;;;-----------------------------------------------------------------------------
211 ;;;-----------------------------------------------------------------------------
213 (defsyscall "mkdir" :int
214 "Create a directory."
215 (path filename-designator
)
218 (defsyscall ("rmdir" %sys-rmdir
) :int
219 (path filename-designator
))
221 (defsyscall ("chdir" %sys-chdir
) :int
222 "Changes the current working directory"
223 (path filename-designator
))
225 (defsyscall* ("fchdir" %sys-fchdir
) :int
228 (defsyscall ("getcwd" %%sys-getcwd
) :string
232 (defentrypoint %sys-getcwd
()
233 "Returns the current working directory as a string."
234 (with-foreign-pointer (buf path-max size
)
237 (defsyscall ("mkdtemp" %%sys-mkdtemp
) :int
238 (template filename-designator
))
240 (defentrypoint %sys-mkdtemp
(&optional
(template ""))
241 (let ((template (concatenate 'string template
"XXXXXX")))
242 (with-foreign-string (ptr (filename template
))
243 (values (%%sys-mkdtemp ptr
) (foreign-string-to-lisp ptr
)))))
246 ;;;-----------------------------------------------------------------------------
248 ;;;-----------------------------------------------------------------------------
250 (defsyscall ("close" %sys-close
) :int
251 "Close an open file descriptor."
254 (defsyscall ("dup" %sys-dup
) :int
257 (defsyscall* ("dup2" %sys-dup2
) :int
261 (defsyscall* ("ioctl" %sys-ioctl
/2) :int
265 (defsyscall* ("ioctl" %sys-ioctl
/3) :int
270 (defentrypoint %sys-fd-open-p
(fd)
271 (not (minusp (%sys-fstat fd
))))
274 ;;;-----------------------------------------------------------------------------
275 ;;; File descriptor polling
276 ;;;-----------------------------------------------------------------------------
278 ;;; FIXME: Until a way to autodetect platform features is implemented
279 #+(or darwin freebsd
)
280 (define-constant pollrdhup
0)
282 (defsyscall ("poll" %sys-poll
) :int
283 "Scan for I/O activity on multiple file descriptors."
289 ;;;-----------------------------------------------------------------------------
291 ;;;-----------------------------------------------------------------------------
293 (defsyscall ("munmap" %sys-munmap
) :int
294 "Unmap pages of memory."
299 ;;;-----------------------------------------------------------------------------
301 ;;;-----------------------------------------------------------------------------
303 (defsyscall* ("usleep" %sys-usleep
) :int
304 (useconds useconds-t
))
306 (defsyscall ("time" %%sys-time
) time-t
309 (defentrypoint %sys-time
()
310 (%%sys-time
(null-pointer)))
312 (defsyscall ("gettimeofday" %%sys-gettimeofday
) :int
316 (defentrypoint %sys-gettimeofday
()
317 "Return the time in seconds and microseconds."
318 (with-foreign-object (tv 'timeval
)
319 (with-foreign-slots ((sec usec
) tv timeval
)
320 (%%sys-gettimeofday tv
(null-pointer))
323 ;;; FIXME: or we can implement this through the MACH functions.
326 (defctype kern-return-t
:int
)
327 (defctype clock-res-t
:int
)
328 (defctype clock-id-t
:int
)
329 (defctype port-t
:unsigned-int
) ; not sure
330 (defctype clock-serv-t port
)
332 (defconstant kern-success
0)
334 (defconstant system-clock
0)
335 (defconstant calendar-clock
1)
336 (defconstant realtime-clock
0)
338 (defsyscall ("mach_host_self" %sys-mach-host-self
) port-t
)
340 (defsyscall ("host_get_clock_service" %%sys-host-get-clock-service
) kern-return-t
343 (clock-name (:pointer clock-serv-t
)))
345 (defentrypoint %sys-host-get-clock-service
(id &optional
(host (%sys-mach-host-self
)))
346 (with-foreign-object (clock 'clock-serv-t
)
347 (%%sys-host-get-clock-service host id clock
)
348 (mem-ref clock
:int
)))
350 (defsyscall ("clock_get_time" %clock-get-time
) kern-return-t
351 (clock-serv clock-serv-t
)
354 (defentrypoint clock-get-time
(clock-service)
355 (with-foreign-object (time 'timespec
)
356 (%clock-get-time clock-service time
)
357 (with-foreign-slots ((tv-sec tv-nsec
) time timespec
)
358 (values tv-sec tv-nsec
)))))
362 (defsyscall ("clock_getres" %%sys-clock-getres
) :int
363 "Returns the resolution of the clock CLOCKID."
367 (defentrypoint %sys-clock-getres
(clock-id)
368 (with-foreign-object (ts 'timespec
)
369 (with-foreign-slots ((sec nsec
) ts timespec
)
370 (%%sys-clock-getres clock-id ts
)
373 (defsyscall ("clock_gettime" %%sys-clock-gettime
) :int
377 (defentrypoint %sys-clock-gettime
(clock-id)
378 "Returns the time of the clock CLOCKID."
379 (with-foreign-object (ts 'timespec
)
380 (with-foreign-slots ((sec nsec
) ts timespec
)
381 (%%sys-clock-gettime clock-id ts
)
384 (defsyscall ("clock_settime" %%sys-clock-settime
) :int
388 (defentrypoint %sys-clock-settime
(clock-id)
389 "Sets the time of the clock CLOCKID."
390 (with-foreign-object (ts 'timespec
)
391 (with-foreign-slots ((sec nsec
) ts timespec
)
392 (%%sys-clock-settime clock-id ts
)
393 (values sec nsec
)))))
395 (defentrypoint %sys-get-monotonic-time
()
396 "Gets current time in seconds from a system's monotonic clock."
397 (multiple-value-bind (seconds nanoseconds
)
398 #-darwin
(%sys-clock-gettime clock-monotonic
)
399 #+darwin
(%sys-clock-get-time
(%sys-host-get-clock-service system-clock
))
400 (+ seconds
(/ nanoseconds
1d9
))))
403 ;;;-----------------------------------------------------------------------------
405 ;;;-----------------------------------------------------------------------------
407 (defcvar ("environ" :read-only t
) (:pointer
:string
))
409 (defsyscall ("getenv" %sys-getenv
) :string
410 "Returns the value of an environment variable"
413 (defsyscall ("setenv" %sys-setenv
) :int
414 "Changes the value of an environment variable"
417 (overwrite bool-designator
))
419 (defsyscall ("unsetenv" %sys-unsetenv
) :int
420 "Removes the binding of an environment variable"
424 ;;;-----------------------------------------------------------------------------
426 ;;;-----------------------------------------------------------------------------
428 (defsyscall ("gethostname" %%sys-gethostname
) :int
432 (defentrypoint %sys-gethostname
()
433 (with-foreign-pointer-as-string ((cstr size
) 256)
434 (%%sys-gethostname cstr size
)))
436 (defsyscall ("getdomainname" %%sys-getdomainname
) :int
440 (defentrypoint %sys-getdomainname
()
441 (with-foreign-pointer-as-string ((cstr size
) 256)
442 (%%sys-getdomainname cstr size
)))