#include #include #include #include #include #include #include #include #include #include "file_src.h" #include "messages.h" #define BLOCK_SIZE 2048 struct local_file_data { int fd; /* the file descriptor, once the file is opened */ off_t size; /* file size */ off_t bytes_read; /* bytes already read from file */ int error; char *path; /* path of the file on local filesystem */ }; static int lf_open(struct iso_file_src *src) { struct local_file_data *data; assert(src); data = (struct local_file_data*) src->data; assert(data->fd == -1); data->fd = open(data->path, O_RDONLY); data->bytes_read = (off_t) 0; data->error = 0; return (data->fd != -1 ? 1 : 0); } static void lf_close(struct iso_file_src *src) { struct local_file_data *data; assert(src); data = (struct local_file_data*) src->data; assert(data->fd != -1); close(data->fd); data->fd = -1; } static int lf_read_block(struct iso_file_src *src, unsigned char *buffer) { ssize_t bytes; struct local_file_data *data; assert(src); assert(buffer); data = (struct local_file_data*) src->data; assert(data->fd != -1); if (data->bytes_read >= data->size) { return 0; } if (data->error) { memset(buffer, 0, BLOCK_SIZE); data->bytes_read += BLOCK_SIZE; return -2; } bytes = 0; do { ssize_t result; result = read(data->fd, buffer + bytes, BLOCK_SIZE - bytes); if (result < 0) { char msg[PATH_MAX + 32]; sprintf(msg, "Problem reading from %s", data->path); iso_msg_sorry(LIBISO_CANT_READ_FILE, msg); /* fill buffer with 0s and return */ memset(buffer + bytes, 0, BLOCK_SIZE - bytes); data->bytes_read += BLOCK_SIZE; return -1; } if (!result) break; bytes += result; } while (bytes < BLOCK_SIZE); if (bytes < BLOCK_SIZE) { /* eof */ memset(buffer + bytes, 0, BLOCK_SIZE - bytes); } data->bytes_read += (off_t) bytes; if (data->bytes_read >= data->size) { return 0; } else { return 1; } } static off_t lf_get_size(struct iso_file_src *src) { struct local_file_data *data; assert(src); data = (struct local_file_data*) src->data; return data->size; } static void lf_free_data(struct iso_file_src *src) { free(src->data); } struct iso_file_src* iso_file_src_from_path(const char *path) { struct stat info; struct iso_file_src *src; struct local_file_data *data; assert(path); if (lstat(path, &info) < 0) { iso_msg_fatal(LIBISO_FILE_DOESNT_EXIST, "File doesn't exist"); return NULL; } if (access(path, R_OK) < 0) { iso_msg_fatal(LIBISO_FILE_NO_READ_ACCESS, "No read access"); return NULL; } data = malloc(sizeof(struct local_file_data)); if (!data) return NULL; src = malloc(sizeof(struct iso_file_src)); if (!src) { free(data); return NULL; } data->fd = -1; data->path = strdup(path); data->size = info.st_size; src->open = lf_open; src->close = lf_close; src->read_block = lf_read_block; src->get_size = lf_get_size; src->free_data = lf_free_data; src->data = data; return src; }