1 (define-module (language python module os
)
2 #:use-module
(system foreign
)
3 #:use-module
(oop pf-objects
)
4 #:use-module
(oop goops
)
5 #:use-module
(rnrs bytevectors
)
6 #:use-module
(language python for
)
7 #:use-module
((language python module python
) #:select
(open))
8 #:use-module
(language python try
)
9 #:use-module
(language python exceptions
)
10 #:use-module
(language python yield
)
11 #:use-module
(language python string
)
12 #:use-module
(language python bytes
)
13 #:use-module
(language python list
)
14 #:export
(error name ctermid environ environb chdir fchdir getcwd
15 fsencode fdencode fspath PathLike getenv getenvb
16 get_exec_path getgid getegid geteuid
17 getgroups getgrouplist getlogin getpgid getpgrp getpid
18 getppid PRIO_PROCESS PRIO_PRGRP PRIO_USER getpriority
19 getresgid getuid initgroups putenv setegid seteuid
20 setgid setgroups setpgrp setpgid setpriority setregid
21 setresgid setreuid setresuid getsid setsid setuid strerr
24 dopen close closerange device_encoding dup dup2 fchmod fchown
25 fdatasync fpathconf fstat fstatvfs fsynch ftruncate isatty
26 F_LOCK F_TLOCK F_ULOCK F_TEST lockf
27 SEEK_SET SEEK_CUR SEEK_END SEEK_DATA SEEK_HOLE lseek
28 open O_RDONLY O_WRONLY O_RDWR O_APPEND O_CREAT O_EXCL
29 O_TRUNC O_SYNC O_NDELAY O_NONBLOCK O_NOCTTY O_LARGEFILE
30 O_NOTRANS O_DSYNC O_RSYNC O_CLOEXEC O_PATH O_DIRECTORY
31 O_NOFOLLOW O_DIRECT O_NOATIME O_ASYNC O_TMPFILE
32 openpty pipe pipe2 posix_fallocate
33 posix_fadvise POSIX_FADV_NORMAL POSIX_FADV_RANDOM
34 POSIX_FADV_SEQUENTIAL POSIX_FADV_WILLNEED
35 POSIX_FADV_DONTNEED POSIX_FADV_NOREUSE
36 pread pwrite read sendfile set_blocking get_blocking
37 set_blocking readv write writev set_inheritable
41 (define error
'OSError
)
43 (define-syntax-rule (aif it p x y
) (let ((it p
)) (if it x y
)))
44 (define-syntax-rule (ca code
)
47 (lambda x
(raise error x
))))
48 (define-syntax-rule (rm code
)
56 ((_ (x ...
) code
) (guile (x ...
) code code
))
57 ((_ (x ...
) code1 code2
)
58 (define code1
(lambda (x ...
) (ca ((@ (guile) code2 x ...
))))))
59 ((_ code
) (guile code code
))
61 (define code1
(lambda x
(ca (apply (@ (guile) code2 x
))))))))
66 (define-values (environ environb
)
68 (define e
(dereference-pointer (dynamic-pointer "environ" (dynamic-link))))
71 (let ((*e
(dereference-pointer e
)))
72 (if (null-pointer?
*e
)
76 (lp (make-pointer (+ (pointer-address e
) 8))))))))
79 (let lp
((es (get-envs)))
81 (let ((x (string-split (car es
) #\
=)))
83 (v (string-join (cdr x
) "=")))
84 (cons (cons k v
) (lp (cdr es
)))))
87 (define-python-class Env
()
89 (lambda (self) (values)))
93 (let ((r ((@ (guile) getenv
) (slot-ref (pystring k
) 'str
))))
94 (if r r
(raise IndexError
)))))
98 (putenv (slot-ref (pystring (+ k
"=" v
)) 'str
))))
102 (putenv (slot-ref (pystring k
) 'str
))))
108 (for ((x : (getkw))) ()
109 (yield (car x
) (cdr x
)))))))))
111 (define-python-class Envb
()
113 (lambda (self) (values)))
117 (let ((r (bytes ((@ (guile) getenv
) (slot-ref (string k
) 'str
)))))
118 (if r r
(raise IndexError
)))))
122 (putenv (slot-ref (string (+ k
"=" v
)) 'str
))))
126 (putenv (slot-ref (string k
) 'str
))))
132 (for ((x : (getkw))) ()
133 (yield (car x
) (cdr x
)))))))))
136 (values (Env) (Envb))))
142 (error "not implemented"))
146 (define (fsencode fn
)
147 (error "not implemented"))
148 (define (fsdecode fn
)
149 (error "not implemented"))
151 (define-method (fspath (pth <string
> )) pth
)
152 (define-method (fspath (pth <py-string
> )) pth
)
153 (define-method (fspath (pth <py-bytes
> )) pth
)
154 (define-method (fspath (pth <py-bytearray
>)) pth
)
155 (define-method (fspath (pth <p
> ))
156 (aif it
(ref pth
'__fspath__
)
160 (define-python-class PathLike
()
162 (lambda (self) (error "not implemented"))))
165 (define* (getenv key
#:key
(default None
))
168 (pylist-ref environ key
))
169 (#:except IndexError
=> (lambda x default
))))
171 (define* (getenvb key
#:key
(default None
))
174 (pylist-ref environb key
))
175 (#:except IndexError
=> (lambda x default
))))
177 (define* (get_exec_path #:key
(env #f
))
179 (let ((s (slot-ref (string s
) 'str
)))
180 (string-split str
":")))
182 (f (pylist-ref env
"PATH"))
183 (f (pylist-ref environ
"PATH"))))
189 (define (getgrouplist user group
)
190 (error "not impllemeneted"))
197 (let ((f (pointer->procedure int
198 (dynamic-func "getpgid" (dynamic-link))
208 (define PRIO_PROCESS
(@ (guile) PRIO_PROCESS
))
209 (define PRIO_PRGRP
(@ (guile) PRIO_PRGRP
))
210 (define PRIO_USER
(@ (guile) PRIO_USER
))
215 (let* ((f (pointer->procedure
217 (dynamic-func "getresgid" (dynamic-link))
221 (let* ((a (make-bytevector 8))
222 (ap (bytevector->pointer a
))
223 (b (make-bytevector 8))
224 (bp (bytevector->pointer b
))
225 (c (make-bytevector 8))
226 (cp (bytevector->pointer c
)))
229 (bytevector-u16-ref a
0 (native-endianness))
230 (bytevector-u16-ref b
0 (native-endianness))
231 (bytevector-u16-ref c
0 (native-endianness)))))))
236 (let ((f (pointer->procedure
238 (dynamic-func "initgroups" (dynamic-link))
242 (rm (string->pointer user
) group
))))
244 (define (putenv key value
)
245 (pylist-set! environ key value
))
253 (let ((f (pointer->procedure
'int
254 (dynamic-func "setpgrp" (dynamic-link))
263 (let ((f (pointer->procedure
'int
264 (dynamic-func "setregid" (dynamic-link))
270 (let ((f (pointer->procedure
'int
271 (dynamic-func "setresgid" (dynamic-link))
277 (let ((f (pointer->procedure
'int
278 (dynamic-func "setreuid" (dynamic-link))
284 (let ((f (pointer->procedure
'int
285 (dynamic-func "setresuid" (dynamic-link))
298 ;; File descriptor operations
305 (define (closerange fd_low fd_high
)
306 (for ((i : (range low high
))) ()
308 (lambda () (close i
))
309 (#:except OSError
=> (lambda (x) (values))))))
311 (define device_encoding
(lambda (fd) (error "not implemented")))
316 (let ((f (pointer->procedure
'int
317 (dynamic-func "dup3" (dynamic-link))
319 (lambda* (fd fd2
#:optional
(inheritable?
#t
))
321 (rm (f fd fd2 O_CLOEXEC
))
322 (ca ((@ (guile) dup2
) fd fd2
))))))
324 (guile (fd mode
) fchmod
)
325 (guile (fd uid gid
) fchown
)
328 (define (fdatasync fd
) (error "not implemented"))
329 (define (fpathconf fd name
) (error "not implemented"))
331 (define (concat a ... stx
)
338 (syntax->datum stx
))))))
340 (define-syntax statset
343 ((_ (m ...
) self scm
)
345 (statset m self scm
) ...
))
347 (with-syntax ((mem (concat "st_" #'m
))
348 (smem (concat "stat;" #'m
)))
349 #'(set self
'mem
(smem scm
)))))))
351 (define-python-class stat_result
()
355 (statset (mode ino dev nlink uid gid size atime mtime ctime
)
357 (name-object stat_result
)
360 (stat_result (stat fd
)))
362 (define (fstatvfs fd
) (error "not implemented"))
364 (guile (fd) fsynch fsync
)
366 (guil (fd len
) ftruncate truncate-file
)
368 (guile (fd) isatty isatty?
)
375 (let ((f (pointer->procedure
'int
376 (dynamic-func "lockf" (dynamic-link))
379 (rm (f fd op len
)))))
383 (define SEEK_SET
#x0
)
384 (define SEEK_CUR
#x1
)
385 (define SEEK_END
#x2
)
386 (define SEEK_DATA
#x3
)
387 (define SEEK_HOLE
#x4
)
390 (let ((f (pointer->procedure
'int
391 (dynamic-func "lseek" (dynamic-link))
394 (rm (f fd pos how
)))))
397 (let ((f (pointer->procedure
'int
398 (dynamic-func "openat" (dynamic-link))
401 (lambda* (path flags mode
#:optional
(dir_fd None
))
402 (if (eq? dir_fd None
)
403 (ca (open-fdes path flags mode
))
404 (rm (f dir_fd
(string->pointer path
) flags mode
))))))
407 (define-syntax-rule (mko O
) (define O
(@ (guile) O
)))
426 (define O_DSYNC
#o10000
)
427 (define O_RSYNC O_SYNC
)
428 (define O_CLOEXEC
#o2000000
)
429 (define O_PATH
#o10000000
)
430 (define O_DIRECTORY
#o200000
)
431 (define O_NOFOLLOW
#o400000
)
432 (define O_DIRECT
#o40000
)
433 (define O_NOATIME
#o1000000
)
434 (define O_ASYNC
#o20000
)
435 (define O_TMPFILE
(logior #o20000000 O_DIRECTORY
))
437 (define openpty
(lambda x
(error "not implemented")))
440 (let ((x (ca (@ (guile) pipe
))))
441 (values (car x
) (cdr x
))))
444 (let ((f (pointer->procedure
'int
445 (dynamic-func "pipe2" (dynamic-link))
448 (let* ((a (make-bytevector 16))
449 (ap (bytevector->pointer a
)))
451 (values (bytevector-s32-ref a
0)
452 (bytevector-s32-ref a
1))))))
455 (define posix_fallocate
456 (let ((f (pointer->procedure
'int
457 (dynamic-func "posix_fallocate" (dynamic-link))
460 (rm (f fd off len
)))))
462 (define posix_fadvise
463 (let ((f (pointer->procedure
'int
464 (dynamic-func "posix_fadvise" (dynamic-link))
465 '(int long long int
))))
466 (lambda (fd off len advice
)
467 (rm (f fd off len advice
)))))
469 (define POSIX_FADV_NORMAL
0)
470 (define POSIX_FADV_RANDOM
1)
471 (define POSIX_FADV_SEQUENTIAL
2)
472 (define POSIX_FADV_WILLNEED
3)
473 (define POSIX_FADV_DONTNEED
4)
474 (define POSIX_FADV_NOREUSE
5)
477 (let ((f (pointer->procedure
'int
478 (dynamic-func "pread" (dynamic-link))
479 '(int * long long
))))
480 (lambda (fd size offset
)
481 (let* ((a (make-bytevector size
))
482 (ap (bytevector->pointer a
)))
483 (let ((n (rm (f fd ap size offset
))))
486 (let ((o (make <bytevector
>)))
487 (slot-set! o
'n
(size))
488 (slot-set! o
'size n
)
493 (let ((f (pointer->procedure
'int
494 (dynamic-func "pwrite" (dynamic-link))
495 '(int * long long
))))
497 (lambda (fd a offset
)
498 (let* ((ap (bytevector->pointer a
)))
499 (rm (f fd ap size offset
))))))
502 (let ((f (pointer->procedure
'int
503 (dynamic-func "read" (dynamic-link))
506 (let* ((a (make-bytevector size
))
507 (ap (bytevector->pointer a
)))
508 (let ((n (rm (f fd ap size
))))
511 (let ((o (make <bytevector
>)))
512 (slot-set! o
'n
(size))
513 (slot-set! o
'size n
)
517 (define (sendfile out in offset count
)
520 ((@ (guile) sendfile out in count
))
521 ((@ (guile) sendfile out in count offset
)))))
524 (define fcntl2
(pointer->procedure
'int
525 (dynamic-func "fcntl" (dynamic-link))
527 (define fcntl3
(pointer->procedure
'int
528 (dynamic-func "fcntl" (dynamic-link))
531 (define (set_blocking fd is-blocking?
)
532 (let ((o (rm (fcntl2 fd F_GETFL
))))
534 (rm (fcntl3 fd F_GETFL
(logior o O_NONBLOCK
)))
535 (rm (fcntl3 fd F_GETFL
(logand o
(lognot O_NONBLOCK
)))))))
537 (define (get_blocking fd
)
538 (if (= (logand O_NONBLOCK
(rm (fcntl2 fd F_GETFL
))) 0)
542 (define (readv fd buffers
) (error "not implemented"))
544 (guile (fd pg
) tcsetpgrp
)
548 (let ((f (pointer->procedure
'int
549 (dynamic-func "write" (dynamic-link))
553 (let* ((ap (bytevector->pointer a
)))
554 (rm (f fd ap size
))))))
556 (define (writev fd buffers
) (error "not implemented"))
559 (define (set_inheritable fd is-inh?
)
560 (let ((o (rm (fcntl2 fd F_GETFL
))))
562 (rm (fcntl3 fd F_GETFL
(logior o O_CLOEXEC
)))
563 (rm (fcntl3 fd F_GETFL
(logand o
(lognot O_CLOEXEC
)))))))
565 (define (get_inheritable fd
)
566 (if (= (logand O_CLOEXEC
(rm (fcntl2 fd F_GETFL
))) 0)
572 (define AT_EACCESS
#x200
)
573 (define AT_SYMLINK_NOFOLLOW
#x100
)
575 (define F_OK
(@ (guile) F_OK
))
576 (define W_OK
(@ (guile) W_OK
))
577 (define R_OK
(@ (guile) R_OK
))
578 (define X_OK
(@ (guile) X_OK
))
581 (let ((f (pointer->procedure
'int
582 (dynamic-func "access" (dynamic-link))
584 (fa (pointer->procedure
'int
585 (dynamic-func "faccessat" (dynamic-link))
588 (lambda* (path mode
#:key
591 (follow_symlinks #t
))
592 (if (eq? dir_fd None
)
593 (rm (f (string->pointer path
) mode
))
594 (rm (fa (string->pointer path
) mode dir_fd
595 (logior (if effective_ids AT_EACCESS
0)
596 (if follow_symlinks
0 AT_SYMLINK_NOFOLLOW
))))))))
601 (let ((f (pointer->procedure
'int
602 (dynamic-func "access" (dynamic-link))
605 (let ((pth (aif it
(ref pth
'__fspath__
)
610 (ca ((@ (guile) chdir
) pth
)))))))
614 (lambda x
(error "Not implemented")))
617 (let ((f (pointer->procedure
'int
618 (dynamic-func "chmod" (dynamic-link))
620 (ff (pointer->procedure
'int
621 (dynamic-func "fchmod" (dynamic-link))
623 (fat (pointer->procedure
'int
624 (dynamic-func "fchmodat" (dynamic-link))
626 (lambda* (path mode
#:key
(dir_fd None
) (follow_symlinks #t
))
629 (let ((path (aif it
(ref path
'__fspath__
)
632 (if (eq? dir_fd None
)
633 (rm (f (string->pointer path
) mode
))
634 (rm (fat (string->pointer path
) mode
638 AT_SYMLINK_NOFOLLOW
)))))))))
642 (define (path-it path
)
643 (aif it
(ref path
'__fspath__
)
648 (let ((f (pointer->procedure
'int
649 (dynamic-func "chown" (dynamic-link))
651 (ff (pointer->procedure
'int
652 (dynamic-func "fchown" (dynamic-link))
654 (lf (pointer->procedure
'int
655 (dynamic-func "lchow" (dynamic-link))
657 (fat (pointer->procedure
'int
658 (dynamic-func "fchownat" (dynamic-link))
659 '(* int int int int
))))
660 (lambda* (path uid gid
#:key
(dir_fd None
) (follow_symlinks #t
))
662 (rm (ff path uid gid
))
663 (let ((path (path-it path
)))
664 (if (eq? dir_fd None
)
666 (rm (f (string->pointer path
) uid gid
))
667 (rm (lf (string->pointer path
) uid gid
)))
668 (rm (fat (string->pointer path
) uid gid dir_fd
671 AT_SYMLINK_NOFOLLOW
)))))))))
675 (define fchdir chdir
)
682 (define lchflags
(lambda x
(error "not implemented")))
684 (define (lchmod path mode
)
685 (chmod path mode
#:follow_symlinks
#f
))
687 (define (lchown path uid gid
)
688 (chown path uid gid
#:follow_symlinks
#f
))
691 (let ((f (pointer->procedure
'int
692 (dynamic-func "linkat" (dynamic-link))
693 '(* * int int int
))))
694 (lambda* (src dst
#:key
697 (follow_symlinks #t
))
698 (let ((src (path-it src
))
700 (src_dir_fd (if (eq? src_dir_fd None
) AT_FDCWD src_dir_fd
))
701 (dst_dir_fd (if (eq? dst_dir_fd None
) AT_FDCWD dst_dir_fd
)))
702 (rm (f (string->pointer src
)
703 (string->pointer dst
)
708 AT_SYMLINK_NOFOLLOW
)))))))
711 (lambda* (#:optional
(pth "."))
712 (let ((pth (if (number? pth
)
713 (read-link (format #f
"/proc/self/fd/~a" pth
))
715 (let ((o (ca (opendir pth
))))
719 (let lp
((o ) (l '()))
720 (let ((w (ca (readdir o
))))
724 (lambda x
(closedir o
)))))))
727 (let ((f (pointer->procedure
'int
728 (dynamic-func "fstatat" (dynamic-link))
730 (g (pointer->procedure
'*
731 (dynamic-func "scm_stat2scm_" (dynamic-link))
733 (lambda* (path #:key
(dir_fd None
) (follow_symlinks #t
))
735 (stat_result ((@ (guile) stat
) path
))
736 (let ((path (get-path path
)))
737 (if (eq? dir_fd None
)
739 (stat_result ((@ (guile) stat
) path
))
740 (stat_result ((@ (guile) lstat
) path
)))
741 (let ((bv (make-bytevector 80))
742 (bvp (bytevector->pointer bv
)))
744 (string->pointer path
)
748 AT_SYMLINK_NOFOLLOW
)))
749 (stat_result (ca (pointer->scm
(g bvp
)))))))))))
752 (lambda* (path #:key
(dir_fd None
))
753 (stat path
#:dir_fd dir_fd
#:follow_symlinks
#f
)))