From 135ac835ebee32896412990e8c3a89e3c8ed8289 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Sun, 30 Dec 2007 18:29:39 +0100 Subject: [PATCH] Implementation of IsoDataSource based on POSIX I/O. --- src/data_source.c | 147 ++++++++++++++++++++++++++++++++++++++++++++-- src/error.h | 1 + src/libisofs.h | 3 +- 3 files changed, 146 insertions(+), 5 deletions(-) diff --git a/src/data_source.c b/src/data_source.c index 41ec6c9..1bd1213 100644 --- a/src/data_source.c +++ b/src/data_source.c @@ -8,8 +8,23 @@ #include "libisofs.h" #include "error.h" +#include "util.h" #include +#include +#include +#include +#include +#include + +/** + * Private data for File IsoDataSource + */ +struct file_data_src +{ + char *path; + int fd; +}; /** * Increments the reference counting of the given IsoDataSource. @@ -31,6 +46,93 @@ void iso_data_source_unref(IsoDataSource *src) } } +static +int ds_open(IsoDataSource *src) +{ + int fd; + struct file_data_src *data; + + if (src == NULL || src->data == NULL) { + return ISO_NULL_POINTER; + } + + data = (struct file_data_src*) src->data; + if (data->fd != -1) { + return ISO_FILE_ALREADY_OPENNED; + } + + fd = open(data->path, O_RDONLY); + if (fd == -1) { + return ISO_FILE_ERROR; + } + + data->fd = fd; + return ISO_SUCCESS; +} + +static +int ds_close(IsoDataSource *src) +{ + int ret; + struct file_data_src *data; + + if (src == NULL || src->data == NULL) { + return ISO_NULL_POINTER; + } + + data = (struct file_data_src*) src->data; + if (data->fd == -1) { + return ISO_FILE_NOT_OPENNED; + } + + /* close can fail if fd is not valid, but that should never happen */ + ret = close(data->fd); + + /* in any case we mark file as closed */ + data->fd = -1; + return ret == 0 ? ISO_SUCCESS : ISO_FILE_ERROR; +} + +static int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) +{ + struct file_data_src *data; + + if (src == NULL || src->data == NULL || buffer == NULL) { + return ISO_NULL_POINTER; + } + + data = (struct file_data_src*) src->data; + if (data->fd == -1) { + return ISO_FILE_NOT_OPENNED; + } + + /* goes to requested block */ + if (lseek(data->fd, (off_t)lba * (off_t)2048, SEEK_SET) == (off_t) -1) { + return ISO_FILE_SEEK_ERROR; + } + + // TODO guard against partial reads. + if (read(data->fd, buffer, 2048) != 2048) { + return ISO_FILE_READ_ERROR; + } + + return ISO_SUCCESS; +} + +static +void ds_free_data(IsoDataSource *src) +{ + struct file_data_src *data; + + data = (struct file_data_src*)src->data; + + /* close the file if needed */ + if (data->fd != 1) { + close(data->fd); + } + free(data->path); + free(data); +} /** * Create a new IsoDataSource from a local file. This is suitable for @@ -46,11 +148,48 @@ void iso_data_source_unref(IsoDataSource *src) */ int iso_data_source_new_from_file(const char *path, IsoDataSource **src) { - + int ret; + struct file_data_src *data; + IsoDataSource *ds; + if (path == NULL || src == NULL) { + return ISO_NULL_POINTER; + } + + /* ensure we have read access to the file */ + ret = iso_eaccess(path); + if (ret < 0) { + return ret; + } + + data = malloc(sizeof(struct file_data_src)); + if (data == NULL) { return ISO_MEM_ERROR; } - - //TODO implement - return -1; + + ds = malloc(sizeof(IsoDataSource)); + if (ds == NULL) { + free(data); + return ISO_MEM_ERROR; + } + + /* fill data fields */ + data->path = strdup(path); + if (data->path == NULL) { + free(data); + free(ds); + return ISO_MEM_ERROR; + } + + data->fd = -1; + ds->refcount = 1; + ds->data = data; + + ds->open = ds_open; + ds->close = ds_close; + ds->read_block = ds_read_block; + ds->free_data = ds_free_data; + + *src = ds; + return ISO_SUCCESS; } diff --git a/src/error.h b/src/error.h index 9e4ed22..9368b66 100644 --- a/src/error.h +++ b/src/error.h @@ -39,6 +39,7 @@ #define ISO_FILE_IS_NOT_DIR -108 #define ISO_FILE_IS_NOT_SYMLINK -109 #define ISO_FILE_TOO_BIG -110 +#define ISO_FILE_SEEK_ERROR -111 #define ISO_CHARSET_CONV_ERROR -150 diff --git a/src/libisofs.h b/src/libisofs.h index ba9d7ad..f3b2ec1 100644 --- a/src/libisofs.h +++ b/src/libisofs.h @@ -9,6 +9,7 @@ #define LIBISO_LIBISOFS_H_ #include +#include struct burn_source; @@ -188,7 +189,7 @@ struct Iso_Data_Source { * @return * 1 if success, < 0 on error */ - int (*read_block)(IsoDataSource *src, int lba, unsigned char *buffer); + int (*read_block)(IsoDataSource *src, uint32_t lba, uint8_t *buffer); /** * Clean up the source specific data. Never call this directly, it is