You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
1.9 KiB
107 lines
1.9 KiB
/* |
|
* Contains a simple implementation of a data source that reads from a |
|
* given file. |
|
*/ |
|
|
|
#include <assert.h> |
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
#include <fcntl.h> |
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
|
|
#include "libisofs.h" |
|
|
|
#define BLOCK_SIZE 2048 |
|
|
|
#define BLOCK_OUT_OF_FILE -1; |
|
#define READ_ERROR -2; |
|
#define SEEK_ERROR -3; |
|
|
|
struct file_data_src { |
|
int fd; |
|
int nblocks; |
|
}; |
|
|
|
static int |
|
ds_read_block(struct data_source *src, int lba, unsigned char *buffer) |
|
{ |
|
struct file_data_src *data; |
|
|
|
assert(src && buffer); |
|
|
|
data = (struct file_data_src*)src->data; |
|
|
|
/* For block devices size is always 0, so this can't be used. |
|
* if (lba >= data->nblocks) |
|
* return BLOCK_OUT_OF_FILE; |
|
*/ |
|
|
|
/* goes to requested block */ |
|
if ( lseek(data->fd, (off_t)lba * (off_t)BLOCK_SIZE, SEEK_SET) == (off_t) -1 ) |
|
return SEEK_ERROR; |
|
|
|
if ( read(data->fd, buffer, BLOCK_SIZE) != BLOCK_SIZE ) |
|
return READ_ERROR; |
|
|
|
return 0; |
|
} |
|
|
|
static int ds_get_size(struct data_source *src) |
|
{ |
|
struct file_data_src *data; |
|
|
|
assert(src); |
|
|
|
data = (struct file_data_src*)src->data; |
|
return data->nblocks; |
|
} |
|
|
|
static void ds_free_data(struct data_source *src) |
|
{ |
|
struct file_data_src *data; |
|
|
|
assert(src); |
|
|
|
data = (struct file_data_src*)src->data; |
|
|
|
/* close the file */ |
|
close(data->fd); |
|
free(data); |
|
} |
|
|
|
struct data_source *data_source_from_file(const char *path) |
|
{ |
|
int fd; |
|
struct stat info; |
|
struct file_data_src *data; |
|
struct data_source *ret; |
|
|
|
assert(path); |
|
|
|
fd = open(path, O_RDONLY); |
|
if (fd == -1) |
|
return NULL; |
|
|
|
fstat(fd, &info); |
|
|
|
data = malloc(sizeof(struct file_data_src)); |
|
data->fd = fd; |
|
data->nblocks = info.st_size / BLOCK_SIZE; |
|
|
|
ret = malloc(sizeof(struct data_source)); |
|
ret->refcount = 1; |
|
ret->read_block = ds_read_block; |
|
ret->get_size = ds_get_size; |
|
ret->free_data = ds_free_data; |
|
ret->data = data; |
|
return ret; |
|
} |
|
|
|
void data_source_free(struct data_source *src) |
|
{ |
|
if (--src->refcount == 0) { |
|
src->free_data(src); |
|
free(src); |
|
} |
|
}
|
|
|