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-without-arg
) :int
265 (defsyscall* ("ioctl" %%sys-ioctl-with-arg
) :int
270 (defentrypoint %sys-ioctl
(fd request
&optional
(arg nil argp
))
273 ((not argp
) (%%sys-ioctl-without-arg fd request
))
274 ((pointerp arg
) (%%sys-ioctl-with-arg fd request arg
))
275 (t (error "Wrong argument to ioctl: ~S" arg
))))
277 (defentrypoint %sys-fd-open-p
(fd)
278 (not (minusp (%sys-fstat fd
))))
281 ;;;-----------------------------------------------------------------------------
282 ;;; File descriptor polling
283 ;;;-----------------------------------------------------------------------------
285 ;;; FIXME: Until a way to autodetect platform features is implemented
286 #+(or darwin freebsd
)
287 (define-constant pollrdhup
0)
289 (defsyscall ("poll" %sys-poll
) :int
290 "Scan for I/O activity on multiple file descriptors."
296 ;;;-----------------------------------------------------------------------------
298 ;;;-----------------------------------------------------------------------------
300 (defsyscall ("munmap" %sys-munmap
) :int
301 "Unmap pages of memory."
306 ;;;-----------------------------------------------------------------------------
308 ;;;-----------------------------------------------------------------------------
310 (defsyscall* ("usleep" %sys-usleep
) :int
311 (useconds useconds-t
))
313 (defsyscall ("time" %%sys-time
) time-t
316 (defentrypoint %sys-time
()
317 (%%sys-time
(null-pointer)))
319 (defsyscall ("gettimeofday" %%sys-gettimeofday
) :int
323 (defentrypoint %sys-gettimeofday
()
324 "Return the time in seconds and microseconds."
325 (with-foreign-object (tv 'timeval
)
326 (with-foreign-slots ((sec usec
) tv timeval
)
327 (%%sys-gettimeofday tv
(null-pointer))
330 ;;; FIXME: or we can implement this through the MACH functions.
333 (defctype kern-return-t
:int
)
334 (defctype clock-res-t
:int
)
335 (defctype clock-id-t
:int
)
336 (defctype port-t
:unsigned-int
) ; not sure
337 (defctype clock-serv-t port
)
339 (defconstant kern-success
0)
341 (defconstant system-clock
0)
342 (defconstant calendar-clock
1)
343 (defconstant realtime-clock
0)
345 (defsyscall ("mach_host_self" %sys-mach-host-self
) port-t
)
347 (defsyscall ("host_get_clock_service" %%sys-host-get-clock-service
) kern-return-t
350 (clock-name (:pointer clock-serv-t
)))
352 (defentrypoint %sys-host-get-clock-service
(id &optional
(host (%sys-mach-host-self
)))
353 (with-foreign-object (clock 'clock-serv-t
)
354 (%%sys-host-get-clock-service host id clock
)
355 (mem-ref clock
:int
)))
357 (defsyscall ("clock_get_time" %clock-get-time
) kern-return-t
358 (clock-serv clock-serv-t
)
361 (defentrypoint clock-get-time
(clock-service)
362 (with-foreign-object (time 'timespec
)
363 (%clock-get-time clock-service time
)
364 (with-foreign-slots ((tv-sec tv-nsec
) time timespec
)
365 (values tv-sec tv-nsec
)))))
369 (defsyscall ("clock_getres" %%sys-clock-getres
) :int
370 "Returns the resolution of the clock CLOCKID."
374 (defentrypoint %sys-clock-getres
(clock-id)
375 (with-foreign-object (ts 'timespec
)
376 (with-foreign-slots ((sec nsec
) ts timespec
)
377 (%%sys-clock-getres clock-id ts
)
380 (defsyscall ("clock_gettime" %%sys-clock-gettime
) :int
384 (defentrypoint %sys-clock-gettime
(clock-id)
385 "Returns the time of the clock CLOCKID."
386 (with-foreign-object (ts 'timespec
)
387 (with-foreign-slots ((sec nsec
) ts timespec
)
388 (%%sys-clock-gettime clock-id ts
)
391 (defsyscall ("clock_settime" %%sys-clock-settime
) :int
395 (defentrypoint %sys-clock-settime
(clock-id)
396 "Sets the time of the clock CLOCKID."
397 (with-foreign-object (ts 'timespec
)
398 (with-foreign-slots ((sec nsec
) ts timespec
)
399 (%%sys-clock-settime clock-id ts
)
400 (values sec nsec
)))))
402 (defentrypoint %sys-get-monotonic-time
()
403 "Gets current time in seconds from a system's monotonic clock."
404 (multiple-value-bind (seconds nanoseconds
)
405 #-darwin
(%sys-clock-gettime clock-monotonic
)
406 #+darwin
(%sys-clock-get-time
(%sys-host-get-clock-service system-clock
))
407 (+ seconds
(/ nanoseconds
1d9
))))
410 ;;;-----------------------------------------------------------------------------
412 ;;;-----------------------------------------------------------------------------
414 (defcvar ("environ" :read-only t
) (:pointer
:string
))
416 (defsyscall ("getenv" %sys-getenv
) :string
417 "Returns the value of an environment variable"
420 (defsyscall ("setenv" %sys-setenv
) :int
421 "Changes the value of an environment variable"
424 (overwrite bool-designator
))
426 (defsyscall ("unsetenv" %sys-unsetenv
) :int
427 "Removes the binding of an environment variable"
431 ;;;-----------------------------------------------------------------------------
433 ;;;-----------------------------------------------------------------------------
435 (defsyscall ("gethostname" %%sys-gethostname
) :int
439 (defentrypoint %sys-gethostname
()
440 (with-foreign-pointer-as-string ((cstr size
) 256)
441 (%%sys-gethostname cstr size
)))
443 (defsyscall ("getdomainname" %%sys-getdomainname
) :int
447 (defentrypoint %sys-getdomainname
()
448 (with-foreign-pointer-as-string ((cstr size
) 256)
449 (%%sys-getdomainname cstr size
)))