#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#include "isoburn.h"
Go to the source code of this file.
Data Structures | |
struct | isoburn_cache_tile |
struct | isoburn_cached_drive |
Defines | |
#define | Libisoburn_tile_blockS 32 |
#define | Libisoburn_cache_tileS 32 |
#define | Libisoburn_max_agE 2000000000 |
Functions | |
static int | ds_inc_age (struct isoburn_cached_drive *icd, int idx, int flag) |
int | ds_read_block (IsoDataSource *src, uint32_t lba, uint8_t *buffer) |
static int | ds_open (IsoDataSource *src) |
static int | ds_close (IsoDataSource *src) |
static void | ds_free_data (IsoDataSource *src) |
int | isoburn_data_source_shutdown (IsoDataSource *src, int flag) |
Disable read capabilities of a data source which was originally created by isoburn_data_source_new(). | |
IsoDataSource * | isoburn_data_source_new (struct burn_drive *d) |
Get a data source suitable for read from a drive using burn_read_data() function. |
#define Libisoburn_cache_tileS 32 |
Definition at line 42 of file data_source.c.
#define Libisoburn_max_agE 2000000000 |
Definition at line 65 of file data_source.c.
Referenced by ds_inc_age().
#define Libisoburn_tile_blockS 32 |
Definition at line 38 of file data_source.c.
Referenced by ds_read_block().
static int ds_close | ( | IsoDataSource * | src | ) | [static] |
Definition at line 198 of file data_source.c.
{ /* nothing to do, device is always grabbed */ return 1; }
static void ds_free_data | ( | IsoDataSource * | src | ) | [static] |
Definition at line 204 of file data_source.c.
{ /* nothing to do */; if(src->data != NULL) free(src->data); src->data= NULL; }
static int ds_inc_age | ( | struct isoburn_cached_drive * | icd, | |
int | idx, | |||
int | flag | |||
) | [static] |
Definition at line 256 of file data_source.c.
References isoburn_cached_drive::current_age, Libisoburn_max_agE, and isoburn_cached_drive::tiles.
Referenced by ds_read_block().
{ int i; (icd->current_age)++; if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */ for(i= 0; i<Libisoburn_cache_tileS; i++) (icd->tiles)[i].age= 0; icd->current_age= 1; } (icd->tiles)[idx].age= icd->current_age; return(1); }
static int ds_open | ( | IsoDataSource * | src | ) | [static] |
Definition at line 192 of file data_source.c.
{ /* nothing to do, device is always grabbed */ return 1; }
int ds_read_block | ( | IsoDataSource * | src, | |
uint32_t | lba, | |||
uint8_t * | buffer | |||
) |
Definition at line 70 of file data_source.c.
References isoburn_cache_tile::age, isoburn_cache_tile::cache_data, isoburn_cache_tile::cache_hits, isoburn_cache_tile::cache_lba, isoburn_cached_drive::drive, ds_inc_age(), isoburn_msgs_submit(), isoburn_cache_tile::last_aligned_error_lba, isoburn_cache_tile::last_error_lba, Libisoburn_tile_blockS, and isoburn_cached_drive::tiles.
{ int ret, i, oldest, oldest_age; struct burn_drive *d; off_t count; uint32_t aligned_lba; char msg[80]; struct isoburn_cache_tile *tiles; struct isoburn_cached_drive *icd; if(src == NULL || buffer == NULL) /* It is not required by the specs of libisofs but implicitely assumed by its current implementation that a data source read result <0 is a valid libisofs error code. */ return ISO_NULL_POINTER; icd = (struct isoburn_cached_drive *) src->data; d = (struct burn_drive*) icd->drive; if(d == NULL) { /* This would happen if libisoburn saw output data in the fifo and performed early drive release and afterwards libisofs still tries to read data. That would constitute a bad conceptual problem in libisoburn. */ isoburn_msgs_submit(NULL, 0x00060000, "Programming error: Drive released while libisofs still attempts to read", 0, "FATAL", 0); return ISO_ASSERT_FAILURE; } tiles = (struct isoburn_cache_tile *) icd->tiles; aligned_lba= lba & ~(Libisoburn_tile_blockS - 1); for(i=0; i<Libisoburn_cache_tileS; i++) { if(aligned_lba == tiles[i].cache_lba && tiles[i].cache_lba != 0xffffffff) { (tiles[i].cache_hits)++; memcpy(buffer, tiles[i].cache_data + (lba - aligned_lba) * 2048, 2048); count= 2048; ds_inc_age(icd, i, 0); return 1; } } /* find oldest tile */ oldest_age= Libisoburn_max_agE; oldest= 0; for(i= 0; i<Libisoburn_cache_tileS; i++) { if(tiles[i].cache_lba == 0xffffffff) { oldest= i; break; } if(tiles[i].age<oldest_age) { oldest_age= tiles[i].age; oldest= i; } } tiles[oldest].cache_lba= 0xffffffff; /* invalidate cache */ if(tiles[oldest].last_aligned_error_lba == aligned_lba) { ret = 0; } else { ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048, (char *) tiles[oldest].cache_data, Libisoburn_tile_blockS * 2048, &count, 2); } if (ret <= 0 ) { tiles[oldest].last_aligned_error_lba = aligned_lba; /* Read-ahead failure ? Try to read 2048 directly. */ if(tiles[oldest].last_error_lba == lba) ret = 0; else ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer, 2048, &count, 0); if (ret > 0) return 1; tiles[oldest].last_error_lba = lba; #ifdef ISO_DATA_SOURCE_MISHAP ret= ISO_DATA_SOURCE_MISHAP; #else /* <<< pre libisofs-0.6.7 */ /* It is not required by the specs of libisofs but implicitely assumed ... But it is not possible to ignore FAILURE. libisofs insists in original error codes, i.e. libisoburn cannot change severity FAILURE associated with ISO_FILE_READ_ERROR. So ISO_FILE_READ_ERROR is not an option and libisoburn has to misuse ISO_FILE_CANT_WRITE, which is actually for image generation and not for image reading. This is quite wrong, although the error message text is unclear enough to make it appear plausible. */ ret= ISO_FILE_CANT_WRITE; #endif if(ret >= 0) ret = -1; sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret); isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0); return ret; } #ifdef Libisoburn_read_cache_reporT fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n", oldest, tiles[oldest].cache_hits, aligned_lba, (int) count); #endif tiles[oldest].cache_lba= aligned_lba; tiles[oldest].cache_hits= 1; ds_inc_age(icd, oldest, 0); memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048); count= 2048; return 1; }
IsoDataSource* isoburn_data_source_new | ( | struct burn_drive * | d | ) |
Get a data source suitable for read from a drive using burn_read_data() function.
d | drive to read from. Must be grabbed. |
Definition at line 225 of file data_source.c.
References isoburn_cache_tile::age, isoburn_cache_tile::cache_hits, isoburn_cache_tile::cache_lba, isoburn_cached_drive::current_age, isoburn_cached_drive::drive, isoburn_cache_tile::last_aligned_error_lba, isoburn_cache_tile::last_error_lba, and isoburn_cached_drive::tiles.
Referenced by isoburn_read_image().
{ IsoDataSource *ret; struct isoburn_cached_drive *icd= NULL; int i; if (d==NULL) return NULL; ret = malloc(sizeof(IsoDataSource)); icd = calloc(1,sizeof(struct isoburn_cached_drive)); if (ret == NULL || icd == NULL) return NULL; ret->refcount = 1; ret->read_block = ds_read_block; ret->open = ds_open; ret->close = ds_close; ret->free_data = ds_free_data; ret->data = icd; icd->drive = d; icd->current_age= 0; for(i= 0; i<Libisoburn_cache_tileS; i++) { icd->tiles[i].cache_lba = 0xffffffff; icd->tiles[i].cache_hits = 0; icd->tiles[i].last_error_lba = 0xffffffff; icd->tiles[i].last_aligned_error_lba = 0xffffffff; icd->tiles[i].age= 0; } return ret; }
int isoburn_data_source_shutdown | ( | IsoDataSource * | src, | |
int | flag | |||
) |
Disable read capabilities of a data source which was originally created by isoburn_data_source_new().
After this any attempt to read will yield a FATAL programming error event. This is usually done to allow libburn to release the drive while libisofs still holds a reference to the data source object. libisofs is not supposed to use this object for reading any more, nevertheless. The disabled state of the data source is a safety fence around this daring situation.
src | The data source to be disabled | |
flag | unused yet |
Definition at line 213 of file data_source.c.
References isoburn_cached_drive::drive.
Referenced by isoburn_prepare_disc_aux().
{ struct isoburn_cached_drive *icd; if(src==NULL) return(0); icd= (struct isoburn_cached_drive *) src->data; icd->drive= NULL; return(1); }