diff --git a/Makefile.am b/Makefile.am index 827c35f..98d55a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,11 +19,12 @@ src_libisofs_la_SOURCES = \ src/fsource.h \ src/fsource.c \ src/fs_local.c \ - src/messages.h \ - src/messages.c \ - src/libiso_msgs.h \ - src/libiso_msgs.c \ - src/stream.h + src/messages.h \ + src/messages.c \ + src/libiso_msgs.h \ + src/libiso_msgs.c \ + src/stream.h \ + src/stream.c libinclude_HEADERS = \ src/libisofs.h diff --git a/src/image.h b/src/image.h index 0c3ad55..126ced7 100644 --- a/src/image.h +++ b/src/image.h @@ -41,6 +41,4 @@ struct Iso_Image { struct libiso_msgs *messenger; }; - - #endif /*LIBISO_IMAGE_H_*/ diff --git a/src/stream.c b/src/stream.c new file mode 100644 index 0000000..7fc734c --- /dev/null +++ b/src/stream.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2007 Vreixo Formoso + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See COPYING file for details. + */ + +#include "libisofs.h" +#include "stream.h" +#include "fsource.h" +#include "error.h" + +#include + +typedef struct +{ + IsoFileSource *src; +} _FSrcStream; + +static +int fsrc_open(IsoStream *stream) +{ + IsoFileSource *src; + if (stream == NULL) { + return ISO_NULL_POINTER; + } + src = (IsoFileSource*)stream->data; + return src->open(src); +} + +static +int fsrc_close(IsoStream *stream) +{ + IsoFileSource *src; + if (stream == NULL) { + return ISO_NULL_POINTER; + } + src = (IsoFileSource*)stream->data; + return src->close(src); +} + +static +off_t fsrc_get_size(IsoStream *stream) +{ + struct stat info; + IsoFileSource *src; + if (stream == NULL) { + return ISO_NULL_POINTER; + } + src = (IsoFileSource*)stream->data; + + if (src->lstat(src, &info) < 0) { + return (off_t) -1; + } + + return info.st_size; +} + +static +int fsrc_read(IsoStream *stream, void *buf, size_t count) +{ + IsoFileSource *src; + if (stream == NULL) { + return ISO_NULL_POINTER; + } + src = (IsoFileSource*)stream->data; + return src->read(src, buf, count); +} + +static +int fsrc_is_repeatable(IsoStream *stream) +{ + int ret; + struct stat info; + IsoFileSource *src; + if (stream == NULL) { + return ISO_NULL_POINTER; + } + src = (IsoFileSource*)stream->data; + + ret = src->stat(src, &info); + if (ret < 0) { + return ret; + } + if (info.st_mode & (S_IFREG | S_IFBLK)) { + return 1; + } else { + return 0; + } +} + +static +void fsrc_free(IsoStream *stream) +{ + IsoFileSource *src; + src = (IsoFileSource*)stream->data; + iso_file_source_unref(src); +} + +int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream) +{ + int r; + struct stat info; + IsoStream *str; + if (src == NULL || stream == NULL) { + return ISO_NULL_POINTER; + } + + r = src->stat(src, &info); + if (r < 0) { + return r; + } + if (S_ISDIR(info.st_mode)) { + return ISO_FILE_IS_DIR; + } + + str = malloc(sizeof(IsoStream)); + if (str == NULL) { + return ISO_MEM_ERROR; + } + + str->refcount = 1; + str->data = src; + str->open = fsrc_open; + str->close = fsrc_close; + str->get_size = fsrc_get_size; + str->read = fsrc_read; + str->is_repeatable = fsrc_is_repeatable; + str->free = fsrc_free; + + *stream = str; + return ISO_SUCCESS; +} + +void iso_stream_ref(IsoStream *stream) +{ + ++stream->refcount; +} + +void iso_stream_unref(IsoStream *stream) +{ + if (--stream->refcount == 0) { + stream->free(stream); + free(stream); + } +} diff --git a/src/stream.h b/src/stream.h index ca5cab1..52daa55 100644 --- a/src/stream.h +++ b/src/stream.h @@ -11,6 +11,7 @@ /* * Definitions of streams. */ +#include "fsource.h" /* * Some functions here will be moved to libisofs.h when we expose @@ -37,6 +38,8 @@ struct Iso_Stream /** * Get the size (in bytes) of the stream. + * @return + * The size, or -1 on error */ off_t (*get_size)(IsoStream *stream); @@ -59,11 +62,36 @@ struct Iso_Stream * * This function doesn't take into account if the file has been modified * between the two reads. + * + * @return + * 1 if stream is repeatable, 0 if not, < 0 on error */ int (*is_repeatable)(IsoStream *stream); + /** + * Free implementation specific data. Should never be called by user. + * Use iso_stream_unref() instead. + */ + void (*free)(IsoStream *stream); + int refcount; void *data; }; +void iso_stream_ref(IsoStream *stream); +void iso_stream_unref(IsoStream *stream); + +/** + * Create a stream to read from a IsoFileSource. + * The stream will take the ref. to the IsoFileSource, so after a successfully + * exectution of this function, you musn't unref() the source, unless you + * take an extra ref. + * + * @return + * 1 sucess, < 0 error + * Possible errors: + * + */ +int iso_file_source_stream_new(IsoFileSource *src, IsoStream **stream); + #endif /*STREAM_H_*/