1
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3
4 Copyright 2007-2015 Thomas Schmitt, <scdbackup@gmx.net>
5
6 Provided under GPL version 2 or later.
7
8 This file contains the implementation of classes SpotlistiteM, SectorbitmaP,
9 CheckmediajoB which perform verifying runs on media resp. images.
10 */
11
12 #ifdef HAVE_CONFIG_H
13 #include "../config.h"
14 #endif
15
16 #include <ctype.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <time.h>
25 #include <fcntl.h>
26 #include <errno.h>
27
28 /* O_BINARY is needed for Cygwin but undefined elsewhere */
29 #ifndef O_BINARY
30 #define O_BINARY 0
31 #endif
32
33 #include "xorriso.h"
34 #include "xorriso_private.h"
35 #include "xorrisoburn.h"
36
37
38 /* ------------------------------ SpotlisT -------------------------------- */
39
40
41 struct SpotlistiteM {
42 int start_lba;
43 int blocks;
44 int quality;
45 struct SpotlistiteM *next;
46 };
47
48
Spotlistitem_new(struct SpotlistiteM ** o,int start_lba,int blocks,int quality,int flag)49 int Spotlistitem_new(struct SpotlistiteM **o, int start_lba, int blocks,
50 int quality, int flag)
51 {
52 struct SpotlistiteM *m;
53
54 m= TSOB_FELD(struct SpotlistiteM,1);
55 if(m==NULL)
56 return(-1);
57 *o= m;
58 m->start_lba= start_lba;
59 m->blocks= blocks;
60 m->quality= quality;
61 m->next= NULL;
62 return(1);
63 }
64
65
Spotlistitem_destroy(struct SpotlistiteM ** o,int flag)66 int Spotlistitem_destroy(struct SpotlistiteM **o, int flag)
67 {
68 if((*o) == NULL)
69 return(0);
70 free((char *) *o);
71 *o= NULL;
72 return(1);
73 }
74
75
76 struct SpotlisT {
77 struct SpotlistiteM *list_start;
78 struct SpotlistiteM *list_end;
79 int list_count;
80 struct SpotlistiteM *current_item;
81 int current_idx;
82 };
83
84
Spotlist_new(struct SpotlisT ** o,int flag)85 int Spotlist_new(struct SpotlisT **o, int flag)
86 {
87 struct SpotlisT *m;
88
89 m= TSOB_FELD(struct SpotlisT,1);
90 if(m==NULL)
91 return(-1);
92 *o= m;
93 m->list_start= NULL;
94 m->list_end= NULL;
95 m->list_count= 0;
96 m->current_item= NULL;
97 m->current_idx= -1;
98 return(1);
99 }
100
101
Spotlist_destroy(struct SpotlisT ** o,int flag)102 int Spotlist_destroy(struct SpotlisT **o, int flag)
103 {
104 struct SpotlisT *m;
105 struct SpotlistiteM *li, *next_li;
106
107 if((*o) == NULL)
108 return(0);
109 m= *o;
110 for(li= m->list_start; li != NULL; li= next_li) {
111 next_li= li->next;
112 Spotlistitem_destroy(&li, 0);
113 }
114 free((char *) *o);
115 *o= NULL;
116 return(1);
117 }
118
119
Spotlist_add_item(struct SpotlisT * o,int start_lba,int blocks,int quality,int flag)120 int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks,
121 int quality, int flag)
122 {
123 int ret;
124 struct SpotlistiteM *li;
125 static int debug_verbous= 0;
126
127 ret= Spotlistitem_new(&li, start_lba, blocks, quality, 0);
128 if(ret <= 0)
129 return(ret);
130 if(o->list_end != NULL)
131 o->list_end->next= li;
132 o->list_end= li;
133 if(o->list_start == NULL)
134 o->list_start= li;
135 (o->list_count)++;
136
137 if(debug_verbous) {char quality_name[80];
138 fprintf(stderr, "debug: lba %10d , size %10d , quality '%s'\n",
139 start_lba, blocks, Spotlist__quality_name(quality, quality_name,
140 Xorriso_read_quality_invaliD, 0) + 2);
141 }
142
143 return(1);
144 }
145
146
Spotlist_count(struct SpotlisT * o,int flag)147 int Spotlist_count(struct SpotlisT *o, int flag)
148 {
149 return o->list_count;
150 }
151
152
Spotlist_block_count(struct SpotlisT * o,int flag)153 int Spotlist_block_count(struct SpotlisT *o, int flag)
154 {
155 int list_blocks= 0;
156 struct SpotlistiteM *li;
157
158 for(li= o->list_start; li != NULL; li= li->next) {
159 if(li->start_lba + li->blocks > list_blocks)
160 list_blocks= li->start_lba + li->blocks;
161 }
162 return(list_blocks);
163 }
164
165
Spotlist_sector_size(struct SpotlisT * o,int read_chunk,int flag)166 int Spotlist_sector_size(struct SpotlisT *o, int read_chunk, int flag)
167 {
168 int sector_size;
169 struct SpotlistiteM *li;
170
171 sector_size= read_chunk * 2048;
172 for(li= o->list_start; li != NULL; li= li->next) {
173 if((li->start_lba % read_chunk) || (li->blocks % read_chunk)) {
174 sector_size= 2048;
175 break;
176 }
177 }
178 return(sector_size);
179 }
180
181
Spotlist_get_item(struct SpotlisT * o,int idx,int * start_lba,int * blocks,int * quality,int flag)182 int Spotlist_get_item(struct SpotlisT *o, int idx,
183 int *start_lba, int *blocks, int *quality, int flag)
184 {
185 int i;
186 struct SpotlistiteM *li;
187
188 if(idx < 0 || idx > o->list_count)
189 return(0);
190 if(idx == o->current_idx && o->current_item != NULL)
191 li= o->current_item;
192 else if(idx == o->current_idx + 1 && o->current_item != NULL) {
193 li= o->current_item->next;
194 } else {
195 li= o->list_start;
196 for(i= 0; i < idx; i++)
197 li= li->next;
198 }
199 o->current_item= li;
200 o->current_idx= idx;
201 *start_lba= li->start_lba;
202 *blocks= li->blocks;
203 *quality= li->quality;
204 return(1);
205 }
206
207
Spotlist__quality_name(int quality,char name[80],int bad_limit,int flag)208 char *Spotlist__quality_name(int quality, char name[80], int bad_limit,
209 int flag)
210 {
211 if(quality == Xorriso_read_quality_untesteD ||
212 quality == Xorriso_read_quality_tao_enD ||
213 quality == Xorriso_read_quality_off_tracK)
214 strcpy(name, "0 ");
215 else if(quality <= bad_limit)
216 strcpy(name, "- ");
217 else
218 strcpy(name, "+ ");
219 if(quality == Xorriso_read_quality_gooD)
220 strcat(name, "good");
221 else if(quality == Xorriso_read_quality_md5_matcH)
222 strcat(name, "md5_match");
223 else if(quality == Xorriso_read_quality_sloW)
224 strcat(name, "slow");
225 else if(quality == Xorriso_read_quality_partiaL)
226 strcat(name, "partial");
227 else if(quality == Xorriso_read_quality_valiD)
228 strcat(name, "valid");
229 else if(quality == Xorriso_read_quality_untesteD)
230 strcat(name, "untested");
231 else if(quality == Xorriso_read_quality_md5_mismatcH)
232 strcat(name, "md5_mismatch");
233 else if(quality == Xorriso_read_quality_invaliD)
234 strcat(name, "invalid");
235 else if(quality == Xorriso_read_quality_tao_enD)
236 strcat(name, "tao_end");
237 else if(quality == Xorriso_read_quality_off_tracK)
238 strcat(name, "off_track");
239 else if(quality == Xorriso_read_quality_unreadablE)
240 strcat(name, "unreadable");
241 else
242 sprintf(name, "0 0x%8.8X", (unsigned int) quality);
243 return(name);
244 }
245
246
247 /* ---------------------------- End SpotlisT ------------------------------ */
248
249 /* ---------------------------- SectorbitmaP ------------------------------ */
250
Sectorbitmap_new(struct SectorbitmaP ** o,int sectors,int sector_size,int flag)251 int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size,
252 int flag)
253 {
254 struct SectorbitmaP *m;
255
256 m= TSOB_FELD(struct SectorbitmaP,1);
257 if(m==NULL)
258 return(-1);
259 *o= m;
260 m->sectors= sectors;
261 m->sector_size= sector_size;
262 m->map= NULL;
263 m->map_size= sectors / 8 + 1;
264
265 m->map= calloc(m->map_size, 1);
266 if(m->map == NULL)
267 goto failure;
268 return(1);
269 failure:;
270 Sectorbitmap_destroy(o, 0);
271 return(-1);
272 }
273
274
Sectorbitmap_destroy(struct SectorbitmaP ** o,int flag)275 int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag)
276 {
277 if((*o) == NULL)
278 return(0);
279 if((*o)->map != NULL)
280 free((char *) (*o)->map);
281 free((char *) *o);
282 *o= NULL;
283 return(1);
284 }
285
286
Sectorbitmap_from_file(struct SectorbitmaP ** o,char * path,char * msg,int * os_errno,int flag)287 int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg,
288 int *os_errno, int flag)
289 {
290 int ret, fd= -1, sectors, sector_size, i, todo, map_size, skip, bufsize= 1024;
291 unsigned char *map;
292 unsigned char *buf;
293
294 buf= TSOB_FELD(unsigned char, bufsize);
295 if(buf == NULL)
296 return(-1);
297
298 *os_errno= 0;
299 if(msg != NULL)
300 msg[0]= 0;
301 fd= open(path, O_RDONLY | O_BINARY);
302 if(fd == -1) {
303 *os_errno= errno;
304 if(msg != NULL) {
305 strcpy(msg, "Cannot open path ");
306 Text_shellsafe(path, msg+strlen(msg), 0);
307 }
308 {ret= 0; goto ex;}
309 }
310 ret= read(fd, buf, 32);
311 if(ret < 32) {
312 wrong_filetype:;
313 if(ret == -1)
314 *os_errno= errno;
315 if(msg != NULL) {
316 strcpy(msg, "Not a sector bitmap file: ");
317 Text_shellsafe(path, msg+strlen(msg), 0);
318 }
319 ret= 0; goto ex;
320 }
321 if(strncmp((char *) buf, "xorriso sector bitmap v1 ", 32) == 0)
322 /* ok */;
323 else if(strncmp((char *) buf, "xorriso sector bitmap v2 ", 25) == 0) {
324 skip= -1;
325 sscanf(((char *) buf) + 25, "%d", &skip);
326 if(skip < 0)
327 {ret= 0; goto wrong_filetype;}
328 for(i= 0; i < skip; i+= bufsize) {
329 todo= bufsize;
330 if(i + todo > skip)
331 todo= skip - i;
332 ret= read(fd, buf, todo);
333 if(ret < todo)
334 goto wrong_filetype;
335 }
336 } else
337 {ret= 0; goto wrong_filetype;}
338 ret= read(fd, buf, 8);
339 if(ret < 4)
340 goto wrong_filetype;
341 sectors= (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
342 sector_size= (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
343 if(sectors <= 0 || sector_size <= 0)
344 goto wrong_filetype;
345 ret= Sectorbitmap_new(o, sectors, sector_size, 0);
346 if(ret <= 0) {
347 if(msg != NULL)
348 sprintf(msg, "Cannot allocate bitmap memory for %d sectors", sectors);
349 ret= -1; goto ex;
350 }
351 map= (*o)->map;
352 map_size= (*o)->map_size;
353 for(i= 0; i < map_size; i+= bufsize) {
354 todo= bufsize;
355 if(i + todo > map_size)
356 todo= map_size - i;
357 ret= read(fd, buf, todo);
358 if(ret != todo)
359 goto wrong_filetype;
360 memcpy(map + i, buf, todo);
361 }
362 ret= 1;
363 ex:;
364 if(fd != -1)
365 close(fd);
366 if(buf != NULL)
367 free(buf);
368 if(ret <= 0)
369 Sectorbitmap_destroy(o, 0);
370 return(ret);
371 }
372
373
Sectorbitmap_to_file(struct SectorbitmaP * o,char * path,char * info,char * msg,int * os_errno,int flag)374 int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info,
375 char *msg, int *os_errno, int flag)
376 {
377 int ret, fd= -1, j, l;
378 unsigned char buf[40];
379
380 *os_errno= 0;
381 fd= open(path, O_WRONLY | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR);
382 if(fd == -1) {
383 *os_errno= errno;
384 if(msg != NULL) {
385 strcpy(msg, "Cannot open path ");
386 Text_shellsafe(path, msg+strlen(msg), 0);
387 }
388 ret= 0; goto ex;
389 }
390
391 l= 0;
392 if(info != NULL)
393 l= strlen(info);
394 if(l > 999999) {
395 strcpy(msg, "Info string is longer than 999999 bytes");
396 ret= 0; goto ex;
397 }
398 sprintf((char *) buf, "xorriso sector bitmap v2 %-6d\n", l);
399
400 ret= write(fd, buf, 32);
401 if(ret != 32) {
402 cannot_write:;
403 *os_errno= errno;
404 if(msg != NULL) {
405 strcpy(msg, "Cannot write to ");
406 Text_shellsafe(path, msg+strlen(msg), 0);
407 }
408 ret= 0; goto ex;
409 }
410 if(l > 0) {
411 ret= write(fd, info, l);
412 if(ret != l)
413 goto cannot_write;
414 }
415
416 for(j= 0; j < 4; j++) {
417 buf[j]= o->sectors >> (24 - j * 8);
418 buf[j+4]= o->sector_size >> (24 - j * 8);
419 }
420 ret= write(fd, buf, 8);
421 if(ret != 8)
422 goto cannot_write;
423 ret= write(fd, o->map, o->map_size);
424 if(ret != o->map_size)
425 goto cannot_write;
426
427 ret= 1;
428 ex:;
429 if(fd != -1)
430 close(fd);
431 return(ret);
432 }
433
434
435 /* @param flag bit0= sector bit value
436 */
Sectorbitmap_set(struct SectorbitmaP * o,int sector,int flag)437 int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag)
438 {
439 if(sector < 0 || sector >= o->sectors)
440 return(0);
441 if(flag & 1)
442 o->map[sector / 8]|= 1 << (sector % 8);
443 else
444 o->map[sector / 8]&= ~(1 << (sector % 8));
445 return(1);
446 }
447
448
449 /* @param flag bit0= sector bit value
450 */
Sectorbitmap_set_range(struct SectorbitmaP * o,int start_sector,int sectors,int flag)451 int Sectorbitmap_set_range(struct SectorbitmaP *o,
452 int start_sector, int sectors, int flag)
453 {
454 int start_i, end_i, i;
455 unsigned char value;
456
457 if(start_sector < 0 || start_sector + sectors > o->sectors || sectors < 1)
458 return(0);
459 if(flag & 1)
460 value= ~0;
461 else
462 value= 0;
463 start_i= start_sector / 8;
464 end_i= (start_sector + sectors - 1) / 8;
465 for(i= start_sector; i / 8 == start_i && i < start_sector + sectors; i++)
466 Sectorbitmap_set(o, i, flag & 1);
467 for(i= start_i + 1; i < end_i; i++)
468 o->map[i]= value;
469 if(end_i > start_i)
470 for(i= end_i * 8; i < start_sector + sectors; i++)
471 Sectorbitmap_set(o, i, flag & 1);
472 return(1);
473 }
474
475
Sectorbitmap_is_set(struct SectorbitmaP * o,int sector,int flag)476 int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag)
477 {
478 if(sector < 0 || sector >= o->sectors)
479 return(0);
480 return(!! (o->map[sector / 8] & (1 << (sector % 8))));
481 }
482
483
Sectorbitmap_bytes_are_set(struct SectorbitmaP * o,off_t start_byte,off_t end_byte,int flag)484 int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o,
485 off_t start_byte, off_t end_byte, int flag)
486 {
487 int end_sector, i;
488
489 end_sector= end_byte / o->sector_size;
490 for(i= start_byte / o->sector_size; i <= end_sector; i++)
491 if(!Sectorbitmap_is_set(o, i, 0))
492 return(0);
493 return(1);
494 }
495
496
Sectorbitmap_get_layout(struct SectorbitmaP * o,int * sectors,int * sector_size,int flag)497 int Sectorbitmap_get_layout(struct SectorbitmaP *o,
498 int *sectors, int *sector_size, int flag)
499 {
500 *sectors= o->sectors;
501 *sector_size= o->sector_size;
502 return(1);
503 }
504
505
Sectorbitmap_copy(struct SectorbitmaP * from,struct SectorbitmaP * to,int flag)506 int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to,
507 int flag)
508 {
509 int i, run_start, run_value, start_sec, limit_sec, start_aligned;
510 int end_complete;
511
512 if(((off_t) from->sectors) * ((off_t) from->sector_size) >
513 ((off_t) to->sectors) * ((off_t) to->sector_size))
514 return(-1);
515 if(from->sector_size == to->sector_size) {
516 for(i= 0; i < from->map_size; i++)
517 to->map[i]= from->map[i];
518 return(1);
519 }
520 run_start= 0;
521 run_value= Sectorbitmap_is_set(from, 0, 0);
522 for(i= 1; i <= from->sectors; i++) {
523 if(i < from->sectors)
524 if(Sectorbitmap_is_set(from, i, 0) == run_value)
525 continue;
526 start_sec= run_start * from->sector_size / to->sector_size;
527 start_aligned=
528 (start_sec * to->sector_size == run_start * from->sector_size);
529 limit_sec= i * from->sector_size / to->sector_size;
530 end_complete= (limit_sec * to->sector_size == i * from->sector_size);
531 if(run_value) {
532 if(!start_aligned)
533 start_sec++;
534 } else {
535 if(!end_complete)
536 limit_sec++;
537 }
538 if(start_sec < limit_sec)
539 Sectorbitmap_set_range(to, start_sec, limit_sec - 1 - start_sec,
540 !!run_value);
541 run_value= !run_value;
542 run_start= i;
543 }
544 return(1);
545 }
546
547
Sectorbitmap_clone(struct SectorbitmaP * from,struct SectorbitmaP ** clone,int flag)548 int Sectorbitmap_clone(struct SectorbitmaP *from, struct SectorbitmaP **clone,
549 int flag)
550 {
551 int ret;
552
553 ret= Sectorbitmap_new(clone, from->sectors, from->sector_size, 0);
554 if(ret <= 0)
555 return(ret);
556 ret= Sectorbitmap_copy(from, *clone, 0);
557 if(ret <= 0)
558 Sectorbitmap_destroy(clone, 0);
559 return(ret);
560 }
561
562
563 /* -------------------------- End SectorbitmaP ---------------------------- */
564
565 /* ---------------------------- CheckmediajoB ----------------------------- */
566
Checkmediajob_new(struct CheckmediajoB ** o,int flag)567 int Checkmediajob_new(struct CheckmediajoB **o, int flag)
568 {
569 struct CheckmediajoB *m;
570
571 m= TSOB_FELD(struct CheckmediajoB,1);
572 if(m==NULL)
573 return(-1);
574 *o= m;
575 m->use_dev= 0;
576 m->min_lba= -1;
577 m->max_lba= -1;
578 m->min_block_size= 0;
579 m->async_chunks= 0;
580 m->mode= 0;
581 m->start_time= time(NULL);
582 m->time_limit= 28800;
583 m->item_limit= 100000;
584 strcpy(m->abort_file_path, "/var/opt/xorriso/do_abort_check_media");
585 m->data_to_path[0]= 0;
586 m->data_to_fd= -1;
587 m->data_to_offset= 0;
588 m->data_to_limit= -1;
589 m->patch_lba0= 0;
590 m->patch_lba0_msc1= -1;
591 m->sector_map_path[0]= 0;
592 m->sector_map= NULL;
593 m->map_with_volid= 0;
594 m->retry= 0;
595 m->report_mode= 0;
596 strcpy(m->event_severity, "ALL");
597 m->slow_threshold_seq= 1.0;
598 return(1);
599 }
600
601
Checkmediajob_destroy(struct CheckmediajoB ** o,int flag)602 int Checkmediajob_destroy(struct CheckmediajoB **o, int flag)
603 {
604 if((*o) == NULL)
605 return(0);
606 if((*o)->data_to_fd != -1)
607 close((*o)->data_to_fd);
608 Sectorbitmap_destroy(&((*o)->sector_map), 0);
609 free((char *) *o);
610 *o= NULL;
611 return(1);
612 }
613
614
Checkmediajob_copy(struct CheckmediajoB * from,struct CheckmediajoB * to,int flag)615 int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to,
616 int flag)
617 {
618 to->use_dev= from->use_dev;
619 to->min_lba= from->min_lba;
620 to->max_lba= from->max_lba;
621 to->min_block_size= from->min_block_size;
622 to->mode= from->mode;
623 to->time_limit= from->time_limit;
624 to->item_limit= from->item_limit;
625 strcpy(to->abort_file_path, from->abort_file_path);
626 strcpy(to->data_to_path, from->data_to_path);
627 /* not copied: data_to_fd */
628 to->data_to_offset= from->data_to_offset;
629 to->data_to_limit= from->data_to_limit;
630 to->patch_lba0= from->patch_lba0;
631 to->patch_lba0_msc1= from->patch_lba0_msc1;
632 strcpy(to->sector_map_path, from->sector_map_path);
633 /* not copied: sector_map */
634 to->map_with_volid= from->map_with_volid;
635 to->retry= from->retry;
636 to->report_mode= from->report_mode;
637 strcpy(to->event_severity, from->event_severity);
638 to->slow_threshold_seq= from->slow_threshold_seq;
639 return(1);
640 }
641
642
643 /* -------------------------- End CheckmediajoB --------------------------- */
644
645
Xorriso_check_media_setup_job(struct XorrisO * xorriso,struct CheckmediajoB * job,char ** argv,int old_idx,int end_idx,int flag)646 int Xorriso_check_media_setup_job(struct XorrisO *xorriso,
647 struct CheckmediajoB *job,
648 char **argv, int old_idx, int end_idx, int flag)
649 {
650 int ret, i, sev;
651 double num;
652 struct CheckmediajoB *default_job;
653 char sev_text[20];
654
655 if(xorriso->check_media_default != NULL)
656 Checkmediajob_copy(xorriso->check_media_default, job, 0);
657 for(i= old_idx; i < end_idx; i++) {
658 if(strncmp(argv[i], "abort_file=", 11) == 0) {
659 ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0);
660 if(ret <= 0)
661 goto ex;
662 } else if(strncmp(argv[i], "async_chunks=", 13) == 0) {
663 num= Scanf_io_size(argv[i] + 13, 1);
664 if(num >= 0 && num <= 1024)
665 job->async_chunks= num;
666 else
667 goto bad_value;
668 } else if(strncmp(argv[i], "bad_limit=", 10) == 0) {
669 if(strcmp(argv[i] + 10, "good") == 0)
670 xorriso->check_media_bad_limit= Xorriso_read_quality_gooD;
671 else if(strcmp(argv[i] + 10, "md5_match") == 0)
672 xorriso->check_media_bad_limit= Xorriso_read_quality_md5_matcH;
673 else if(strcmp(argv[i] + 10, "slow") == 0)
674 xorriso->check_media_bad_limit= Xorriso_read_quality_sloW;
675 else if(strcmp(argv[i] + 10, "partial") == 0)
676 xorriso->check_media_bad_limit= Xorriso_read_quality_partiaL;
677 else if(strcmp(argv[i] + 10, "valid") == 0)
678 xorriso->check_media_bad_limit= Xorriso_read_quality_valiD;
679 else if(strcmp(argv[i] + 10, "untested") == 0)
680 xorriso->check_media_bad_limit= Xorriso_read_quality_untesteD;
681 else if(strcmp(argv[i] + 10, "md5_mismatch") == 0)
682 xorriso->check_media_bad_limit= Xorriso_read_quality_md5_mismatcH;
683 else if(strcmp(argv[i] + 10, "invalid") == 0)
684 xorriso->check_media_bad_limit= Xorriso_read_quality_invaliD;
685 else if(strcmp(argv[i] + 10, "tao_end") == 0)
686 xorriso->check_media_bad_limit= Xorriso_read_quality_tao_enD;
687 else if(strcmp(argv[i] + 10, "off_track") == 0)
688 xorriso->check_media_bad_limit= Xorriso_read_quality_off_tracK;
689 else if(strcmp(argv[i] + 10, "unreadable") == 0)
690 xorriso->check_media_bad_limit= Xorriso_read_quality_unreadablE;
691 else
692 goto unknown_value;
693 } else if(strncmp(argv[i], "data_to=", 8) == 0) {
694 ret= Sfile_str(job->data_to_path, argv[i] + 8, 0);
695 if(ret <= 0)
696 goto ex;
697 } else if(strncmp(argv[i], "chunk_size=", 11) == 0) {
698 num= Scanf_io_size(argv[i] + 11, 1);
699 if(num >= 2048 || num == 0)
700 job->min_block_size= num / 2048;
701 else
702 goto bad_value;
703 } else if(strncmp(argv[i], "event=", 6) == 0) {
704 strncpy(sev_text, argv[i] + 6, 19);
705 sev_text[19]= 0;
706 ret= Xorriso__text_to_sev(sev_text, &sev, 0);
707 if(ret <= 0) {
708 strcpy(xorriso->info_text, "-check_media event=");
709 Text_shellsafe(sev_text, xorriso->info_text, 1);
710 strcat(xorriso->info_text, " : Not a known severity name");
711 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
712 goto ex;
713 }
714 strcpy(job->event_severity, sev_text);
715 } else if(strncmp(argv[i], "map_with_volid=", 15) == 0) {
716 if(strcmp(argv[i] + 15, "on") == 0)
717 job->map_with_volid= 1;
718 else if(strcmp(argv[i] + 15, "off") == 0)
719 job->map_with_volid= 0;
720 else
721 goto unknown_value;
722 } else if(strncmp(argv[i], "max_lba=", 8) == 0 ||
723 strncmp(argv[i], "min_lba=", 8) == 0) {
724 num= -1;
725 sscanf(argv[i] + 8, "%lf", &num);
726 if(num > 0x7fffffff || num < 0)
727 num= -1;
728 if(strncmp(argv[i], "max_lba=", 8) == 0)
729 job->max_lba= num;
730 else
731 job->min_lba= num;
732 } else if(strncmp(argv[i], "patch_lba0=", 11) == 0) {
733 job->patch_lba0_msc1= -1;
734 if(strcmp(argv[i] + 11, "on") == 0)
735 job->patch_lba0= 1;
736 else if(strcmp(argv[i] + 11, "off") == 0)
737 job->patch_lba0= 0;
738 else if(strcmp(argv[i] + 11, "force") == 0)
739 job->patch_lba0= 2;
740 else if(argv[i][11] >= '1' && argv[i][11] <= '9') {
741 num= -1;
742 sscanf(argv[i] + 11, "%lf", &num);
743 if(num > 0x7fffffff || num < 0)
744 goto bad_value;
745 job->patch_lba0_msc1= num;
746 job->patch_lba0= (num >= 32) + (strstr(argv[i] + 11, ":force") != NULL);
747 } else
748 goto unknown_value;
749 } else if(strncmp(argv[i], "report=", 7) == 0) {
750 if(strcmp(argv[i] + 7, "blocks") == 0)
751 job->report_mode= 0;
752 else if(strcmp(argv[i] + 7, "files") == 0)
753 job->report_mode= 1;
754 else if(strcmp(argv[i] + 7, "blocks_files") == 0)
755 job->report_mode= 2;
756 else
757 goto unknown_value;
758 } else if(strcmp(argv[i], "reset=now") == 0) {
759 ret= Checkmediajob_new(&default_job, 0);
760 if(ret <= 0) {
761 sprintf(xorriso->info_text,
762 "-check_media: Cannot reset options due to lack of resources");
763 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
764 ret= -1; goto ex;
765 }
766 Checkmediajob_copy(default_job, job, 0);
767 Checkmediajob_destroy(&default_job, 0);
768 xorriso->check_media_bad_limit= Xorriso_read_quality_invaliD;
769 } else if(strncmp(argv[i], "retry=", 6) == 0) {
770 if(strcmp(argv[i] + 6, "on") == 0)
771 job->retry= 1;
772 else if(strcmp(argv[i] + 6, "off") == 0)
773 job->retry= -1;
774 else if(strcmp(argv[i] + 6, "default") == 0)
775 job->retry= 0;
776 else
777 goto unknown_value;
778 } else if(strncmp(argv[i], "sector_map=", 11) == 0) {
779 ret= Sfile_str(job->sector_map_path, argv[i] + 11, 0);
780 if(ret <= 0)
781 goto ex;
782 } else if(strncmp(argv[i], "slow_limit=", 11) == 0) {
783 sscanf(argv[i] + 11, "%lf", &(job->slow_threshold_seq));
784 } else if(strncmp(argv[i], "time_limit=", 11) == 0 ||
785 strncmp(argv[i], "item_limit=", 11) == 0 ) {
786 num= -1;
787 sscanf(argv[i] + 11, "%lf", &num);
788 if(num > 0x7fffffff || num < 0)
789 num= -1;
790 if(strncmp(argv[i], "time_limit=", 11) == 0)
791 job->time_limit= num;
792 else
793 job->item_limit= num;
794 } else if(strncmp(argv[i], "use=", 4) == 0) {
795 if(strcmp(argv[i] + 4, "outdev") == 0)
796 job->use_dev= 1;
797 else if(strcmp(argv[i] + 4, "indev") == 0)
798 job->use_dev= 0;
799 else if(strcmp(argv[i] + 4, "sector_map") == 0)
800 job->use_dev= 2;
801 else
802 goto unknown_value;
803 } else if(strncmp(argv[i], "what=", 5) == 0) {
804 if(strcmp(argv[i]+5, "tracks") == 0)
805 job->mode= 0;
806 else if(strcmp(argv[i]+5, "image")== 0)
807 job->mode= 1;
808 else if(strcmp(argv[i]+5, "disc")== 0)
809 job->mode= 2;
810 else {
811 unknown_value:;
812 sprintf(xorriso->info_text,
813 "-check_media: Unknown value with option %s", argv[i]);
814 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
815 ret= 0; goto ex;
816 bad_value:;
817 sprintf(xorriso->info_text,
818 "-check_media: Unsuitable value with option %s", argv[i]);
819 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
820 ret= 0; goto ex;
821 }
822 } else {
823 sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]);
824 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
825 ret= 0; goto ex;
826 }
827 }
828 ret= 1;
829 ex:;
830 return(ret);
831 }
832
833
834 /* @param report Buffer of at least 10*SfileadrL
835 @param flag bit0= only report non-default settings
836 @return <=0 error , 1 ok , 2 with bit0: every option is on default setting
837 */
Xorriso_check_media_list_job(struct XorrisO * xorriso,struct CheckmediajoB * job,char * report,int flag)838 int Xorriso_check_media_list_job(struct XorrisO *xorriso,
839 struct CheckmediajoB *job,
840 char *report, int flag)
841 {
842 int all, ret;
843 char *default_report= NULL, quality_name[80];
844 struct CheckmediajoB *dflt= NULL;
845
846 Xorriso_alloc_meM(default_report, char, 161);
847
848 all= !(flag&1);
849 report[0]= 0;
850 ret= Checkmediajob_new(&dflt, 0);
851 if(ret <= 0)
852 {ret= -1; goto ex;}
853 sprintf(report, "-check_media_defaults");
854 if(!all)
855 strcat(report, " reset=now");
856 if(all || job->use_dev != dflt->use_dev)
857 sprintf(report + strlen(report), " use=%s",
858 job->use_dev == 1 ? "outdev" :
859 job->use_dev == 2 ? "sector_map" : "indev");
860 if(all || job->mode != dflt->mode)
861 sprintf(report + strlen(report), " what=%s",
862 job->mode == 1 ? "disc" : "tracks");
863 if(all || job->min_lba != dflt->min_lba)
864 sprintf(report + strlen(report), " min_lba=%d", job->min_lba);
865 if(all || job->max_lba != dflt->max_lba)
866 sprintf(report + strlen(report), " max_lba=%d", job->max_lba);
867 if(all || job->retry != dflt->retry)
868 sprintf(report + strlen(report), " retry=%s",
869 job->retry == 1 ? "on" : job->retry == -1 ? "off" : "default");
870 if(all || job->time_limit != dflt->time_limit)
871 sprintf(report + strlen(report), " time_limit=%d", job->time_limit);
872 if(all || job->item_limit != dflt->item_limit)
873 sprintf(report + strlen(report), " item_limit=%d", job->item_limit);
874 if(all || strcmp(job->abort_file_path, dflt->abort_file_path)) {
875 strcat(report, " abort_file=");
876 Text_shellsafe(job->abort_file_path, report + strlen(report), 0);
877 }
878 if(strlen(report) > 4 * SfileadrL)
879 {ret= 0; goto ex;}
880 if(all || strcmp(job->data_to_path, dflt->data_to_path)) {
881 strcat(report, " data_to=");
882 Text_shellsafe(job->data_to_path, report + strlen(report), 0);
883 }
884 if(strlen(report) > 4 * SfileadrL)
885 {ret= 0; goto ex;}
886 if(all || strcmp(job->sector_map_path, dflt->sector_map_path)) {
887 strcat(report, " sector_map=");
888 Text_shellsafe(job->sector_map_path, report + strlen(report), 0);
889 }
890 if(all || job->map_with_volid != dflt->map_with_volid)
891 sprintf(report + strlen(report), " map_with_volid=%s",
892 job->map_with_volid == 1 ? "on" : "off");
893 if(all || job->patch_lba0 != dflt->patch_lba0) {
894 sprintf(report + strlen(report), " patch_lba0=");
895 if(job->patch_lba0 == 0)
896 sprintf(report + strlen(report), "off");
897 else if(job->patch_lba0_msc1 >= 0)
898 sprintf(report + strlen(report), "%d%s",
899 job->patch_lba0_msc1, job->patch_lba0 == 2 ? ":force" : "");
900 else
901 sprintf(report + strlen(report), "%s",
902 job->patch_lba0 == 2 ? "force" : "on");
903 }
904 if(all || job->report_mode != dflt->report_mode)
905 sprintf(report + strlen(report), " report=%s",
906 job->report_mode == 0 ? "blocks" :
907 job->report_mode == 1 ? "files" : "blocks_files");
908 if(all || job->slow_threshold_seq != dflt->slow_threshold_seq)
909 sprintf(report + strlen(report), " slow_limit=%f", job->slow_threshold_seq);
910 if(all || xorriso->check_media_bad_limit != Xorriso_read_quality_invaliD)
911 sprintf(report + strlen(report), " bad_limit=%s",
912 Spotlist__quality_name(xorriso->check_media_bad_limit, quality_name,
913 Xorriso_read_quality_invaliD, 0) + 2);
914 if(all || job->min_block_size != dflt->min_block_size)
915 sprintf(report + strlen(report), " chunk_size=%ds", job->min_block_size);
916 if(all || strcmp(job->event_severity, "ALL") != 0)
917 sprintf(report + strlen(report), " event=%s", job->event_severity);
918 if(strlen(report) > 4 * SfileadrL)
919 {ret= 0; goto ex;}
920 ret= 1;
921 ex:;
922 strcat(report, " ");
923 strcat(report, xorriso->list_delimiter);
924 Checkmediajob_destroy(&dflt, 0);
925 if(default_report != NULL) {
926 sprintf(default_report, "-check_media_defaults reset=now %s",
927 xorriso->list_delimiter);
928 if(ret > 0 && strcmp(report, default_report) == 0)
929 ret= 2;
930 }
931 Xorriso_free_meM(default_report);
932 return(ret);
933 }
934
935
Xorriso_sectormap_to_spotlist(struct XorrisO * xorriso,struct CheckmediajoB * job,struct SpotlisT ** spotlist,int flag)936 int Xorriso_sectormap_to_spotlist(struct XorrisO *xorriso,
937 struct CheckmediajoB *job,
938 struct SpotlisT **spotlist,
939 int flag)
940 {
941 struct SectorbitmaP *map;
942 int ret, i, sectors, sector_size, value, old_value= -1, old_start= -1;
943
944 map= job->sector_map;
945 if(map == NULL)
946 return(-1);
947 ret= Spotlist_new(spotlist, 0);
948 if(ret <= 0)
949 {ret= -1; goto ex;}
950 Sectorbitmap_get_layout(map, §ors, §or_size, 0);
951 sector_size/= 2048;
952 if(job->max_lba >= 0)
953 sectors= (job->max_lba + 1) / sector_size;
954 i= 0;
955 if(job->min_lba >= 0)
956 i= job->min_lba / sector_size;
957 for(; i < sectors; i++) {
958 value= Sectorbitmap_is_set(map, i, 0);
959 if(value == old_value)
960 continue;
961 if(old_value >= 0) {
962 ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start,
963 (old_value ? Xorriso_read_quality_valiD :
964 Xorriso_read_quality_invaliD), 0);
965 if(ret <= 0)
966 goto ex;
967 if(job->item_limit > 0 &&
968 Spotlist_count(*spotlist, 0) + 1 >= job->item_limit) {
969 sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d",
970 job->item_limit);
971 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
972 if(sectors - i > 1) {
973 ret= Spotlist_add_item(*spotlist, i * sector_size,
974 (sectors - i - 1) * sector_size,
975 Xorriso_read_quality_untesteD, 0);
976 if(ret <= 0)
977 goto ex;
978 }
979 ret= 2; goto ex;
980 }
981 }
982 old_value= value;
983 old_start= i * sector_size;
984 }
985 if(old_value >= 0) {
986 ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start,
987 (old_value ? Xorriso_read_quality_valiD :
988 Xorriso_read_quality_invaliD), 0);
989 if(ret <= 0)
990 goto ex;
991 }
992 ret= 1;
993 ex:;
994 if(ret <= 0)
995 Spotlist_destroy(spotlist, 0);
996 return(ret);
997 }
998
999
1000 /* @param flag bit0= mark untested areas as valid
1001 bit1= leave untested areas as they are
1002 */
Xorriso_spotlist_to_sectormap(struct XorrisO * xorriso,struct SpotlisT * spotlist,int read_chunk,struct SectorbitmaP ** map,int flag)1003 int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso,
1004 struct SpotlisT *spotlist,
1005 int read_chunk,
1006 struct SectorbitmaP **map,
1007 int flag)
1008 {
1009 struct SectorbitmaP *m;
1010 int map_sectors= -1, map_sector_size= -1, valid;
1011 int list_sectors, list_blocks, sector_size, sector_blocks;
1012 int replace_map= 0, count, i, lba, blocks, quality, ret, pass;
1013
1014 sector_size= Spotlist_sector_size(spotlist, read_chunk, 0);
1015 sector_blocks= sector_size / 2048;
1016 if(*map != NULL)
1017 Sectorbitmap_get_layout(*map, &map_sectors, &map_sector_size, 0);
1018
1019 count= Spotlist_count(spotlist, 0);
1020 list_blocks= Spotlist_block_count(spotlist, 0);
1021
1022 /* >>> ??? insist in list_blocks % sector_blocks == 0 */
1023
1024 list_sectors= list_blocks / sector_blocks;
1025 if(list_sectors * sector_blocks < list_blocks)
1026 list_sectors++;
1027 if(*map != NULL && map_sectors * (map_sector_size / 2048) >= list_blocks &&
1028 map_sector_size == sector_size)
1029 m= *map;
1030 else {
1031 if(*map != NULL) {
1032 if(((off_t) (*map)->sectors) * ((off_t) (*map)->sector_size) >
1033 ((off_t) list_sectors) * ((off_t) sector_size))
1034 list_sectors= (((off_t) (*map)->sectors) *
1035 ((off_t) (*map)->sector_size)) / ((off_t) sector_size)
1036 + 1;
1037 }
1038 ret= Sectorbitmap_new(&m, list_sectors, sector_size, 0);
1039 if(ret <= 0)
1040 return(-1);
1041 replace_map= 1;
1042 if(*map != NULL) {
1043 ret= Sectorbitmap_copy(*map, m, 0);
1044 if(ret <= 0) {
1045 Sectorbitmap_destroy(&m, 0);
1046 return(0);
1047 }
1048 }
1049 }
1050
1051 count= Spotlist_count(spotlist, 0);
1052 /* first set good bits, then eventually override by bad bits */
1053 for(pass= 0; pass < 2; pass++) {
1054 for(i= 0; i < count; i++) {
1055 ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0);
1056 if(ret <= 0)
1057 continue;
1058 valid= quality > xorriso->check_media_bad_limit;
1059 if(quality == Xorriso_read_quality_untesteD && (flag & 1))
1060 valid= 1;
1061 if(quality == Xorriso_read_quality_untesteD && (flag & 2))
1062 continue;
1063 if(pass == 0 && !valid)
1064 continue;
1065 else if(pass == 1 && valid)
1066 continue;
1067 Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks,
1068 valid);
1069 }
1070 }
1071 if(replace_map) {
1072 Sectorbitmap_destroy(map, 0);
1073 *map= m;
1074 }
1075 return(1);
1076 }
1077
1078
Xorriso_open_job_data_to(struct XorrisO * xorriso,struct CheckmediajoB * job,int flag)1079 int Xorriso_open_job_data_to(struct XorrisO *xorriso,
1080 struct CheckmediajoB *job, int flag)
1081 {
1082 if(job->data_to_path[0] == 0)
1083 return(2);
1084 job->data_to_fd= open(job->data_to_path, O_RDWR | O_CREAT | O_BINARY,
1085 S_IRUSR | S_IWUSR);
1086 if(job->data_to_fd == -1) {
1087 sprintf(xorriso->info_text, "Cannot open path ");
1088 Text_shellsafe(job->data_to_path, xorriso->info_text, 1);
1089 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1090 return(0);
1091 }
1092 return(1);
1093 }
1094
1095
Xorriso_update_in_sector_map(struct XorrisO * xorriso,struct SpotlisT * spotlist,int read_chunk,struct CheckmediajoB * job,int flag)1096 int Xorriso_update_in_sector_map(struct XorrisO *xorriso,
1097 struct SpotlisT *spotlist, int read_chunk,
1098 struct CheckmediajoB *job, int flag)
1099 {
1100 int sectors, sector_size, sector_blocks, ret;
1101 struct SectorbitmaP *map;
1102
1103 Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
1104 if(job->use_dev == 1)
1105 return(1);
1106 map= job->sector_map;
1107 sectors= Spotlist_block_count(spotlist, 0);
1108 if(sectors <= 0)
1109 return(0);
1110 sector_size= Spotlist_sector_size(spotlist, read_chunk, 0);
1111 sector_blocks= sector_size / 2048;
1112 if(sector_blocks > 1)
1113 sectors= sectors / sector_blocks + !!(sectors % sector_blocks);
1114 ret= Sectorbitmap_new(&(xorriso->in_sector_map), sectors, sector_size, 0);
1115 if(ret <= 0)
1116 return(ret);
1117 if(map != NULL)
1118 Sectorbitmap_copy(map, xorriso->in_sector_map, 0);
1119 ret= Xorriso_spotlist_to_sectormap(xorriso, spotlist, read_chunk,
1120 &(xorriso->in_sector_map), 1);
1121 return(ret);
1122 }
1123
1124