(%default-port-encoding #f))
                    (open filename mode))))))
    (setvbuf port buffer-mode)
    (when transcoder
      (set-port-encoding! port (transcoder-codec transcoder)))
    port))

(define (file-options->mode file-options base-mode)
  (logior base-mode
          (if (enum-set-member? 'no-create file-options)
              0
              O_CREAT)
          (if (enum-set-member? 'no-truncate file-options)
              0
              O_TRUNC)
          (if (enum-set-member? 'no-fail file-options)
              0
              O_EXCL)))

(define* (open-file-input-port filename
                               #:optional
                               (file-options (file-options))
                               (buffer-mode (buffer-mode block))
                               transcoder)
  "Return an input port for reading from @var{filename}."
  (r6rs-open filename O_RDONLY buffer-mode transcoder))

(define* (open-file-input/output-port filename
                                      #:optional
                                      (file-options (file-options))
                                      (buffer-mode (buffer-mode block))
                                      transcoder)
  "Return a port for reading from and writing to @var{filename}."
  (r6rs-open filename
             (file-options->mode file-options O_RDWR)
             buffer-mode
             transcoder))

(define (open-string-output-port)
  "Return two values: an output port that will collect characters written to it
as a string, and a thunk to retrieve the characters associated with that port."
  (let ((port (open-output-string)))
    (values port
            (lambda ()
              (let ((s (get-output-string port)))
                (seek port 0 SEEK_SET)
                (truncate-file port 0)
                s)))))

(define* (open-file-output-port filename
                                #:optional
                                (file-options (file-options))
                                (buffer-mode (buffer-mode block))
                                maybe-transcoder)
  "Return an output port for writing to @var{filename}."
  (r6rs-open filename
             (file-options->mode file-options O_WRONLY)
             buffer-mode
             maybe-transcoder))

(define (call-with-string-output-port proc)
  "Call @var{proc}, passing it a string output port. When @var{proc} returns,
return the characters accumulated in that port."
  (let ((port (open-output-string)))
    (proc port)
    (get-output-string port)))

(define (make-custom-textual-output-port id
                                         write!
                                         get-position
                                         set-position!
                                         close)
  (make-soft-port (vector (lambda (c) (write! (string c) 0 1))
                          (lambda (s) (write! s 0 (string-length s)))
                          #f ;flush
                          #f ;read character
                          close)
                  "w"))

(define (output-port-buffer-mode port)
  "Return @code{none} if @var{port} is unbuffered, @code{line} if it is
line buffered, or @code{block} otherwise."
  (let ((buffering (bytevector-length
                    (port-buffer-bytevector (port-write-buffer port)))))
    (cond
     ((= buffering 1) 'none)
     ((port-line-buffered? port) 'line)
     (else 'block))))

(define (flush-output-port port)
  (force-output port))

