From ee35f84292fd4108baff2d452527131d0dec4739 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 1 Dec 2005 22:14:27 +0000 Subject: [PATCH] first revision --- libcontainer/container_close.c | 22 ++++++++ libcontainer/container_fstat.c | 19 +++++++ libcontainer/container_lseek.c | 34 ++++++++++++ libcontainer/container_open.c | 50 +++++++++++++++++ libcontainer/container_read.c | 98 ++++++++++++++++++++++++++++++++++ 5 files changed, 223 insertions(+) create mode 100644 libcontainer/container_close.c create mode 100644 libcontainer/container_fstat.c create mode 100644 libcontainer/container_lseek.c create mode 100644 libcontainer/container_open.c create mode 100644 libcontainer/container_read.c diff --git a/libcontainer/container_close.c b/libcontainer/container_close.c new file mode 100644 index 0000000..d8e77c9 --- /dev/null +++ b/libcontainer/container_close.c @@ -0,0 +1,22 @@ +/* + * + * (c) 2005 Laurent Vivier + * + */ + +#include + +#include "libcontainer.h" + +int container_close(container_FILE *file) +{ + if (file == NULL) + return -1; + + if (file->container) + free(file->container); + + free(file); + + return 0; +} diff --git a/libcontainer/container_fstat.c b/libcontainer/container_fstat.c new file mode 100644 index 0000000..0578cc5 --- /dev/null +++ b/libcontainer/container_fstat.c @@ -0,0 +1,19 @@ +/* + * + * (c) 2005 Laurent Vivier + * + */ + +#include "libcontainer.h" + +int container_fstat(container_FILE *file, struct stream_stat *buf) +{ + if (buf == NULL) + return -1; + if (file->container->size == -1) + return -1; + + buf->st_size = file->container->size; + + return 0; +} diff --git a/libcontainer/container_lseek.c b/libcontainer/container_lseek.c new file mode 100644 index 0000000..fe9ea05 --- /dev/null +++ b/libcontainer/container_lseek.c @@ -0,0 +1,34 @@ +/* + * + * (c) 2005 Laurent Vivier + * + */ + +#include +#include + +#include "libcontainer.h" + +int container_lseek(container_FILE *file, off_t offset, int whence) +{ + long new_offset; + + switch(whence) + { + case SEEK_SET: + new_offset = offset; + break; + case SEEK_CUR: + new_offset = file->offset + offset; + break; + default: + return -1; + } + + if (new_offset < 0) + return -1; + + file->offset = new_offset; + + return new_offset; +} diff --git a/libcontainer/container_open.c b/libcontainer/container_open.c new file mode 100644 index 0000000..2d7045a --- /dev/null +++ b/libcontainer/container_open.c @@ -0,0 +1,50 @@ +/* + * + * (c) 2005 Laurent Vivier + * + */ + +#include + +#include "libcontainer.h" + +container_FILE *container_open(device_io_t *device, char *path) +{ + container_FILE *file; + int block_size = device->get_blocksize(device->data); + unsigned long first, nbblocs; + int ret; + + first = strtol(path, &path, 0); + if (*path != ',') + return NULL; + path++; + nbblocs = strtol(path, &path, 0); + if (*path != 0) + return NULL; + + file = (container_FILE *)malloc(sizeof(container_FILE) + block_size); + if (file == NULL) + return NULL; + + file->container = (struct emile_container*)malloc(sizeof(struct emile_container) + block_size * nbblocs); + if (file->container == NULL) + { + free(file); + return NULL; + } + + ret = device->read_sector(device->data, first, file->container, block_size * nbblocs); + if (ret == -1) + { + free(file->container); + free(file); + } + + file->offset = 0; + file->current_block = 0; + file->last_current = 0; + file->last_index = 0; + + return file; +} diff --git a/libcontainer/container_read.c b/libcontainer/container_read.c new file mode 100644 index 0000000..6076430 --- /dev/null +++ b/libcontainer/container_read.c @@ -0,0 +1,98 @@ +/* + * + * (c) 2005 Laurent Vivier + * + */ + +#include +#include + +#include "libcontainer.h" + +static unsigned long seek_block(container_FILE *file) +{ + struct emile_container *container = file->container; + ssize_t current; + int i; + unsigned long offset = file->offset; + int block_size = file->device.get_blocksize(file->device.data); + + /* search forward */ + + for (i = file->last_index, + current = file->last_current; + i < container->blocks[i].count; i++) + { + int extent_size = block_size * + container->blocks[i].count; + + if ( (current <= offset) && (offset < current + extent_size) ) + { + file->last_current = current; + file->last_index = i; + return container->blocks[i].offset + + (offset - current) / block_size; + } + + current += extent_size; + } + + /* search backward */ + + for (i = file->last_index, + current = file->last_current; + i > 0; i--) + { + int extent_size = block_size * + container->blocks[i - 1].count; + + current -= extent_size; + + if ( (current <= offset) && (offset < current + extent_size) ) + { + file->last_current = current; + file->last_index = i - 1; + return container->blocks[i].offset + + (offset - current) / block_size; + } + } + return 0; +} + +ssize_t container_read(container_FILE *file, void *ptr, size_t size) +{ + int err; + ssize_t read = 0; + int part; + int block_size = file->device.get_blocksize(file->device.data); + + while (size != 0) + { + unsigned long block_nb = seek_block(file); + int block_offset = file->offset % block_size; + + if (block_nb != file->current_block) + { + err = file->device.read_sector( + file->device.data, + block_nb, + file->buffer, + block_size); + if (err == -1) + return -1; + file->current_block = block_nb; + } + + part = block_size - block_offset; + if (part > size) + part = size; + memcpy(ptr, file->buffer + block_offset, part); + + size -= part; + ptr = (char*)ptr + part; + file->offset += part; + read += part; + } + + return read; +}