diff options
Diffstat (limited to 'src/input/vcd/libvcd/stream_stdio.c')
-rw-r--r-- | src/input/vcd/libvcd/stream_stdio.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/src/input/vcd/libvcd/stream_stdio.c b/src/input/vcd/libvcd/stream_stdio.c new file mode 100644 index 000000000..e3a79a494 --- /dev/null +++ b/src/input/vcd/libvcd/stream_stdio.c @@ -0,0 +1,236 @@ +/* + $Id: stream_stdio.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +#include <errno.h> + +#include <cdio/cdio.h> + +#include <libvcd/logging.h> + +/* Private headers */ +#include "stream_stdio.h" +#include "util.h" + +static const char _rcsid[] = "$Id: stream_stdio.c,v 1.1 2003/10/13 11:47:12 f1rmb Exp $"; + +#define VCD_STREAM_STDIO_BUFSIZE (128*1024) + +typedef struct { + char *pathname; + FILE *fd; + char *fd_buf; + off_t st_size; /* used only for source */ +} _UserData; + +static int +_stdio_open_source (void *user_data) +{ + _UserData *const ud = user_data; + + if ((ud->fd = fopen (ud->pathname, "rb"))) + { + ud->fd_buf = _vcd_malloc (VCD_STREAM_STDIO_BUFSIZE); + setvbuf (ud->fd, ud->fd_buf, _IOFBF, VCD_STREAM_STDIO_BUFSIZE); + } + + return (ud->fd == NULL); +} + +static int +_stdio_open_sink (void *user_data) +{ + _UserData *const ud = user_data; + + if ((ud->fd = fopen (ud->pathname, "wb"))) + { + ud->fd_buf = _vcd_malloc (VCD_STREAM_STDIO_BUFSIZE); + setvbuf (ud->fd, ud->fd_buf, _IOFBF, VCD_STREAM_STDIO_BUFSIZE); + } + + return (ud->fd == NULL); +} + +static int +_stdio_close(void *user_data) +{ + _UserData *const ud = user_data; + + if (fclose (ud->fd)) + vcd_error ("fclose (): %s", strerror (errno)); + + ud->fd = NULL; + + free (ud->fd_buf); + ud->fd_buf = NULL; + + return 0; +} + +static void +_stdio_free(void *user_data) +{ + _UserData *const ud = user_data; + + if (ud->pathname) + free(ud->pathname); + + if (ud->fd) /* should be NULL anyway... */ + _stdio_close(user_data); + + free(ud); +} + +static long +_stdio_seek(void *user_data, long offset) +{ + _UserData *const ud = user_data; + + if (fseek (ud->fd, offset, SEEK_SET)) + vcd_error ("fseek (): %s", strerror (errno)); + + return offset; +} + +static long +_stdio_stat(void *user_data) +{ + const _UserData *const ud = user_data; + + return ud->st_size; +} + +static long +_stdio_read(void *user_data, void *buf, long count) +{ + _UserData *const ud = user_data; + long read; + + read = fread(buf, 1, count, ud->fd); + + if (read != count) + { /* fixme -- ferror/feof */ + if (feof (ud->fd)) + { + vcd_debug ("fread (): EOF encountered"); + clearerr (ud->fd); + } + else if (ferror (ud->fd)) + { + vcd_error ("fread (): %s", strerror (errno)); + clearerr (ud->fd); + } + else + vcd_debug ("fread (): short read and no EOF?!?"); + } + + return read; +} + +static long +_stdio_write(void *user_data, const void *buf, long count) +{ + _UserData *const ud = user_data; + long written; + + written = fwrite(buf, 1, count, ud->fd); + + if (written != count) + vcd_error ("fwrite (): %s", strerror (errno)); + + return written; +} + +VcdDataSource* +vcd_data_source_new_stdio(const char pathname[]) +{ + VcdDataSource *new_obj = NULL; + vcd_data_source_io_functions funcs = { 0, }; + _UserData *ud = NULL; + struct stat statbuf; + + if (stat (pathname, &statbuf) == -1) + { + vcd_error ("could not stat() file `%s': %s", pathname, strerror (errno)); + return NULL; + } + + ud = _vcd_malloc (sizeof (_UserData)); + + ud->pathname = strdup(pathname); + ud->st_size = statbuf.st_size; /* let's hope it doesn't change... */ + + funcs.open = _stdio_open_source; + funcs.seek = _stdio_seek; + funcs.stat = _stdio_stat; + funcs.read = _stdio_read; + funcs.close = _stdio_close; + funcs.free = _stdio_free; + + new_obj = vcd_data_source_new(ud, &funcs); + + return new_obj; +} + + +VcdDataSink* +vcd_data_sink_new_stdio(const char pathname[]) +{ + VcdDataSink *new_obj = NULL; + vcd_data_sink_io_functions funcs; + _UserData *ud = NULL; + struct stat statbuf; + + if (stat (pathname, &statbuf) != -1) + vcd_warn ("file `%s' exist already, will get overwritten!", pathname); + + ud = _vcd_malloc (sizeof (_UserData)); + + memset (&funcs, 0, sizeof (funcs)); + + ud->pathname = strdup (pathname); + + funcs.open = _stdio_open_sink; + funcs.seek = _stdio_seek; + funcs.write = _stdio_write; + funcs.close = _stdio_close; + funcs.free = _stdio_free; + + new_obj = vcd_data_sink_new (ud, &funcs); + + return new_obj; +} + + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ |