#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 41 of file data_source.c.
Referenced by ds_inc_age(), ds_read_block(), and isoburn_data_source_new().
#define Libisoburn_max_agE 2000000000 |
#define Libisoburn_tile_blockS 32 |
static int ds_close | ( | IsoDataSource * | src | ) | [static] |
static void ds_free_data | ( | IsoDataSource * | src | ) | [static] |
Definition at line 203 of file data_source.c.
Referenced by isoburn_data_source_new().
00204 { 00205 /* nothing to do */; 00206 if(src->data != NULL) 00207 free(src->data); 00208 src->data= NULL; 00209 }
static int ds_inc_age | ( | struct isoburn_cached_drive * | icd, | |
int | idx, | |||
int | flag | |||
) | [static] |
Definition at line 255 of file data_source.c.
References isoburn_cached_drive::current_age, Libisoburn_cache_tileS, Libisoburn_max_agE, and isoburn_cached_drive::tiles.
Referenced by ds_read_block().
00256 { 00257 int i; 00258 00259 (icd->current_age)++; 00260 if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */ 00261 for(i= 0; i<Libisoburn_cache_tileS; i++) 00262 (icd->tiles)[i].age= 0; 00263 icd->current_age= 1; 00264 } 00265 (icd->tiles)[idx].age= icd->current_age; 00266 return(1); 00267 }
static int ds_open | ( | IsoDataSource * | src | ) | [static] |
int ds_read_block | ( | IsoDataSource * | src, | |
uint32_t | lba, | |||
uint8_t * | buffer | |||
) |
Definition at line 69 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_cache_tileS, Libisoburn_max_agE, Libisoburn_tile_blockS, and isoburn_cached_drive::tiles.
Referenced by isoburn_data_source_new().
00070 { 00071 int ret, i, oldest, oldest_age; 00072 struct burn_drive *d; 00073 off_t count; 00074 uint32_t aligned_lba; 00075 char msg[80]; 00076 struct isoburn_cache_tile *tiles; 00077 struct isoburn_cached_drive *icd; 00078 00079 if(src == NULL || buffer == NULL) 00080 /* It is not required by the specs of libisofs but implicitely assumed 00081 by its current implementation that a data source read result <0 is 00082 a valid libisofs error code. 00083 */ 00084 return ISO_NULL_POINTER; 00085 00086 icd = (struct isoburn_cached_drive *) src->data; 00087 d = (struct burn_drive*) icd->drive; 00088 00089 if(d == NULL) { 00090 /* This would happen if libisoburn saw output data in the fifo and 00091 performed early drive release and afterwards libisofs still tries 00092 to read data. 00093 That would constitute a bad conceptual problem in libisoburn. 00094 */ 00095 isoburn_msgs_submit(NULL, 0x00060000, 00096 "Programming error: Drive released while libisofs still attempts to read", 00097 0, "FATAL", 0); 00098 return ISO_ASSERT_FAILURE; 00099 } 00100 00101 tiles = (struct isoburn_cache_tile *) icd->tiles; 00102 00103 aligned_lba= lba & ~(Libisoburn_tile_blockS - 1); 00104 00105 for(i=0; i<Libisoburn_cache_tileS; i++) { 00106 if(aligned_lba == tiles[i].cache_lba && tiles[i].cache_lba != 0xffffffff) { 00107 (tiles[i].cache_hits)++; 00108 memcpy(buffer, tiles[i].cache_data + (lba - aligned_lba) * 2048, 2048); 00109 count= 2048; 00110 ds_inc_age(icd, i, 0); 00111 return 1; 00112 } 00113 } 00114 00115 /* find oldest tile */ 00116 oldest_age= Libisoburn_max_agE; 00117 oldest= 0; 00118 for(i= 0; i<Libisoburn_cache_tileS; i++) { 00119 if(tiles[i].cache_lba == 0xffffffff) { 00120 oldest= i; 00121 break; 00122 } 00123 if(tiles[i].age<oldest_age) { 00124 oldest_age= tiles[i].age; 00125 oldest= i; 00126 } 00127 } 00128 00129 tiles[oldest].cache_lba= 0xffffffff; /* invalidate cache */ 00130 if(tiles[oldest].last_aligned_error_lba == aligned_lba) { 00131 ret = 0; 00132 } else { 00133 ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048, 00134 (char *) tiles[oldest].cache_data, 00135 Libisoburn_tile_blockS * 2048, &count, 2); 00136 } 00137 if (ret <= 0 ) { 00138 tiles[oldest].last_aligned_error_lba = aligned_lba; 00139 00140 /* Read-ahead failure ? Try to read 2048 directly. */ 00141 if(tiles[oldest].last_error_lba == lba) 00142 ret = 0; 00143 else 00144 ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer, 00145 2048, &count, 0); 00146 if (ret > 0) 00147 return 1; 00148 tiles[oldest].last_error_lba = lba; 00149 00150 #ifdef ISO_DATA_SOURCE_MISHAP 00151 ret= ISO_DATA_SOURCE_MISHAP; 00152 #else 00153 /* <<< pre libisofs-0.6.7 */ 00154 /* It is not required by the specs of libisofs but implicitely assumed 00155 ... 00156 But it is not possible to ignore FAILURE. 00157 libisofs insists in original error codes, i.e. libisoburn cannot 00158 change severity FAILURE associated with ISO_FILE_READ_ERROR. 00159 So ISO_FILE_READ_ERROR is not an option and libisoburn has to 00160 misuse ISO_FILE_CANT_WRITE, which is actually for image generation 00161 and not for image reading. 00162 This is quite wrong, although the error message text is unclear 00163 enough to make it appear plausible. 00164 */ 00165 ret= ISO_FILE_CANT_WRITE; 00166 #endif 00167 00168 if(ret >= 0) 00169 ret = -1; 00170 sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret); 00171 isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0); 00172 return ret; 00173 } 00174 00175 #ifdef Libisoburn_read_cache_reporT 00176 fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n", 00177 oldest, tiles[oldest].cache_hits, aligned_lba, (int) count); 00178 #endif 00179 00180 tiles[oldest].cache_lba= aligned_lba; 00181 tiles[oldest].cache_hits= 1; 00182 ds_inc_age(icd, oldest, 0); 00183 00184 memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048); 00185 count= 2048; 00186 00187 return 1; 00188 }
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 224 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, ds_close(), ds_free_data(), ds_open(), ds_read_block(), isoburn_cache_tile::last_aligned_error_lba, isoburn_cache_tile::last_error_lba, Libisoburn_cache_tileS, and isoburn_cached_drive::tiles.
Referenced by isoburn_read_image().
00225 { 00226 IsoDataSource *ret; 00227 struct isoburn_cached_drive *icd= NULL; 00228 int i; 00229 00230 if (d==NULL) 00231 return NULL; 00232 ret = malloc(sizeof(IsoDataSource)); 00233 icd = calloc(1,sizeof(struct isoburn_cached_drive)); 00234 if (ret == NULL || icd == NULL) 00235 return NULL; 00236 ret->refcount = 1; 00237 ret->read_block = ds_read_block; 00238 ret->open = ds_open; 00239 ret->close = ds_close; 00240 ret->free_data = ds_free_data; 00241 ret->data = icd; 00242 icd->drive = d; 00243 icd->current_age= 0; 00244 for(i= 0; i<Libisoburn_cache_tileS; i++) { 00245 icd->tiles[i].cache_lba = 0xffffffff; 00246 icd->tiles[i].cache_hits = 0; 00247 icd->tiles[i].last_error_lba = 0xffffffff; 00248 icd->tiles[i].last_aligned_error_lba = 0xffffffff; 00249 icd->tiles[i].age= 0; 00250 } 00251 return ret; 00252 }
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 212 of file data_source.c.
References isoburn_cached_drive::drive.
Referenced by isoburn_prepare_disc_aux().
00213 { 00214 struct isoburn_cached_drive *icd; 00215 00216 if(src==NULL) 00217 return(0); 00218 icd= (struct isoburn_cached_drive *) src->data; 00219 icd->drive= NULL; 00220 return(1); 00221 }