Migration to iso_file_src in file writing function.

This commit is contained in:
Vreixo Formoso Lopes 2007-09-26 07:47:45 +00:00
parent 8de9d35873
commit f811234b8f
8 changed files with 246 additions and 74 deletions

View File

@ -20,6 +20,7 @@
#include "tree.h" #include "tree.h"
#include "util.h" #include "util.h"
#include "file.h" #include "file.h"
#include "file_src.h"
#include "libisofs.h" #include "libisofs.h"
#include "libburn/libburn.h" #include "libburn/libburn.h"
#include "eltorito.h" #include "eltorito.h"
@ -553,68 +554,37 @@ wr_dir_records(struct ecma119_write_target *t, uint8_t *buf)
static void static void
wr_files(struct ecma119_write_target *t, uint8_t *buf) wr_files(struct ecma119_write_target *t, uint8_t *buf)
{ {
int res;
struct state_files *f_st = &t->state_files; struct state_files *f_st = &t->state_files;
size_t nread;
struct iso_file *f = t->filelist[f_st->file]; struct iso_file *f = t->filelist[f_st->file];
if (f->prev_img) { if (!f_st->src) {
int block;
assert( !t->ms_block && t->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]; char msg[PATH_MAX + 14];
sprintf(msg, "Writing file %s", path); sprintf(msg, "Writing file %s", f->path);
iso_msg_debug(msg); iso_msg_debug(msg);
}
f_st->data_len = f->size; f_st->src = f->src;
f_st->fd = fopen(path, "r"); if ( f->src->open(f->src) <= 0) {
if (!f_st->fd) {
//FIXME instead of exit, just print a msg error and //FIXME instead of exit, just print a msg error and
//skip file (what about reading from /dev/zero? instead) //skip file (what about reading from /dev/zero? instead)
err(1, "couldn't open %s for reading", path); /* can only happen with new files */
err(1, "couldn't open %s for reading", f->path);
} }
assert(t->curblock + t->ms_block == f->block); assert(t->curblock + t->ms_block == f->block);
} }
nread = fread(buf, 1, t->block_size, f_st->fd); res = f_st->src->read_block(f_st->src, buf);
f_st->pos += t->block_size; if (res == 0) {
if (nread < 0) { /* we have read the expected bytes from file */
char msg[PATH_MAX + 32]; f_st->src->close(f_st->src);
sprintf(msg, "Problem reading from %s", path); f_st->src = NULL;
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++; f_st->file++;
if (f_st->file >= t->filelist_len) if (f_st->file >= t->filelist_len)
next_state(t); next_state(t);
} }
}
} }
static void static void
@ -932,8 +902,10 @@ bs_free_data(struct burn_source *bs)
free(t->state_data); free(t->state_data);
if (t->joliet) if (t->joliet)
joliet_tree_free(t->joliet_root); 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, struct burn_source *iso_source_new_ecma119(struct iso_volset *volset,

View File

@ -174,13 +174,14 @@ struct ecma119_write_target
/* for writing out files */ /* for writing out files */
struct state_files { struct state_files {
off_t pos; /* The number of bytes we have written // off_t pos; /* The number of bytes we have written
* so far in the current file. // * so far in the current file.
*/ // */
off_t data_len;/* The number of bytes in the currently // off_t data_len;/* The number of bytes in the currently
* open file. // * open file.
*/ // */
FILE *fd; /* 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 int file; /* The index in filelist that we are
* currently writing (or about to write). */ * currently writing (or about to write). */
} state_files; } state_files;

View File

@ -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 * 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. * 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); iso_file_table_add_file(t->file_table, file);
file->ino = ++t->ino; file->ino = ++t->ino;
} else { } else {

View File

@ -2,22 +2,30 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <limits.h>
#include "file.h" #include "file.h"
#include "tree.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?? //TODO: refactor both hash and this hash table into a single one??
struct iso_file * 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)); struct iso_file *file = calloc(1, sizeof(struct iso_file));
if (!file)
return NULL;
if (f->node.procedence == LIBISO_NEW) { if (f->node.procedence == LIBISO_NEW) {
file->path = f->loc.path; /*TODO strdup? it needs to be free on clear then */ 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_dev = f->node.attrib.st_dev;
file->real_ino = f->node.attrib.st_ino; file->real_ino = f->node.attrib.st_ino;
file->src = iso_file_src_from_path(file->path);
} else { } else {
file->block = f->loc.block; file->block = f->loc.block;
file->prev_img = 1; 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 * number is good enouht for this. Moreover, when we are modifying
* an image, we will modify file->block with the block where the * 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 * 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 * in original image here */
* reading file contents */
file->real_ino = f->loc.block; 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->nlink = 1;
file->sort_weight = f->sort_weight; file->sort_weight = f->sort_weight;
return file; return file;
creation_error:;
free(file);
return NULL;
} }
static unsigned int static unsigned int
@ -75,6 +97,7 @@ iso_file_table_node_new(struct iso_file *file)
static void static void
iso_file_table_node_free(struct iso_file_hash_node *node) iso_file_table_node_free(struct iso_file_hash_node *node)
{ {
iso_file_src_free(node->file->src);
free(node->file); free(node->file);
free(node); free(node);
} }

View File

@ -30,6 +30,7 @@ struct iso_file {
dev_t real_dev; dev_t real_dev;
ino_t real_ino; /**< for lookup by inode caching */ ino_t real_ino; /**< for lookup by inode caching */
int sort_weight; int sort_weight;
struct iso_file_src *src;
}; };
struct iso_file_hash_node { struct iso_file_hash_node {
@ -44,12 +45,14 @@ struct iso_file_table {
}; };
struct iso_tree_node_file; struct iso_tree_node_file;
struct ecma119_write_target;
/** /**
* Create a struct that represents the specified iso_tree_node_file, * Create a struct that represents the specified iso_tree_node_file,
* suitable to be stored into the table, * 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); struct iso_file_table *iso_file_table_new(int cache_inodes);

View File

@ -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 <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
@ -10,9 +17,24 @@
#include "file_src.h" #include "file_src.h"
#include "messages.h" #include "messages.h"
#include "libisofs.h"
#include "util.h"
#define BLOCK_SIZE 2048 #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 { struct local_file_data {
int fd; /* the file descriptor, once the file is opened */ int fd; /* the file descriptor, once the file is opened */
off_t size; /* file size */ off_t size; /* file size */
@ -117,7 +139,10 @@ off_t lf_get_size(struct iso_file_src *src)
static static
void lf_free_data(struct iso_file_src *src) 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* struct iso_file_src*
@ -161,3 +186,121 @@ iso_file_src_from_path(const char *path)
src->data = data; src->data = data;
return src; 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;
}

View File

@ -12,6 +12,8 @@
#include <sys/types.h> #include <sys/types.h>
struct data_source;
struct iso_file_src { struct iso_file_src {
/** /**
@ -74,7 +76,17 @@ struct iso_file_src {
struct iso_file_src* iso_file_src_from_path(const char *path); 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); void iso_file_src_free(struct iso_file_src *src);

View File

@ -36,7 +36,16 @@ create_node(struct ecma119_write_target *t,
struct iso_file *file; struct iso_file *file;
file = iso_file_table_lookup(t->file_table, iso_f); file = iso_file_table_lookup(t->file_table, iso_f);
if ( file == NULL ) { 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); iso_file_table_add_file(t->file_table, file);
} }
ret->info.file = file; ret->info.file = file;