X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcode%2Funix.lisp;h=0a25f7b6240ac08200ae3ebe4498119ec5823a60;hb=aa1a5c6ea31c248587d78f62943ad749ea8fbe2f;hp=7021ce4a130a27d9e45822ad5c48fa8648a09314;hpb=ad6345c0021507c8830c7c8541ed651a89792335;p=sbcl.git diff --git a/src/code/unix.lisp b/src/code/unix.lisp index 7021ce4..0a25f7b 100644 --- a/src/code/unix.lisp +++ b/src/code/unix.lisp @@ -107,18 +107,14 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." #!+win32 (progn - (defconstant espipe 29) - ;; For stat-wrapper hack (different-type or non-existing win32 fields). - (define-alien-type nlink-t short) - (define-alien-type uid-t short) - (define-alien-type gid-t short)) + (defconstant espipe 29)) ;;;; hacking the Unix environment #!-win32 (define-alien-routine ("getenv" posix-getenv) c-string "Return the \"value\" part of the environment string \"name=value\" which - corresponds to NAME, or NIL if there is none." +corresponds to NAME, or NIL if there is none." (name c-string)) ;;; from stdio.h @@ -181,6 +177,29 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." (declare (type unix-fd fd)) (void-syscall ("close" int) fd)) +;;;; stdlib.h + +;;; There are good reasons to implement some OPEN options with an +;;; mkstemp(3)-like routine, but we don't do that yet. Instead, this +;;; function is used only to make a temporary file for RUN-PROGRAM. +;;; sb_mkstemp() is a wrapper that lives in src/runtime/wrap.c. Since +;;; SUSv3 mkstemp() doesn't specify the mode of the created file and +;;; since we have to implement most of this ourselves for Windows +;;; anyway, it seems worthwhile to depart from the mkstemp() +;;; specification by taking a mode to use when creating the new file. +(defun sb-mkstemp (template-string mode) + (declare (type string template-string) + (type unix-file-mode mode)) + (let ((template-buffer (string-to-octets template-string :null-terminate t))) + (with-pinned-objects (template-buffer) + (let ((fd (alien-funcall (extern-alien "sb_mkstemp" + (function int (* char) int)) + (vector-sap template-buffer) + mode))) + (if (minusp fd) + (values nil (get-errno)) + (values fd (octets-to-string template-buffer))))))) + ;;;; timebits.h ;; A time value that is accurate to the nearest @@ -275,7 +294,7 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." #!+largefile "lseek_largefile" (function off-t int off-t int)) fd offset whence))) - (if (minusp result ) + (if (minusp result) (values nil (get-errno)) (values result 0)))) @@ -283,6 +302,10 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." ;;; It attempts to read len bytes from the device associated with fd ;;; and store them into the buffer. It returns the actual number of ;;; bytes read. + +#!-sb!fluid +(declaim (maybe-inline unix-read)) + (defun unix-read (fd buf len) (declare (type unix-fd fd) (type (unsigned-byte 32) len)) @@ -450,6 +473,20 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." (declare (ignore path)) nil) +(defun unix-realpath (path) + (declare (type unix-pathname path)) + (with-alien ((ptr (* char) + (alien-funcall (extern-alien + "sb_realpath" + (function (* char) c-string)) + path))) + (if (null-alien ptr) + (values nil (get-errno)) + (multiple-value-prog1 + (values (with-alien ((c-string c-string ptr)) c-string) + nil) + (free-alien ptr))))) + ;;; UNIX-UNLINK accepts a name and deletes the directory entry for that ;;; name and the file if this is the last link. (defun unix-unlink (name) @@ -656,26 +693,22 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." ;;; st_size is a long, not an off-t, because off-t is a 64-bit ;;; quantity on Alpha. And FIXME: "No one would want a file length ;;; longer than 32 bits anyway, right?":-| +;;; +;;; The comment about alien and 64-bit quantities has not been kept in +;;; sync with the comment now in wrap.h (formerly wrap.c), but it's +;;; not clear whether either comment is correct. -- RMK 2007-11-14. (define-alien-type nil (struct wrapped_stat - (st-dev #!-(or mips largefile) unsigned-int - #!+mips unsigned-long - #!+largefile dev-t) + (st-dev wst-dev-t) (st-ino ino-t) (st-mode mode-t) - (st-nlink nlink-t) - (st-uid uid-t) - (st-gid gid-t) - (st-rdev #!-(or mips largefile) unsigned-int - #!+mips unsigned-long - #!+largefile dev-t) - (st-size #!-(or darwin mips largefile) unsigned-int - #!+(or darwin mips largefile) off-t) - #!+(and darwin) - (st-blksize unsigned-int) - #!-(and darwin) - (st-blksize unsigned-long) - (st-blocks unsigned-long) + (st-nlink wst-nlink-t) + (st-uid wst-uid-t) + (st-gid wst-gid-t) + (st-rdev wst-dev-t) + (st-size wst-off-t) + (st-blksize wst-blksize-t) + (st-blocks wst-blkcnt-t) (st-atime time-t) (st-mtime time-t) (st-ctime time-t))) @@ -918,76 +951,7 @@ SYSCALL-FORM. Repeat evaluation of SYSCALL-FORM if it is interrupted." #!-win32 ((eql kind s-iflnk) :link) (t :special)))))) - -;;; Is the Unix pathname PATHNAME relative, instead of absolute? (E.g. -;;; "passwd" or "etc/passwd" instead of "/etc/passwd"?) -(defun relative-unix-pathname? (pathname) - (declare (type simple-string pathname)) - (or (zerop (length pathname)) - (char/= (schar pathname 0) #\/))) - -;;; Return PATHNAME with all symbolic links resolved. PATHNAME should -;;; already be a complete absolute Unix pathname, since at least in -;;; sbcl-0.6.12.36 we're called only from TRUENAME, and only after -;;; paths have been converted to absolute paths, so we don't need to -;;; try to handle any more generality than that. -(defun unix-resolve-links (pathname) - (declare (type simple-string pathname)) - ;; KLUDGE: The Win32 platform doesn't have symbolic links, so - ;; short-cut this computation (and the check for being an absolute - ;; unix pathname...) - #!+win32 (return-from unix-resolve-links pathname) - (aver (not (relative-unix-pathname? pathname))) - ;; KLUDGE: readlink and lstat are unreliable if given symlinks - ;; ending in slashes -- fix the issue here instead of waiting for - ;; libc to change... - ;; - ;; but be careful! Must not strip the final slash from "/". (This - ;; adjustment might be a candidate for being transferred into the C - ;; code in a wrap_readlink() function, too.) CSR, 2006-01-18 - (let ((len (length pathname))) - (when (and (> len 1) (eql #\/ (schar pathname (1- len)))) - (setf pathname (subseq pathname 0 (1- len))))) - (/noshow "entering UNIX-RESOLVE-LINKS") - (loop with previous-pathnames = nil do - (/noshow pathname previous-pathnames) - (let ((link (unix-readlink pathname))) - (/noshow link) - ;; Unlike the old CMU CL code, we handle a broken symlink by - ;; returning the link itself. That way, CL:TRUENAME on a - ;; broken link returns the link itself, so that CL:DIRECTORY - ;; can return broken links, so that even without - ;; Unix-specific extensions to do interesting things with - ;; them, at least Lisp programs can see them and, if - ;; necessary, delete them. (This is handy e.g. when your - ;; managed-by-Lisp directories are visited by Emacs, which - ;; creates broken links as notes to itself.) - (if (null link) - (return pathname) - (let ((new-pathname - (simplify-namestring - (if (relative-unix-pathname? link) - (let* ((dir-len (1+ (position #\/ - pathname - :from-end t))) - (dir (subseq pathname 0 dir-len))) - (/noshow dir) - (concatenate 'string dir link)) - link)))) - (if (unix-file-kind new-pathname) - (setf pathname new-pathname) - (return pathname))))) - ;; To generalize the principle that even if portable Lisp code - ;; can't do anything interesting with a broken symlink, at - ;; least it should be able to see and delete it, when we - ;; detect a cyclic link, we return the link itself. (So even - ;; though portable Lisp code can't do anything interesting - ;; with a cyclic link, at least it can see it and delete it.) - (if (member pathname previous-pathnames :test #'string=) - (return pathname) - (push pathname previous-pathnames)))) - (defconstant micro-seconds-per-internal-time-unit (/ 1000000 sb!xc:internal-time-units-per-second))