diff --git a/xorriso/xorriso.c b/xorriso/xorriso.c index ba125db3..d7d4bf7b 100644 --- a/xorriso/xorriso.c +++ b/xorriso/xorriso.c @@ -123,13 +123,13 @@ or /* The official xorriso options API. "No shortcuts" */ #include "xorriso.h" -/* The inner isofs- and burn-library interface */ -#include "xorrisoburn.h" - /* The inner description of XorrisO */ #define Xorriso_is_xorriso_selF 1 #include "xorriso_private.h" +/* The inner isofs- and burn-library interface */ +#include "xorrisoburn.h" + /* ------------------------------------------------------------------------ */ @@ -2945,6 +2945,12 @@ char *Spotlist__quality_name(int quality, char name[80], int flag) strcpy(name, "good"); else if(quality == Xorriso_read_quality_sloW) strcpy(name, "slow"); + else if(quality == Xorriso_read_quality_partiaL) + strcpy(name, "partial"); + else if(quality == Xorriso_read_quality_valiD) + strcpy(name, "valid"); + else if(quality == Xorriso_read_quality_invaliD) + strcpy(name, "invalid"); else if(quality == Xorriso_read_quality_off_tracK) strcpy(name, "off track"); else if(quality == Xorriso_read_quality_untesteD) @@ -2959,6 +2965,266 @@ char *Spotlist__quality_name(int quality, char name[80], int flag) /* ---------------------------- End SpotlisT ------------------------------ */ +/* ---------------------------- SectorbitmaP ------------------------------ */ + +struct SectorbitmaP { + int sectors; + int sector_size; + unsigned char *map; + int map_size; +}; + +int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag); + + +int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size, + int flag) +{ + struct SectorbitmaP *m; + + m= TSOB_FELD(struct SectorbitmaP,1); + if(m==NULL) + return(-1); + *o= m; + m->sectors= sectors; + m->sector_size= sector_size; + m->map= NULL; + m->map_size= sectors / 8 + 1; + + m->map= calloc(m->map_size, 1); + if(m->map == NULL) + goto failure; + return(1); +failure:; + Sectorbitmap_destroy(o, 0); + return(-1); +} + + +int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag) +{ + if((*o) == NULL) + return(0); + if((*o)->map != NULL) + free((char *) (*o)->map); + free((char *) *o); + *o= NULL; + return(1); +} + + +int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg, + int *os_errno, int flag) +{ + int ret, fd= -1, sectors, sector_size, i, todo, map_size; + unsigned char *map; + unsigned char buf[1024]; + + *os_errno= 0; + if(msg != NULL) + msg[0]= 0; + fd= open(path, O_RDONLY); + if(fd == -1) { + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Cannot open path "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + return(0); + } + ret= read(fd, buf, 32); + if(ret < 32) { +wrong_filetype:; + if(ret == -1) + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Not a sector bitmap file: "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + ret= 0; goto ex; + } + if(strncmp((char *) buf, "xorriso sector bitmap v1 ", 32) != 0) + {ret= 0; goto wrong_filetype;} + ret= read(fd, buf, 8); + if(ret < 4) + goto wrong_filetype; + sectors= (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + sector_size= (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; + if(sectors <= 0 || sector_size <= 0) + goto wrong_filetype; + ret= Sectorbitmap_new(o, sectors, sector_size, 0); + if(ret <= 0) { + if(msg != NULL) + sprintf(msg, "Cannot allocate bitmap memory for %d sectors", sectors); + ret= -1; goto ex; + } + map= (*o)->map; + map_size= (*o)->map_size; + for(i= 0; i < map_size; i+= sizeof(buf)) { + todo= sizeof(buf); + if(i + todo > map_size) + todo= map_size - i; + ret= read(fd, buf, todo); + if(ret != todo) + goto wrong_filetype; + memcpy(map + i, buf, todo); + } + ret= 1; +ex:; + if(fd != -1) + close(fd); + if(ret <= 0) + Sectorbitmap_destroy(o, 0); + return(ret); +} + + +int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *msg, + int *os_errno, int flag) +{ + int ret, fd= -1, j; + unsigned char buf[32]; + + *os_errno= 0; + fd= open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if(fd == -1) { + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Cannot open path "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + return(0); + } + ret= write(fd, "xorriso sector bitmap v1 ", 32); + if(ret != 32) { +cannot_write:; + *os_errno= errno; + if(msg != NULL) { + strcpy(msg, "Cannot write to "); + Text_shellsafe(path, msg+strlen(msg), 0); + } + ret= 0; goto ex; + } + for(j= 0; j < 4; j++) { + buf[j]= o->sectors >> (24 - j * 8); + buf[j+4]= o->sector_size >> (24 - j * 8); + } + ret= write(fd, buf, 8); + if(ret != 8) + goto cannot_write; + ret= write(fd, o->map, o->map_size); + if(ret != o->map_size) + goto cannot_write; + + ret= 1; +ex:; + if(fd != -1) + close(fd); + return(ret); +} + + +/* @param flag bit0= sector bit value +*/ +int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag) +{ + if(sector < 0 || sector >= o->sectors) + return(0); + if(flag & 1) + o->map[sector / 8]|= 1 << (sector % 8); + else + o->map[sector / 8]&= ~(1 << (sector % 8)); + return(1); +} + + +/* @param flag bit0= sector bit value +*/ +int Sectorbitmap_set_range(struct SectorbitmaP *o, + int start_sector, int sectors, int flag) +{ + int start_i, end_i, i; + unsigned char value; + + if(start_sector < 0 || start_sector + sectors > o->sectors || sectors < 1) + return(0); + if(flag & 1) + value= ~0; + else + value= 0; + start_i= start_sector / 8; + end_i= (start_sector + sectors - 1) / 8; + for(i= start_sector; i / 8 == start_i && i < start_sector + sectors; i++) + Sectorbitmap_set(o, i, flag & 1); + for(i= start_i + 1; i < end_i; i++) + o->map[i]= value; + if(end_i > start_i) + for(i= end_i * 8; i < start_sector + sectors; i++) + Sectorbitmap_set(o, i, flag & 1); + return(1); +} + + +int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag) +{ + if(sector < 0 || sector >= o->sectors) + return(0); + return(!! (o->map[sector / 8] & (1 << (sector % 8)))); +} + + +int Sectorbitmap_get_layout(struct SectorbitmaP *o, + int *sectors, int *sector_size, int flag) +{ + *sectors= o->sectors; + *sector_size= o->sector_size; + return(1); +} + + +int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to, + int flag) +{ + int i, run_start, run_value, start_sec, limit_sec, start_aligned; + int end_complete; + + if(from->sectors * from->sector_size > to->sectors * to->sector_size) + return(-1); + if(from->sector_size == to->sector_size) { + for(i= 0; i < from->map_size; i++) + to->map[i]= from->map[i]; + return(1); + } + run_start= 0; + run_value= Sectorbitmap_is_set(from, 0, 0); + for(i= 1; i <= from->sectors; i++) { + if(i < from->sectors) + if(Sectorbitmap_is_set(from, i, 0) == run_value) + continue; + start_sec= run_start * from->sector_size / to->sector_size; + start_aligned= + (start_sec * to->sector_size == run_start * from->sector_size); + limit_sec= i * from->sector_size / to->sector_size; + end_complete= (limit_sec * to->sector_size == i * from->sector_size); + if(run_value) { + if(!start_aligned) + start_sec++; + } else { + if(!end_complete) + limit_sec++; + } + if(start_sec < limit_sec) + Sectorbitmap_set_range(to, start_sec, limit_sec - 1 - start_sec, + !!run_value); + run_value= !run_value; + run_start= i; + } + return(1); +} + + +/* -------------------------- End SectorbitmaP ---------------------------- */ + /* ---------------------------- CheckmediajoB ----------------------------- */ int Checkmediajob_new(struct CheckmediajoB **o, int flag) @@ -2972,10 +3238,15 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag) m->min_lba= -1; m->max_lba= -1; m->min_block_size= 16; - m->mode= 1; + m->mode= 0; m->start_time= time(NULL); m->time_limit= -1; m->item_limit= -1; + m->data_to_path[0]= 0; + m->data_to_fd= -1; + m->sector_map_path[0]= 0; + m->sector_map= NULL; + m->retry= 0; return(1); } @@ -2984,6 +3255,7 @@ int Checkmediajob_destroy(struct CheckmediajoB **o, int flag) { if((*o) == NULL) return(0); + Sectorbitmap_destroy(&((*o)->sector_map), 0); free((char *) *o); *o= NULL; return(1); @@ -8376,7 +8648,70 @@ int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag) return(1); } + +int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, + struct SpotlisT *spotlist, + int sector_size, + struct SectorbitmaP **map, + int flag) +{ + struct SectorbitmaP *m; + int map_sectors= -1, map_sector_size= -1; + int list_sectors, list_blocks, sector_blocks; + int replace_map= 0, count, i, lba, blocks, quality, ret; + + sector_blocks= sector_size / 2048; + if(*map != NULL) + Sectorbitmap_get_layout(*map, &map_sectors, &map_sector_size, 0); + + count= Spotlist_count(spotlist, 0); + list_blocks= 0; + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + if(lba + blocks > list_blocks) + list_blocks= lba + blocks; + } + + /* >>> ??? insist in list_blocks % sector_blocks == 0 */ + + list_sectors= list_blocks / sector_blocks; + if(list_sectors * sector_blocks < list_blocks) + list_sectors++; + if(*map != NULL && map_sectors * (map_sector_size / 2048) >= list_blocks && + map_sector_size == sector_size) + m= *map; + else { + ret= Sectorbitmap_new(&m, list_sectors, sector_size, 0); + if(ret <= 0) + return(-1); + replace_map= 1; + if(*map != NULL) { + ret= Sectorbitmap_copy(*map, m, 0); + if(ret <= 0) { + Sectorbitmap_destroy(&m, 0); + return(0); + } + } + } + + count= Spotlist_count(spotlist, 0); + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks, + quality >= Xorriso_read_quality_valiD); + } + if(replace_map) { + Sectorbitmap_destroy(map, 0); + *map= m; + } + return(1); +} + /* ---------------------------- Options API ------------------------ */ @@ -8896,7 +9231,11 @@ int Xorriso_option_check_media(struct XorrisO *xorriso, goto ex; for(i= old_idx; i < end_idx; i++) { - if(strncmp(argv[i], "max_lba=", 8) == 0 || + if(strncmp(argv[i], "data_to=", 8) == 0) { + ret= Sfile_str(job->data_to_path, argv[i] + 8, 0); + if(ret <= 0) + goto ex; + } else if(strncmp(argv[i], "max_lba=", 8) == 0 || strncmp(argv[i], "min_lba=", 8) == 0) { num= -1; sscanf(argv[i] + 8, "%lf", &num); @@ -8906,6 +9245,19 @@ int Xorriso_option_check_media(struct XorrisO *xorriso, job->max_lba= num; else job->min_lba= num; + } else if(strncmp(argv[i], "retry=", 6) == 0) { + if(strcmp(argv[i] + 6, "on") == 0) + job->retry= 1; + else if(strcmp(argv[i] + 6, "off") == 0) + job->retry= -1; + else if(strcmp(argv[i] + 6, "default") == 0) + job->retry= 0; + else + goto unknown_value; + } else if(strncmp(argv[i], "sector_map=", 11) == 0) { + ret= Sfile_str(job->sector_map_path, argv[i] + 11, 0); + if(ret <= 0) + goto ex; } else if(strncmp(argv[i], "time_limit=", 11) == 0 || strncmp(argv[i], "item_limit=", 11) == 0 ) { num= -1; @@ -8916,8 +9268,20 @@ int Xorriso_option_check_media(struct XorrisO *xorriso, job->time_limit= num; else job->item_limit= num; + } else if(strncmp(argv[i], "what=", 5) == 0) { + if(strcmp(argv[i]+5, "tracks") == 0) + job->mode= 0; + else if(strcmp(argv[i]+5, "disc")== 0) + job->mode= 1; + else { +unknown_value:; + sprintf(xorriso->info_text, + "-check_media: Unknown value with option %s", argv[i]); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); + ret= 0; goto ex; + } } else { - sprintf(xorriso->info_text, "-check_media: Unknown option %s", argv[i]); + sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]); Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0); ret= 0; goto ex; } @@ -10449,7 +10813,8 @@ int Xorriso_option_help(struct XorrisO *xorriso, int flag) " -check_media [options] --", " Try to read data blocks from media and report about the", " outcome. Several options modify the behavior:", -" min_lba= , max_lba= , time_limit= , item_limit=", +" min_lba= , max_lba= , time_limit= , item_limit= ,", +" data_to= ,", "", "Compatibility emulation (argument list may be ended by --):", " -as mkisofs [-help|-version|-o|-R|-J|-V|-P|-f|-m|-exclude-list|-no-pad|", diff --git a/xorriso/xorriso_private.h b/xorriso/xorriso_private.h index 19325370..67dcc3e5 100644 --- a/xorriso/xorriso_private.h +++ b/xorriso/xorriso_private.h @@ -50,6 +50,7 @@ struct ExclusionS; /* List of -not_* conditions */ struct PermiteM; /* Stack of temporarily altered access permissions */ struct SpotlisT; /* List of intervals with different read qualities */ struct CheckmediajoB; /* Parameters for Xorriso_check_media() */ +struct SectorbitmaP; /* Distiniction between valid and invalid sectors */ /* maximum number of history lines to be reported with -status:long_history */ @@ -453,6 +454,11 @@ int Xorriso_auto_chmod(struct XorrisO *xorriso, char *disk_path, int flag); int Xorriso_protect_stdout(struct XorrisO *xorriso, int flag); +int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, + struct SpotlisT *spotlist, + int sector_size, + struct SectorbitmaP **map, + int flag); int Sfile_str(char target[SfileadrL], char *source, int flag); @@ -632,9 +638,12 @@ char *Spotlist__quality_name(int quality, char name[80], int flag); #define Xorriso_read_quality_gooD 0x7fffffff -#define Xorriso_read_quality_sloW 0x40000000 -#define Xorriso_read_quality_off_tracK 0x08000000 -#define Xorriso_read_quality_untesteD 0x04000000 +#define Xorriso_read_quality_sloW 0x60000000 +#define Xorriso_read_quality_partiaL 0x50000000 +#define Xorriso_read_quality_valiD 0x40000000 +#define Xorriso_read_quality_invaliD 0x3fffffff +#define Xorriso_read_quality_off_tracK 0x20000000 +#define Xorriso_read_quality_untesteD 0x10000000 #define Xorriso_read_quality_unreadablE 0x00000000 @@ -642,5 +651,22 @@ int Checkmediajob_new(struct CheckmediajoB **o, int flag); int Checkmediajob_destroy(struct CheckmediajoB **o, int flag); + +int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size, + int flag); +int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag); +int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg, + int *os_errno, int flag); +int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *msg, + int *os_errno, int flag); +int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag); +int Sectorbitmap_set_range(struct SectorbitmaP *o, + int start_sector, int sectors, int flag); +int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag); + +int Sectorbitmap_get_layout(struct SectorbitmaP *o, + int *sectors, int *sector_size, int flag); + + #endif /* Xorriso_private_includeD */ diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index 629db2f0..ead63963 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.08.09.161311" +#define Xorriso_timestamP "2008.08.11.201604" diff --git a/xorriso/xorrisoburn.c b/xorriso/xorrisoburn.c index 25f54713..31f44e82 100644 --- a/xorriso/xorrisoburn.c +++ b/xorriso/xorrisoburn.c @@ -6557,18 +6557,21 @@ int Xorriso_msinfo(struct XorrisO *xorriso, int *msc1, int *msc2, int flag) return(1); } - +/* @return <=0 error, 1= done, 2= aborted due to limit +*/ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, struct CheckmediajoB *job, int from_lba, int block_count, int read_chunk, int min_block_size, int flag) { - int i, ret, total_count= 0; - int prev_quality= -1, quality= -1; + int i, j, ret, total_count= 0, sectors= -1, sector_size= -1, skip_reading; + int prev_quality= -1, quality= -1, retry= 0, profile_no, is_cd; + int start_sec, end_sec, first_value; + char profile_name[80]; int start_lba= 0; struct burn_drive *drive; struct burn_drive_info *dinfo; - char data[64*1024]; + char data[64*1024], sfe[5*SfileadrL]; off_t data_count, to_read; double pre_read_time, post_read_time, time_diff, total_time_diff= 0; @@ -6576,9 +6579,25 @@ int Xorriso_check_interval(struct XorrisO *xorriso, struct SpotlisT *spotlist, "on attempt to check media readability", 0); if(ret<=0) goto ex; + ret= burn_disc_get_profile(drive, &profile_no, profile_name); + if(ret > 0) + if(profile_no >= 0x08 && profile_no <= 0x0a) + is_cd= 1; + + if(job->sector_map != NULL) { + Sectorbitmap_get_layout(job->sector_map, §ors, §or_size, 0); + sector_size/= 2048; + } + + if(job->retry > 0) + retry= 1; + else if(job-retry == 0 && is_cd) + retry= 1; start_lba= from_lba; - for(i= 0; i < block_count; i+= read_chunk) { + to_read= read_chunk; + for(i= 0; i < block_count; i+= to_read) { + skip_reading= 0; if(job->item_limit > 0 && Spotlist_count(spotlist, 0) + 2 >= job->item_limit) { sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d", @@ -6599,7 +6618,7 @@ abort_check:; if(ret <= 0) goto ex; } - ret= Spotlist_add_item(spotlist, i + from_lba, block_count - 1, + ret= Spotlist_add_item(spotlist, i + from_lba, block_count - i, Xorriso_read_quality_untesteD, 0); if(ret > 0) ret= 2; @@ -6608,27 +6627,103 @@ abort_check:; to_read= read_chunk; if(i + to_read > block_count) to_read= block_count - i; - ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, data, - to_read * (off_t) 2048, &data_count, 4); - post_read_time= Sfile_microtime(0); - time_diff= post_read_time - pre_read_time; - total_time_diff+= time_diff; - total_count++; - if(ret <= 0) { - Xorriso_process_msg_queues(xorriso,0); - quality= Xorriso_read_quality_unreadablE; - if(read_chunk > min_block_size) { + if(is_cd && i + to_read + 2 >= block_count) { + /* Read last 2 blocks of CD track separately, because with TAO tracks + they are always unreadable but with SAO tracks they contain data. + */ + if(to_read > 2) + to_read-= 2; + else if(to_read > 1) + to_read--; + } - /* >>> evaluate min blocks */; +#ifdef NIX + /* >>> this is not yet suitable for min_block_size */ +#endif + if(sector_size == read_chunk && from_lba % read_chunk == 0) { + if(Sectorbitmap_is_set(job->sector_map, (i + from_lba) / read_chunk, 0)) { + quality= Xorriso_read_quality_valiD; + skip_reading= 1; } + } else if(sector_size > 0) { + start_sec= (i + from_lba) / sector_size; + end_sec= (i + to_read + from_lba) / sector_size; + first_value= Sectorbitmap_is_set(job->sector_map, start_sec, 0); + for(j= start_sec; j < end_sec; j++) + if(Sectorbitmap_is_set(job->sector_map, j, 0) != first_value) + break; + to_read= j * sector_size - i - from_lba; + skip_reading= !!first_value; + if(skip_reading) + quality= Xorriso_read_quality_valiD; + } + + if(skip_reading) { + pre_read_time= post_read_time= Sfile_microtime(0); } else { - quality= Xorriso_read_quality_gooD; + data_count= 0; + pre_read_time= Sfile_microtime(0); + ret= burn_read_data(drive, ((off_t) (i + from_lba)) * (off_t) 2048, data, + to_read * (off_t) 2048, &data_count, 4 * !retry); + post_read_time= Sfile_microtime(0); + time_diff= post_read_time - pre_read_time; + total_time_diff+= time_diff; + total_count++; + if(ret <= 0) { + Xorriso_process_msg_queues(xorriso,0); - /* >>> find better threshold than 1.0 */ + if(data_count > 0 && retry) { + if(prev_quality >= 0) { + ret= Spotlist_add_item(spotlist, start_lba, + i + from_lba - start_lba, prev_quality, 0); + if(ret <= 0) + goto ex; + } + ret= Spotlist_add_item(spotlist, i + from_lba, data_count / 2048, + Xorriso_read_quality_partiaL, 0); + if(ret <= 0) + goto ex; + start_lba= i + from_lba + data_count / 2048; + prev_quality= Xorriso_read_quality_unreadablE; + } + quality= Xorriso_read_quality_unreadablE; - if(time_diff > 1.0 && i > 0) - quality= Xorriso_read_quality_sloW; +#ifdef NIX + if(read_chunk > min_block_size) { + + /* >>> evaluate min blocks */; + + } +#endif + + + } else { + quality= Xorriso_read_quality_gooD; + + /* >>> find better threshold than 1.0 */ + + if(time_diff > 1.0 && i > 0) + quality= Xorriso_read_quality_sloW; + } + if(data_count > 0) { + if(job->data_to_fd >= 0) { + ret= lseek(job->data_to_fd, ((off_t) (i + from_lba)) * (off_t) 2048, + SEEK_SET); + if(ret == -1) { +failed_to_write:; + sprintf(xorriso->info_text, "Cannot write %d bytes to lba %d of %s", + (int) data_count, i + from_lba, + Text_shellsafe(job->data_to_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, + "FAILURE", 0); + {ret= 0; goto ex;} + } + ret= write(job->data_to_fd, data, data_count); + if(ret == -1) + goto failed_to_write; + } + } } if(quality != prev_quality) { if(prev_quality >= 0) { @@ -6669,10 +6764,17 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, struct CheckmediajoB *job, int flag) { int media_blocks= 0, read_chunk= 16, ret, mode, min_block_size, start_lba= 0; - int blocks; + int blocks, os_errno, i, j, last_track_end= -1, track_blocks, track_lba; + int num_sessions, num_tracks, declare_untested= 0, sector_size, count; + int lba, quality; + char sfe[5*SfileadrL]; struct burn_drive *drive; struct burn_drive_info *dinfo; struct isoburn_toc_disc *isoburn_disc= NULL; + struct isoburn_toc_session **isoburn_sessions; + struct isoburn_toc_track **iso_burn_tracks; + struct burn_toc_entry isoburn_entry; + struct stat stbuf; *spotlist= NULL; @@ -6692,6 +6794,30 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, if(ret <= 0) {ret= -1; goto ex;} + if(job->sector_map_path[0]) { + Sectorbitmap_destroy(&(job->sector_map), 0); + if(stat(job->sector_map_path, &stbuf) != -1) { + ret= Sectorbitmap_from_file(&(job->sector_map), job->sector_map_path, + xorriso->info_text, &os_errno, 0); + if(ret <= 0) { + if(xorriso->info_text[0]) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno, + "FAILURE", 0); + goto ex; + } + } + } + + if(job->data_to_path[0]) { + job->data_to_fd= open(job->data_to_path, O_WRONLY | O_CREAT, + S_IRUSR | S_IWUSR); + if(job->data_to_fd == -1) { + sprintf(xorriso->info_text, "Cannot open path %s", + Text_shellsafe(job->data_to_path, sfe, 0)); + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0); + {ret= 0; goto ex;} + } + } Xorriso_pacifier_reset(xorriso, 0); job->start_time= time(NULL); mode= job->mode; @@ -6705,11 +6831,55 @@ int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist, if(ret <= 0) goto ex; - } else if(mode == 0) { + } else if(mode == 0) { /* track by track */ + isoburn_disc= isoburn_toc_drive_get_disc(drive); + if(isoburn_disc == NULL) + goto no_content_visible; + isoburn_sessions= + isoburn_toc_disc_get_sessions(isoburn_disc, &num_sessions); + for(i= 0; i < num_sessions; i++) { + iso_burn_tracks= isoburn_toc_session_get_tracks(isoburn_sessions[i], + &num_tracks); + for(j= 0; j < num_tracks; j++) { + isoburn_toc_track_get_entry(iso_burn_tracks[j], &isoburn_entry); + if(!(isoburn_entry.extensions_valid & 1)) /* should not happen */ + continue; + track_lba= isoburn_entry.start_lba; + track_blocks= isoburn_entry.track_blocks; + if(last_track_end >= 0 && last_track_end < track_lba && + last_track_end >= start_lba) { + ret= Spotlist_add_item(*spotlist, last_track_end, + track_lba - last_track_end, + Xorriso_read_quality_off_tracK, 0); + if(ret <= 0) + goto ex; + } + last_track_end= track_lba + track_blocks; - /* >>> track by track */; + if(track_lba < start_lba) { + track_blocks-= start_lba - track_lba; + track_lba= start_lba; + } + if(track_blocks <= 0) + continue; + if(declare_untested) { + ret= Spotlist_add_item(*spotlist, track_lba, track_blocks, + Xorriso_read_quality_untesteD, 0); + if(ret <= 0) + goto ex; + } else { + ret= Xorriso_check_interval(xorriso, *spotlist, job, + track_lba, track_blocks, + read_chunk, min_block_size, 0); + if(ret <= 0) + goto ex; + if(ret == 2) + declare_untested= 1; + } + } + } - } else if(mode == 1) { + } else if(mode == 1) { /* isoburn disc capacity */ isoburn_disc= isoburn_toc_drive_get_disc(drive); if(isoburn_disc == NULL) { no_content_visible:; @@ -6738,6 +6908,32 @@ no_content_visible:; xorriso->pacifier_count, xorriso->pacifier_total, "", 1); ret= 1; ex:; + if(job->data_to_fd != -1) + close(job->data_to_fd); + if(ret > 0 && job->sector_map_path[0]) { + sector_size= read_chunk * 2048; + count= Spotlist_count(*spotlist, 0); + for(i= 0; i < count; i++) { + ret= Spotlist_get_item(*spotlist, i, &lba, &blocks, &quality, 0); + if(ret <= 0) + continue; + if(lba % read_chunk) { + sector_size= 2048; + break; + } + } + ret= Xorriso_spotlist_to_sectormap(xorriso, *spotlist, sector_size, + &(job->sector_map), 0); + if(ret > 0) { + ret= Sectorbitmap_to_file(job->sector_map, job->sector_map_path, + xorriso->info_text, &os_errno, 0); + if(ret <= 0) { + if(xorriso->info_text[0]) + Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, os_errno, + "FAILURE", 0); + } + } + } if(ret < 0) Spotlist_destroy(spotlist, 0); return(ret); diff --git a/xorriso/xorrisoburn.h b/xorriso/xorrisoburn.h index 3a12171a..bdfe1b90 100644 --- a/xorriso/xorrisoburn.h +++ b/xorriso/xorrisoburn.h @@ -14,9 +14,6 @@ #ifndef Xorrisoburn_includeD #define Xorrisoburn_includeD yes -struct XorrisO; -struct FindjoB; -struct SpotlisT; /* The minimum version of libisoburn to be used with this version of xorriso */ @@ -297,6 +294,16 @@ struct CheckmediajoB { int item_limit; /* Maximum number of media check list items as result */ + char data_to_path[SfileadrL]; + int data_to_fd; + + char sector_map_path[SfileadrL]; + struct SectorbitmaP *sector_map; + + int retry; /* -1= only try full read_chunk, 1=retry with 2k blocks + 0= retry with CD, full chunk else + */ + }; int Xorriso_check_media(struct XorrisO *xorriso, struct SpotlisT **spotlist,