Migration to iso_file_src in file writing function.
This commit is contained in:
parent
8de9d35873
commit
f811234b8f
@ -20,6 +20,7 @@
|
||||
#include "tree.h"
|
||||
#include "util.h"
|
||||
#include "file.h"
|
||||
#include "file_src.h"
|
||||
#include "libisofs.h"
|
||||
#include "libburn/libburn.h"
|
||||
#include "eltorito.h"
|
||||
@ -553,67 +554,36 @@ wr_dir_records(struct ecma119_write_target *t, uint8_t *buf)
|
||||
static void
|
||||
wr_files(struct ecma119_write_target *t, uint8_t *buf)
|
||||
{
|
||||
int res;
|
||||
struct state_files *f_st = &t->state_files;
|
||||
size_t nread;
|
||||
struct iso_file *f = t->filelist[f_st->file];
|
||||
|
||||
if (f->prev_img) {
|
||||
int block;
|
||||
assert( !t->ms_block && t->src );
|
||||
|
||||
if (!f_st->src) {
|
||||
|
||||
/**
|
||||
* f->block block where file write begins
|
||||
* t->curblock block we're writting now
|
||||
* f->real_ino initial block for file on source
|
||||
*/
|
||||
block = t->curblock - f->block;
|
||||
if ( t->src->read_block(t->src, f->real_ino + block, buf) ) {
|
||||
iso_msg_sorry(LIBISO_CANT_READ_IMG,
|
||||
"Problem reading file from previous image");
|
||||
}
|
||||
if ( f->size <= (off_t) (block+1) * t->block_size ) {
|
||||
f_st->file++;
|
||||
if (f_st->file >= t->filelist_len)
|
||||
next_state(t);
|
||||
}
|
||||
} else {
|
||||
const char *path = f->path;
|
||||
|
||||
if (!f_st->fd) {
|
||||
|
||||
if (!f->prev_img) {
|
||||
char msg[PATH_MAX + 14];
|
||||
sprintf(msg, "Writing file %s", path);
|
||||
sprintf(msg, "Writing file %s", f->path);
|
||||
iso_msg_debug(msg);
|
||||
|
||||
f_st->data_len = f->size;
|
||||
f_st->fd = fopen(path, "r");
|
||||
if (!f_st->fd) {
|
||||
//FIXME instead of exit, just print a msg error and
|
||||
//skip file (what about reading from /dev/zero? instead)
|
||||
err(1, "couldn't open %s for reading", path);
|
||||
}
|
||||
assert(t->curblock + t->ms_block == f->block);
|
||||
}
|
||||
|
||||
nread = fread(buf, 1, t->block_size, f_st->fd);
|
||||
f_st->pos += t->block_size;
|
||||
if (nread < 0) {
|
||||
char msg[PATH_MAX + 32];
|
||||
sprintf(msg, "Problem reading from %s", path);
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE, msg);
|
||||
} else if (nread != t->block_size && f_st->pos < f_st->data_len) {
|
||||
char msg[PATH_MAX + 32];
|
||||
sprintf(msg, "Incomplete read from %s", path);
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE, msg);
|
||||
}
|
||||
if (f_st->pos >= f_st->data_len) {
|
||||
fclose(f_st->fd);
|
||||
f_st->fd = 0;
|
||||
f_st->pos = 0;
|
||||
f_st->file++;
|
||||
if (f_st->file >= t->filelist_len)
|
||||
next_state(t);
|
||||
}
|
||||
|
||||
f_st->src = f->src;
|
||||
if ( f->src->open(f->src) <= 0) {
|
||||
//FIXME instead of exit, just print a msg error and
|
||||
//skip file (what about reading from /dev/zero? instead)
|
||||
/* can only happen with new files */
|
||||
err(1, "couldn't open %s for reading", f->path);
|
||||
}
|
||||
assert(t->curblock + t->ms_block == f->block);
|
||||
}
|
||||
|
||||
res = f_st->src->read_block(f_st->src, buf);
|
||||
if (res == 0) {
|
||||
/* we have read the expected bytes from file */
|
||||
f_st->src->close(f_st->src);
|
||||
f_st->src = NULL;
|
||||
f_st->file++;
|
||||
if (f_st->file >= t->filelist_len)
|
||||
next_state(t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,8 +902,10 @@ bs_free_data(struct burn_source *bs)
|
||||
free(t->state_data);
|
||||
if (t->joliet)
|
||||
joliet_tree_free(t->joliet_root);
|
||||
if (t->state_files.fd)
|
||||
fclose(t->state_files.fd);
|
||||
|
||||
// TODO is this needed?
|
||||
if (t->state_files.src)
|
||||
t->state_files.src->close(t->state_files.src);
|
||||
}
|
||||
|
||||
struct burn_source *iso_source_new_ecma119(struct iso_volset *volset,
|
||||
|
@ -174,13 +174,14 @@ struct ecma119_write_target
|
||||
|
||||
/* for writing out files */
|
||||
struct state_files {
|
||||
off_t pos; /* The number of bytes we have written
|
||||
* so far in the current file.
|
||||
*/
|
||||
off_t data_len;/* The number of bytes in the currently
|
||||
* open file.
|
||||
*/
|
||||
FILE *fd; /* The currently open file. */
|
||||
// off_t pos; /* The number of bytes we have written
|
||||
// * so far in the current file.
|
||||
// */
|
||||
// off_t data_len;/* The number of bytes in the currently
|
||||
// * open file.
|
||||
// */
|
||||
// FILE *fd; /* The currently open file. */
|
||||
struct iso_file_src *src; /* source for reading from the file */
|
||||
int file; /* The index in filelist that we are
|
||||
* currently writing (or about to write). */
|
||||
} state_files;
|
||||
|
@ -183,7 +183,16 @@ create_file(struct ecma119_write_target *t,
|
||||
* If the file is not already added to the disc, we add it now
|
||||
* to the file table, and get a new inode number for it.
|
||||
*/
|
||||
file = iso_file_new(iso);
|
||||
file = iso_file_new(t, iso);
|
||||
if (!file) {
|
||||
/*
|
||||
* That was an error.
|
||||
* TODO currently this cause the file to be ignored... Maybe
|
||||
* throw an error is a better alternative
|
||||
*/
|
||||
ecma119_tree_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
file->ino = ++t->ino;
|
||||
} else {
|
||||
|
@ -1,23 +1,31 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "file.h"
|
||||
#include "tree.h"
|
||||
#include "file_src.h"
|
||||
#include "messages.h"
|
||||
#include "ecma119.h"
|
||||
|
||||
//TODO: refactor both hash and this hash table into a single one??
|
||||
|
||||
struct iso_file *
|
||||
iso_file_new(struct iso_tree_node_file *f)
|
||||
iso_file_new(struct ecma119_write_target *t, struct iso_tree_node_file *f)
|
||||
{
|
||||
struct iso_file *file = calloc(1, sizeof(struct iso_file));
|
||||
if (!file)
|
||||
return NULL;
|
||||
if (f->node.procedence == LIBISO_NEW) {
|
||||
file->path = f->loc.path; /*TODO strdup? it needs to be free on clear then */
|
||||
file->real_dev = f->node.attrib.st_dev;
|
||||
file->real_ino = f->node.attrib.st_ino;
|
||||
file->src = iso_file_src_from_path(file->path);
|
||||
} else {
|
||||
file->block = f->loc.block;
|
||||
file->prev_img = 1;
|
||||
@ -26,14 +34,28 @@ iso_file_new(struct iso_tree_node_file *f)
|
||||
* number is good enouht for this. Moreover, when we are modifying
|
||||
* an image, we will modify file->block with the block where the
|
||||
* file needs to be written in the new image. So, we store the block
|
||||
* in original image here, because we will need to use it for
|
||||
* reading file contents */
|
||||
* in original image here */
|
||||
file->real_ino = f->loc.block;
|
||||
file->src = iso_file_src_from_prev_img(t->src, f->loc.block,
|
||||
f->node.attrib.st_size);
|
||||
}
|
||||
if (!file->src)
|
||||
goto creation_error;
|
||||
file->size = file->src->get_size(file->src);
|
||||
|
||||
if (file->size != f->node.attrib.st_size) {
|
||||
char msg[PATH_MAX + 32];
|
||||
/* can only happen on path files */
|
||||
assert(f->node.procedence == LIBISO_NEW);
|
||||
sprintf(msg, "Size of file %s has changed\n", file->path);
|
||||
iso_msg_sorry(LIBISO_CANT_READ_FILE, msg);
|
||||
}
|
||||
file->size = f->node.attrib.st_size;
|
||||
file->nlink = 1;
|
||||
file->sort_weight = f->sort_weight;
|
||||
return file;
|
||||
creation_error:;
|
||||
free(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
@ -75,6 +97,7 @@ iso_file_table_node_new(struct iso_file *file)
|
||||
static void
|
||||
iso_file_table_node_free(struct iso_file_hash_node *node)
|
||||
{
|
||||
iso_file_src_free(node->file->src);
|
||||
free(node->file);
|
||||
free(node);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ struct iso_file {
|
||||
dev_t real_dev;
|
||||
ino_t real_ino; /**< for lookup by inode caching */
|
||||
int sort_weight;
|
||||
struct iso_file_src *src;
|
||||
};
|
||||
|
||||
struct iso_file_hash_node {
|
||||
@ -44,12 +45,14 @@ struct iso_file_table {
|
||||
};
|
||||
|
||||
struct iso_tree_node_file;
|
||||
struct ecma119_write_target;
|
||||
|
||||
/**
|
||||
* Create a struct that represents the specified iso_tree_node_file,
|
||||
* suitable to be stored into the table,
|
||||
*/
|
||||
struct iso_file *iso_file_new(struct iso_tree_node_file*);
|
||||
struct iso_file *iso_file_new(struct ecma119_write_target *t,
|
||||
struct iso_tree_node_file*);
|
||||
|
||||
struct iso_file_table *iso_file_table_new(int cache_inodes);
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
/*
|
||||
* Implementation of iso_file_src for:
|
||||
*
|
||||
* a) read from local filesystem files
|
||||
* b) read from previous session / image files
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
@ -10,9 +17,24 @@
|
||||
|
||||
#include "file_src.h"
|
||||
#include "messages.h"
|
||||
#include "libisofs.h"
|
||||
#include "util.h"
|
||||
|
||||
#define BLOCK_SIZE 2048
|
||||
|
||||
|
||||
void iso_file_src_free(struct iso_file_src *src)
|
||||
{
|
||||
src->free_data(src);
|
||||
free(src);
|
||||
}
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* A) FILE SRC FOR LOCAL FILESYSTEM FILES
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
struct local_file_data {
|
||||
int fd; /* the file descriptor, once the file is opened */
|
||||
off_t size; /* file size */
|
||||
@ -117,7 +139,10 @@ off_t lf_get_size(struct iso_file_src *src)
|
||||
static
|
||||
void lf_free_data(struct iso_file_src *src)
|
||||
{
|
||||
free(src->data);
|
||||
struct local_file_data *data;
|
||||
data = (struct local_file_data*) src->data;
|
||||
free(data->path);
|
||||
free(data);
|
||||
}
|
||||
|
||||
struct iso_file_src*
|
||||
@ -161,3 +186,121 @@ iso_file_src_from_path(const char *path)
|
||||
src->data = data;
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* B) FILE SRC FOR PREVIOUS IMAGE FILES
|
||||
* ==========================================================================
|
||||
*/
|
||||
|
||||
struct prev_img_file_data {
|
||||
int block; /* block where image begins */
|
||||
off_t size; /* file size */
|
||||
int nblocks; /* file size in blocks */
|
||||
int current; /* last block read from file */
|
||||
int error;
|
||||
struct data_source *src; /* source for reading from previous image */
|
||||
};
|
||||
|
||||
static
|
||||
int pi_open(struct iso_file_src *src)
|
||||
{
|
||||
struct prev_img_file_data *data;
|
||||
assert(src);
|
||||
|
||||
data = (struct prev_img_file_data*) src->data;
|
||||
data->current = data->block;
|
||||
data->error = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void pi_close(struct iso_file_src *src)
|
||||
{
|
||||
/* nothing needed */
|
||||
return;
|
||||
}
|
||||
|
||||
static
|
||||
int pi_read_block(struct iso_file_src *src, unsigned char *buffer)
|
||||
{
|
||||
int res;
|
||||
struct prev_img_file_data *data;
|
||||
assert(src);
|
||||
assert(buffer);
|
||||
|
||||
data = (struct prev_img_file_data*) src->data;
|
||||
|
||||
if (data->current >= data->block + data->nblocks) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data->error) {
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
data->current++;
|
||||
return -2;
|
||||
}
|
||||
|
||||
res = data->src->read_block(data->src, data->current++, buffer);
|
||||
if (res < 0) {
|
||||
iso_msg_sorry(LIBISO_CANT_READ_IMG,
|
||||
"Problem reading file from previous image");
|
||||
/* fill buffer with 0s and return */
|
||||
memset(buffer, 0, BLOCK_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data->current >= data->block + data->nblocks) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
off_t pi_get_size(struct iso_file_src *src)
|
||||
{
|
||||
struct prev_img_file_data *data;
|
||||
assert(src);
|
||||
|
||||
data = (struct prev_img_file_data*) src->data;
|
||||
return data->size;
|
||||
}
|
||||
|
||||
static
|
||||
void pi_free_data(struct iso_file_src *src)
|
||||
{
|
||||
free(src->data);
|
||||
}
|
||||
|
||||
struct iso_file_src*
|
||||
iso_file_src_from_prev_img(struct data_source* data_src, int block, off_t size)
|
||||
{
|
||||
struct iso_file_src *src;
|
||||
struct prev_img_file_data *data;
|
||||
|
||||
data = malloc(sizeof(struct prev_img_file_data));
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
src = malloc(sizeof(struct iso_file_src));
|
||||
if (!src) {
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->block = block;
|
||||
data->size = size;
|
||||
data->nblocks = div_up(size, BLOCK_SIZE);
|
||||
data->src = data_src;
|
||||
|
||||
src->open = pi_open;
|
||||
src->close = pi_close;
|
||||
src->read_block = pi_read_block;
|
||||
src->get_size = pi_get_size;
|
||||
src->free_data = pi_free_data;
|
||||
|
||||
src->data = data;
|
||||
return src;
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct data_source;
|
||||
|
||||
struct iso_file_src {
|
||||
|
||||
/**
|
||||
@ -74,7 +76,17 @@ struct iso_file_src {
|
||||
struct iso_file_src* iso_file_src_from_path(const char *path);
|
||||
|
||||
/**
|
||||
* close and free a iso_file_src
|
||||
* Get a iso_file_src() for reading from a previous image file.
|
||||
* @param src data_source to read from previous image. It is not freed,
|
||||
* so you need to free it when no more needed.
|
||||
* @param block block on image where file begins
|
||||
* @param nblocks number of block of the file
|
||||
*/
|
||||
struct iso_file_src*
|
||||
iso_file_src_from_prev_img(struct data_source* src, int block, off_t size);
|
||||
|
||||
/**
|
||||
* free a iso_file_src
|
||||
*/
|
||||
void iso_file_src_free(struct iso_file_src *src);
|
||||
|
||||
|
@ -36,7 +36,16 @@ create_node(struct ecma119_write_target *t,
|
||||
struct iso_file *file;
|
||||
file = iso_file_table_lookup(t->file_table, iso_f);
|
||||
if ( file == NULL ) {
|
||||
file = iso_file_new(iso_f);
|
||||
file = iso_file_new(t, iso_f);
|
||||
if (!file) {
|
||||
/*
|
||||
* That was an error.
|
||||
* TODO currently this cause the file to be ignored... Maybe
|
||||
* throw an error is a better alternative
|
||||
*/
|
||||
joliet_tree_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
iso_file_table_add_file(t->file_table, file);
|
||||
}
|
||||
ret->info.file = file;
|
||||
|
Loading…
Reference in New Issue
Block a user