Browse Source

Migration to iso_file_src in file writing function.

master
Vreixo Formoso Lopes 13 years ago
parent
commit
f811234b8f
8 changed files with 246 additions and 74 deletions
  1. +29
    -57
      libisofs/ecma119.c
  2. +8
    -7
      libisofs/ecma119.h
  3. +10
    -1
      libisofs/ecma119_tree.c
  4. +28
    -5
      libisofs/file.c
  5. +4
    -1
      libisofs/file.h
  6. +144
    -1
      libisofs/file_src.c
  7. +13
    -1
      libisofs/file_src.h
  8. +10
    -1
      libisofs/joliet.c

+ 29
- 57
libisofs/ecma119.c View File

@ -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,


+ 8
- 7
libisofs/ecma119.h View File

@ -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;


+ 10
- 1
libisofs/ecma119_tree.c 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
* 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 {


+ 28
- 5
libisofs/file.c View File

@ -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);
}


+ 4
- 1
libisofs/file.h View File

@ -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);


+ 144
- 1
libisofs/file_src.c 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 <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;
}

+ 13
- 1
libisofs/file_src.h View File

@ -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);


+ 10
- 1
libisofs/joliet.c View File

@ -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…
Cancel
Save