(element-type 'base-char)
;; the Unix file descriptor
(fd -1 :type fixnum)
+ ;; What do we know about the FD?
+ (fd-type :unknown :type keyword)
;; controls when the output buffer is flushed
(buffering :full :type (member :full :line :none))
;; controls whether the input buffer must be cleared before output
(return (reset-buffer obuf)))
(count
;; Partial write -- update buffer status and
- ;; queue or wait. Do not use INCF! Another
- ;; thread might have moved head...
- (setf (buffer-head obuf) (+ count head))
+ ;; queue or wait.
+ (incf head count)
+ (setf (buffer-head obuf) head)
(queue-or-wait))
#!-win32
((eql errno sb!unix:ewouldblock)
(count 0))
(tagbody
;; Check for blocking input before touching the stream if we are to
- ;; serve events: if the FD is blocking, we don't want to hang on the
- ;; write if we are to serve events or notice timeouts.
- (if (and (or (fd-stream-serve-events stream)
- (fd-stream-timeout stream)
- *deadline*)
+ ;; serve events: if the FD is blocking, we don't want to try an uninterruptible
+ ;; read(). Regular files should never block, so we can elide the check.
+ (if (and (neq :regular (fd-stream-fd-type stream))
(sysread-may-block-p stream))
(go :wait-for-input)
(go :main))
((not (or input output))
(error "File descriptor must be opened either for input or output.")))
(let ((stream (%make-fd-stream :fd fd
+ :fd-type (progn
+ #!-win32 (sb!unix:fd-type fd)
+ ;; KLUDGE.
+ #!+win32 (if serve-events
+ :unknown
+ :regular))
:name name
:file file
:original original
(cond ((numberp fd)
(case direction
((:input :output :io)
+ ;; For O_APPEND opened files, lseek returns 0 until first write.
+ ;; So we jump ahead here.
+ (when (eq if-exists :append)
+ (sb!unix:unix-lseek fd 0 sb!unix:l_xtnd))
(make-fd-stream fd
:input input
:output output