From bad03a9a2b91917b470fe6625409e517d2025cea Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Sat, 8 Mar 2008 18:34:41 +0100 Subject: [PATCH] Add lseek() function to IsoFileSource. --- libisofs/fs_image.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ libisofs/fs_local.c | 47 ++++++++++++++++++++++++++++++++++++++ libisofs/fsource.c | 6 +++++ libisofs/libisofs.h | 38 +++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+) diff --git a/libisofs/fs_image.c b/libisofs/fs_image.c index 8394cfd..54bb456 100644 --- a/libisofs/fs_image.c +++ b/libisofs/fs_image.c @@ -632,6 +632,60 @@ int ifs_read(IsoFileSource *src, void *buf, size_t count) return read; } +static +off_t ifs_lseek(IsoFileSource *src, off_t offset, int flag) +{ + ImageFileSourceData *data; + + if (src == NULL) { + return (off_t)ISO_NULL_POINTER; + } + if (offset < (off_t)0) { + return (off_t)ISO_WRONG_ARG_VALUE; + } + + data = src->data; + + if (!data->opened) { + return (off_t)ISO_FILE_NOT_OPENED; + } else if (data->opened != 1) { + return (off_t)ISO_FILE_IS_DIR; + } + + switch (flag) { + case 0: /* SEEK_SET */ + data->data.offset = offset; + break; + case 1: /* SEEK_CUR */ + data->data.offset += offset; + break; + case 2: /* SEEK_END */ + /* do this make sense? */ + data->data.offset = data->info.st_size + offset; + break; + default: + return (off_t)ISO_WRONG_ARG_VALUE; + } + + if (data->data.offset % BLOCK_SIZE != 0) { + /* we need to buffer the block */ + uint32_t block; + _ImageFsData *fsdata; + + if (data->data.offset < data->info.st_size) { + int ret; + fsdata = data->fs->data; + block = data->block + (data->data.offset / BLOCK_SIZE); + ret = fsdata->src->read_block(fsdata->src, block, + data->data.content); + if (ret < 0) { + return (off_t)ret; + } + } + } + return data->data.offset; +} + static int ifs_readdir(IsoFileSource *src, IsoFileSource **child) { @@ -771,6 +825,7 @@ IsoFileSourceIface ifs_class = { ifs_open, ifs_close, ifs_read, + ifs_lseek, ifs_readdir, ifs_readlink, ifs_get_filesystem, diff --git a/libisofs/fs_local.c b/libisofs/fs_local.c index bf37337..e9c61a1 100644 --- a/libisofs/fs_local.c +++ b/libisofs/fs_local.c @@ -304,6 +304,52 @@ int lfs_read(IsoFileSource *src, void *buf, size_t count) } } +static +off_t lfs_lseek(IsoFileSource *src, off_t offset, int flag) +{ + _LocalFsFileSource *data; + int whence; + + if (src == NULL) { + return (off_t)ISO_NULL_POINTER; + } + switch (flag) { + case 0: + whence = SEEK_SET; break; + case 1: + whence = SEEK_CUR; break; + case 2: + whence = SEEK_END; break; + default: + return (off_t)ISO_WRONG_ARG_VALUE; + } + + data = src->data; + switch (data->openned) { + case 1: /* not dir */ + { + off_t ret; + ret = lseek(data->info.fd, offset, whence); + if (ret < 0) { + /* error on read */ + switch (errno) { + case ESPIPE: + ret = (off_t)ISO_FILE_ERROR; + break; + default: + ret = (off_t)ISO_ERROR; + break; + } + } + return ret; + } + case 2: /* directory */ + return (off_t)ISO_FILE_IS_DIR; + default: + return (off_t)ISO_FILE_NOT_OPENED; + } +} + static int lfs_readdir(IsoFileSource *src, IsoFileSource **child) { @@ -430,6 +476,7 @@ IsoFileSourceIface lfs_class = { lfs_open, lfs_close, lfs_read, + lfs_lseek, lfs_readdir, lfs_readlink, lfs_get_filesystem, diff --git a/libisofs/fsource.c b/libisofs/fsource.c index b6e5c5f..4b74350 100644 --- a/libisofs/fsource.c +++ b/libisofs/fsource.c @@ -92,6 +92,12 @@ int iso_file_source_read(IsoFileSource *src, void *buf, size_t count) return src->class->read(src, buf, count); } +inline +off_t iso_file_source_lseek(IsoFileSource *src, off_t offset, int flag) +{ + return src->class->lseek(src, offset, flag); +} + inline int iso_file_source_readdir(IsoFileSource *src, IsoFileSource **child) { diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 72e20c7..848bf70 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -559,6 +559,25 @@ struct IsoFileSource_Iface * ISO_INTERRUPTED */ int (*read)(IsoFileSource *src, void *buf, size_t count); + + /** + * Repositions the offset of the IsoFileSource (must be opened) to the + * given offset according to the value of flag. + * + * @param offset + * in bytes + * @param flag + * 0 The offset is set to offset bytes (SEEK_SET) + * 1 The offset is set to its current location plus offset bytes + * (SEEK_CUR) + * 2 The offset is set to the size of the file plus offset bytes + * (SEEK_END). + * @return + * Absolute offset posistion on the file, or < 0 on error. Cast the + * returning value to int to get a valid libisofs error. + * @since 0.6.4 + */ + off_t (*lseek)(IsoFileSource *src, off_t offset, int flag); /** * Read a directory. @@ -3216,6 +3235,25 @@ int iso_file_source_close(IsoFileSource *src); */ int iso_file_source_read(IsoFileSource *src, void *buf, size_t count); +/** + * Repositions the offset of the given IsoFileSource (must be opened) to the + * given offset according to the value of flag. + * + * @param offset + * in bytes + * @param flag + * 0 The offset is set to offset bytes (SEEK_SET) + * 1 The offset is set to its current location plus offset bytes + * (SEEK_CUR) + * 2 The offset is set to the size of the file plus offset bytes + * (SEEK_END). + * @return + * Absolute offset posistion on the file, or < 0 on error. Cast the + * returning value to int to get a valid libisofs error. + * @since 0.6.4 + */ +off_t iso_file_source_lseek(IsoFileSource *src, off_t offset, int flag); + /** * Read a directory. *