Re: Odd behavior for manually-constructed file-stream
Gary Byers <[email protected]> Mon, 25 Sep 2006 10:11:23 -0600 (MDT)
| Newsgroups | gmane.lisp.openmcl.bugs |
|---|---|
| Message-ID | <[email protected]> |
On Sun, 24 Sep 2006, Richard M Kreuter wrote:
> Hello,
>
> Using OpenMCL 1.0 PPC/Linux, I'm having trouble figuring out how to
> acheive consistency across print/file-position/read operations on a
> file-stream made with ccl::make-fd-stream.
>
> The strangeness is this: a print followed by a file-position followed
> by a read signals an end-of-file error unless both (1) force-output is
> called between the print and the file-position and (2) the postition
> argument to file-position was greater than 1.
>
> By inspection, neither of these is required for streams with direction
> :io created by open, so I'm confused about what the intended behavior
> is supposed to be on OpenMCL.
File streams created with OPEN call FORCE-OUTPUT and otherwise do the
right thing(s) with buffering when FILE-POSITION is called on them.
In general, streams created with CCL::MAKE-FD-STREAM don't. (It's
intended for non-seekable things like pipes and sockets and ptys.)
>
> Below are some transcripts that demonstrate the behaviors described
> above.
>
> What am I doing wrong?
Why are you using CCL::MAKE-FD-STREAM ?
(If the answer is "because you already had a file descriptor and
wanted to use stream functions to access it, as in your example"
... it'd be handy to have something like that - something like OPEN
that took an open FD rather than a pathname - but it doesn't really
exist.)
One very, very sleazy way of doing that - that might almost work -
would be to use OPEN to create a file stream to some (other) temporary
file, then use the #_dup2 functon to make the file descriptor of that
stream match the file descriptor in question. Something like:
(defun get-file-stream-for-fd (fd &rest open-args)
(let* ((stream (apply #'open "/some/random/file" open-args)))
;; Some stream classes use different file descriptors
;; for input and output. FILE-STREAMs opened for I/O use the same
;; descriptor in both directions, but CCL::STREAM-DEVICE wants
;; its second arg to be one of :INPUT or :OUTPUT (and the stream
;; has to be open in the direction indicated by that arg.)
(#_dup2 fd (ccl::stream-device stream :input))
stream))
That's untested (and admittedly very, very sleazy.)
>
> Thanks in advance,
> RmK
> --
>
> ;; Behavior of a stream constructed by OPEN. No force-outputs are
> ;; necessary, and setting file-position to 0 works as I'd expect.
> ;; Not using with-open-file just for symmetry with the following
> ;; examples.
> CL-USER> (with-open-stream (stream
> (open "/tmp/foo.tmp"
> :direction :io :if-exists :supersede))
> (print 'bar stream)
> (file-position stream 0)
> (read-char stream))
> #\Newline
> CL-USER> (with-open-stream (stream
> (open "/tmp/foo.tmp"
> :direction :io :if-exists :supersede))
> (print 'foo stream)
> (file-position stream 0)
> (read stream))
> FOO
>
> ;; Use cffi to define tmpfile() and fileno() functions.
> CL-USER> (defpackage tmpfile (:use :cl :cffi))
> #<Package "TMPFILE">
> CL-USER> (in-package tmpfile)
> #<Package "TMPFILE">
> TMPFILE> (defcfun "tmpfile" :pointer)
> TMPFILE
> TMPFILE> (defcfun "fileno" :int (file :pointer))
> FILENO
> TMPFILE> (defun make-tmpfile ()
> (let ((file (tmpfile)))
> (let ((fd (unwind-protect
> (fileno file)
> (foreign-free file))))
> (ccl::make-fd-stream fd :direction :io
> :class 'file-stream))))
> MAKE-TMPFILE
>
> ;; Verify that make-tmpfile does something.
> TMPFILE> (make-tmpfile)
> #<FILE-CHARACTER-IO-STREAM (NIL/9) #x35516FE6>
> TMPFILE> (close *)
> T
>
> ;; Try the same routine as above:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> (print 'bar stream)
> (file-position stream 0)
> (read-char stream))
> Unexpected end of file on #<FILE-CHARACTER-IO-STREAM (NIL/9) #x355101DE>
> [Condition of type END-OF-FILE]
> ; Evaluation aborted
>
> ;; Try force-output:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> (print 'bar stream)
> (force-output stream)
> (file-position stream 0)
> (read-char stream))
> Unexpected end of file on #<FILE-CHARACTER-IO-STREAM (NIL/9) #x3556A216>
> [Condition of type END-OF-FILE]
> ; Evaluation aborted
>
> ;; Try setting the file-position to 1 instead of 0:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> (print 'bar stream)
> (file-position stream 1)
> (read-char stream))
> Unexpected end of file on #<FILE-CHARACTER-IO-STREAM (NIL/9) #x3559DA0E>
> [Condition of type END-OF-FILE]
> ; Evaluation aborted
>
> ;; Using both force-output and setting the file-position to 1:
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> (print 'bar stream)
> (force-output stream)
> (file-position stream 1)
> (read-char stream))
> #\B
> TMPFILE> (with-open-stream (stream (make-tmpfile))
> (print 'foo stream)
> (force-output stream)
> (file-position stream 1)
> (read stream))
> FOO
>
> _______________________________________________
> Bug-openmcl mailing list
> [email protected]
> http://clozure.com/mailman/listinfo/bug-openmcl
>
>