/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2018-2021 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "mu_scm.h" #include struct port_stream { struct _mu_stream stream; SCM port; }; static int port_stream_read (struct _mu_stream *str, char *buf, size_t bufsize, size_t *pnread) { struct port_stream *pstr = (struct port_stream *)str; size_t n = scm_c_read (pstr->port, buf, bufsize); if (pnread) *pnread = n; return 0; } static int port_stream_write (struct _mu_stream *str, const char *buf, size_t bufsize, size_t *pnwrite) { struct port_stream *pstr = (struct port_stream *)str; scm_c_write (pstr->port, buf, bufsize); if (pnwrite) *pnwrite = bufsize; return 0; } static int port_stream_seek (struct _mu_stream *str, mu_off_t off, mu_off_t *presult) { struct port_stream *pstr = (struct port_stream *)str; SCM ret = scm_seek (pstr->port, scm_from_signed_integer (off), scm_from_int (SEEK_SET)); if (presult) *presult = scm_to_int64 (ret); /* FIXME: scm_to_off_t is not exposed */ return 0; } static int port_stream_truncate (mu_stream_t stream, mu_off_t size) { struct port_stream *pstr = (struct port_stream *)stream; scm_truncate_file (pstr->port, scm_from_signed_integer (size)); return 0; } static void port_stream_done (struct _mu_stream *str) { struct port_stream *pstr = (struct port_stream *)str; scm_gc_unprotect_object (pstr->port); } static int port_stream_size (struct _mu_stream *str, mu_off_t *psize) { struct port_stream *pstr = (struct port_stream *)str; mu_off_t cur; int rc; SCM ret; rc = mu_stream_seek (str, 0, MU_SEEK_CUR, &cur); if (rc) return rc; ret = scm_seek (pstr->port, scm_from_signed_integer (0), scm_from_int (SEEK_END)); rc = mu_stream_seek (str, cur, MU_SEEK_SET, NULL); if (rc == 0) *psize = scm_to_int64 (ret); return rc; } int mu_scm_port_stream_create (mu_stream_t *pstream, SCM port) { char *mode; int flags = MU_STREAM_SEEK|_MU_STR_OPEN; struct port_stream *pstr; mode = scm_to_locale_string (scm_port_mode (port)); if (strchr (mode, 'r')) flags |= MU_STREAM_READ; if (strchr (mode, 'w')) flags |= MU_STREAM_WRITE; free (mode); pstr = (struct port_stream *) _mu_stream_create (sizeof (*pstr), flags); if (!pstr) return ENOMEM; pstr->stream.read = port_stream_read; pstr->stream.write = port_stream_write; pstr->stream.seek = port_stream_seek; pstr->stream.size = port_stream_size; pstr->stream.truncate = port_stream_truncate; pstr->stream.done = port_stream_done; pstr->port = port; scm_gc_protect_object (port); *pstream = (mu_stream_t) pstr; return 0; }