"Fossies" - the Fresh Open Source Software Archive 
Member "libisoburn-1.5.4/xorriso/check_media.c" (5 Dec 2020, 32965 Bytes) of package /linux/misc/libisoburn-1.5.4.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "check_media.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
1.4.8_vs_1.5.0.
1
2 /* xorriso - creates, loads, manipulates and burns ISO 9660 filesystem images.
3
4 Copyright 2007-2020 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
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
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
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
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
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
147 int Spotlist_count(struct SpotlisT *o, int flag)
148 {
149 return o->list_count;
150 }
151
152
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
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
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
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_md5_mismatcH && quality > bad_limit) ||
214 quality == Xorriso_read_quality_off_tracK)
215 strcpy(name, "0 ");
216 else if(quality <= bad_limit)
217 strcpy(name, "- ");
218 else
219 strcpy(name, "+ ");
220 if(quality == Xorriso_read_quality_gooD)
221 strcat(name, "good");
222 else if(quality == Xorriso_read_quality_md5_matcH)
223 strcat(name, "md5_match");
224 else if(quality == Xorriso_read_quality_sloW)
225 strcat(name, "slow");
226 else if(quality == Xorriso_read_quality_partiaL)
227 strcat(name, "partial");
228 else if(quality == Xorriso_read_quality_valiD)
229 strcat(name, "valid");
230 else if(quality == Xorriso_read_quality_untesteD)
231 strcat(name, "untested");
232 else if(quality == Xorriso_read_quality_md5_mismatcH)
233 strcat(name, "md5_mismatch");
234 else if(quality == Xorriso_read_quality_invaliD)
235 strcat(name, "invalid");
236 else if(quality == Xorriso_read_quality_tao_enD)
237 strcat(name, "tao_end");
238 else if(quality == Xorriso_read_quality_off_tracK)
239 strcat(name, "off_track");
240 else if(quality == Xorriso_read_quality_unreadablE)
241 strcat(name, "unreadable");
242 else
243 sprintf(name, "0 0x%8.8X", (unsigned int) quality);
244 return(name);
245 }
246
247
248 /* ---------------------------- End SpotlisT ------------------------------ */
249
250 /* ---------------------------- SectorbitmaP ------------------------------ */
251
252 int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size,
253 int flag)
254 {
255 struct SectorbitmaP *m;
256
257 m= TSOB_FELD(struct SectorbitmaP,1);
258 if(m==NULL)
259 return(-1);
260 *o= m;
261 m->sectors= sectors;
262 m->sector_size= sector_size;
263 m->map= NULL;
264 m->map_size= sectors / 8 + 1;
265
266 m->map= calloc(m->map_size, 1);
267 if(m->map == NULL)
268 goto failure;
269 return(1);
270 failure:;
271 Sectorbitmap_destroy(o, 0);
272 return(-1);
273 }
274
275
276 int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag)
277 {
278 if((*o) == NULL)
279 return(0);
280 if((*o)->map != NULL)
281 free((char *) (*o)->map);
282 free((char *) *o);
283 *o= NULL;
284 return(1);
285 }
286
287
288 int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg,
289 int *os_errno, int flag)
290 {
291 int ret, fd= -1, sectors, sector_size, i, todo, map_size, skip, bufsize= 1024;
292 unsigned char *map;
293 unsigned char *buf;
294
295 buf= TSOB_FELD(unsigned char, bufsize);
296 if(buf == NULL)
297 return(-1);
298
299 *os_errno= 0;
300 if(msg != NULL)
301 msg[0]= 0;
302 fd= open(path, O_RDONLY | O_BINARY);
303 if(fd == -1) {
304 *os_errno= errno;
305 if(msg != NULL) {
306 strcpy(msg, "Cannot open path ");
307 Text_shellsafe(path, msg+strlen(msg), 0);
308 }
309 {ret= 0; goto ex;}
310 }
311 ret= read(fd, buf, 32);
312 if(ret < 32) {
313 wrong_filetype:;
314 if(ret == -1)
315 *os_errno= errno;
316 if(msg != NULL) {
317 strcpy(msg, "Not a sector bitmap file: ");
318 Text_shellsafe(path, msg+strlen(msg), 0);
319 }
320 ret= 0; goto ex;
321 }
322 if(strncmp((char *) buf, "xorriso sector bitmap v1 ", 32) == 0)
323 /* ok */;
324 else if(strncmp((char *) buf, "xorriso sector bitmap v2 ", 25) == 0) {
325 skip= -1;
326 sscanf(((char *) buf) + 25, "%d", &skip);
327 if(skip < 0)
328 {ret= 0; goto wrong_filetype;}
329 for(i= 0; i < skip; i+= bufsize) {
330 todo= bufsize;
331 if(i + todo > skip)
332 todo= skip - i;
333 ret= read(fd, buf, todo);
334 if(ret < todo)
335 goto wrong_filetype;
336 }
337 } else
338 {ret= 0; goto wrong_filetype;}
339 ret= read(fd, buf, 8);
340 if(ret < 4)
341 goto wrong_filetype;
342 sectors= (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
343 sector_size= (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
344 if(sectors <= 0 || sector_size <= 0)
345 goto wrong_filetype;
346 ret= Sectorbitmap_new(o, sectors, sector_size, 0);
347 if(ret <= 0) {
348 if(msg != NULL)
349 sprintf(msg, "Cannot allocate bitmap memory for %d sectors", sectors);
350 ret= -1; goto ex;
351 }
352 map= (*o)->map;
353 map_size= (*o)->map_size;
354 for(i= 0; i < map_size; i+= bufsize) {
355 todo= bufsize;
356 if(i + todo > map_size)
357 todo= map_size - i;
358 ret= read(fd, buf, todo);
359 if(ret != todo)
360 goto wrong_filetype;
361 memcpy(map + i, buf, todo);
362 }
363 ret= 1;
364 ex:;
365 if(fd != -1)
366 close(fd);
367 if(buf != NULL)
368 free(buf);
369 if(ret <= 0)
370 Sectorbitmap_destroy(o, 0);
371 return(ret);
372 }
373
374
375 int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info,
376 char *msg, int *os_errno, int flag)
377 {
378 int ret, fd= -1, j, l;
379 unsigned char buf[40];
380
381 *os_errno= 0;
382 fd= open(path, O_WRONLY | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR);
383 if(fd == -1) {
384 *os_errno= errno;
385 if(msg != NULL) {
386 strcpy(msg, "Cannot open path ");
387 Text_shellsafe(path, msg+strlen(msg), 0);
388 }
389 ret= 0; goto ex;
390 }
391
392 l= 0;
393 if(info != NULL)
394 l= strlen(info);
395 if(l > 999999) {
396 strcpy(msg, "Info string is longer than 999999 bytes");
397 ret= 0; goto ex;
398 }
399 sprintf((char *) buf, "xorriso sector bitmap v2 %-6d\n", l);
400
401 ret= write(fd, buf, 32);
402 if(ret != 32) {
403 cannot_write:;
404 *os_errno= errno;
405 if(msg != NULL) {
406 strcpy(msg, "Cannot write to ");
407 Text_shellsafe(path, msg+strlen(msg), 0);
408 }
409 ret= 0; goto ex;
410 }
411 if(l > 0) {
412 ret= write(fd, info, l);
413 if(ret != l)
414 goto cannot_write;
415 }
416
417 for(j= 0; j < 4; j++) {
418 buf[j]= o->sectors >> (24 - j * 8);
419 buf[j+4]= o->sector_size >> (24 - j * 8);
420 }
421 ret= write(fd, buf, 8);
422 if(ret != 8)
423 goto cannot_write;
424 ret= write(fd, o->map, o->map_size);
425 if(ret != o->map_size)
426 goto cannot_write;
427
428 ret= 1;
429 ex:;
430 if(fd != -1)
431 close(fd);
432 return(ret);
433 }
434
435
436 /* @param flag bit0= sector bit value
437 */
438 int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag)
439 {
440 if(sector < 0 || sector >= o->sectors)
441 return(0);
442 if(flag & 1)
443 o->map[sector / 8]|= 1 << (sector % 8);
444 else
445 o->map[sector / 8]&= ~(1 << (sector % 8));
446 return(1);
447 }
448
449
450 /* @param flag bit0= sector bit value
451 */
452 int Sectorbitmap_set_range(struct SectorbitmaP *o,
453 int start_sector, int sectors, int flag)
454 {
455 int start_i, end_i, i;
456 unsigned char value;
457
458 if(start_sector < 0 || start_sector + sectors > o->sectors || sectors < 1)
459 return(0);
460 if(flag & 1)
461 value= ~0;
462 else
463 value= 0;
464 start_i= start_sector / 8;
465 end_i= (start_sector + sectors - 1) / 8;
466 for(i= start_sector; i / 8 == start_i && i < start_sector + sectors; i++)
467 Sectorbitmap_set(o, i, flag & 1);
468 for(i= start_i + 1; i < end_i; i++)
469 o->map[i]= value;
470 if(end_i > start_i)
471 for(i= end_i * 8; i < start_sector + sectors; i++)
472 Sectorbitmap_set(o, i, flag & 1);
473 return(1);
474 }
475
476
477 int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag)
478 {
479 if(sector < 0 || sector >= o->sectors)
480 return(0);
481 return(!! (o->map[sector / 8] & (1 << (sector % 8))));
482 }
483
484
485 int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o,
486 off_t start_byte, off_t end_byte, int flag)
487 {
488 int end_sector, i;
489
490 end_sector= end_byte / o->sector_size;
491 for(i= start_byte / o->sector_size; i <= end_sector; i++)
492 if(!Sectorbitmap_is_set(o, i, 0))
493 return(0);
494 return(1);
495 }
496
497
498 int Sectorbitmap_get_layout(struct SectorbitmaP *o,
499 int *sectors, int *sector_size, int flag)
500 {
501 *sectors= o->sectors;
502 *sector_size= o->sector_size;
503 return(1);
504 }
505
506
507 int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to,
508 int flag)
509 {
510 int i, run_start, run_value, start_sec, limit_sec, start_aligned;
511 int end_complete;
512
513 if(((off_t) from->sectors) * ((off_t) from->sector_size) >
514 ((off_t) to->sectors) * ((off_t) to->sector_size))
515 return(-1);
516 if(from->sector_size == to->sector_size) {
517 for(i= 0; i < from->map_size; i++)
518 to->map[i]= from->map[i];
519 return(1);
520 }
521 run_start= 0;
522 run_value= Sectorbitmap_is_set(from, 0, 0);
523 for(i= 1; i <= from->sectors; i++) {
524 if(i < from->sectors)
525 if(Sectorbitmap_is_set(from, i, 0) == run_value)
526 continue;
527 start_sec= run_start * from->sector_size / to->sector_size;
528 start_aligned=
529 (start_sec * to->sector_size == run_start * from->sector_size);
530 limit_sec= i * from->sector_size / to->sector_size;
531 end_complete= (limit_sec * to->sector_size == i * from->sector_size);
532 if(run_value) {
533 if(!start_aligned)
534 start_sec++;
535 } else {
536 if(!end_complete)
537 limit_sec++;
538 }
539 if(start_sec < limit_sec)
540 Sectorbitmap_set_range(to, start_sec, limit_sec - 1 - start_sec,
541 !!run_value);
542 run_value= !run_value;
543 run_start= i;
544 }
545 return(1);
546 }
547
548
549 int Sectorbitmap_clone(struct SectorbitmaP *from, struct SectorbitmaP **clone,
550 int flag)
551 {
552 int ret;
553
554 ret= Sectorbitmap_new(clone, from->sectors, from->sector_size, 0);
555 if(ret <= 0)
556 return(ret);
557 ret= Sectorbitmap_copy(from, *clone, 0);
558 if(ret <= 0)
559 Sectorbitmap_destroy(clone, 0);
560 return(ret);
561 }
562
563
564 /* -------------------------- End SectorbitmaP ---------------------------- */
565
566 /* ---------------------------- CheckmediajoB ----------------------------- */
567
568 int Checkmediajob_new(struct CheckmediajoB **o, int flag)
569 {
570 struct CheckmediajoB *m;
571
572 m= TSOB_FELD(struct CheckmediajoB,1);
573 if(m==NULL)
574 return(-1);
575 *o= m;
576 m->use_dev= 0;
577 m->min_lba= -1;
578 m->max_lba= -1;
579 m->min_block_size= 0;
580 m->async_chunks= 0;
581 m->mode= 0;
582 m->start_time= time(NULL);
583 m->time_limit= 28800;
584 m->item_limit= 100000;
585 strcpy(m->abort_file_path, "/var/opt/xorriso/do_abort_check_media");
586 m->data_to_path[0]= 0;
587 m->data_to_fd= -1;
588 m->data_to_offset= 0;
589 m->data_to_limit= -1;
590 m->data_to_skip= 0;
591 m->patch_lba0= 0;
592 m->patch_lba0_msc1= -1;
593 m->sector_map_path[0]= 0;
594 m->sector_map= NULL;
595 m->map_with_volid= 0;
596 m->retry= 0;
597 m->report_mode= 0;
598 strcpy(m->event_severity, "ALL");
599 m->slow_threshold_seq= 1.0;
600 return(1);
601 }
602
603
604 int Checkmediajob_destroy(struct CheckmediajoB **o, int flag)
605 {
606 if((*o) == NULL)
607 return(0);
608 if((*o)->data_to_fd != -1 && strcmp((*o)->data_to_path, "-") != 0)
609 close((*o)->data_to_fd);
610 Sectorbitmap_destroy(&((*o)->sector_map), 0);
611 free((char *) *o);
612 *o= NULL;
613 return(1);
614 }
615
616
617 int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to,
618 int flag)
619 {
620 to->use_dev= from->use_dev;
621 to->min_lba= from->min_lba;
622 to->max_lba= from->max_lba;
623 to->min_block_size= from->min_block_size;
624 to->mode= from->mode;
625 to->time_limit= from->time_limit;
626 to->item_limit= from->item_limit;
627 strcpy(to->abort_file_path, from->abort_file_path);
628 strcpy(to->data_to_path, from->data_to_path);
629 /* not copied: data_to_fd */
630 to->data_to_offset= from->data_to_offset;
631 to->data_to_limit= from->data_to_limit;
632 to->data_to_skip= from->data_to_skip;
633 to->patch_lba0= from->patch_lba0;
634 to->patch_lba0_msc1= from->patch_lba0_msc1;
635 strcpy(to->sector_map_path, from->sector_map_path);
636 /* not copied: sector_map */
637 to->map_with_volid= from->map_with_volid;
638 to->retry= from->retry;
639 to->report_mode= from->report_mode;
640 strcpy(to->event_severity, from->event_severity);
641 to->slow_threshold_seq= from->slow_threshold_seq;
642 return(1);
643 }
644
645
646 /* -------------------------- End CheckmediajoB --------------------------- */
647
648
649 int Xorriso_check_media_setup_job(struct XorrisO *xorriso,
650 struct CheckmediajoB *job,
651 char **argv, int old_idx, int end_idx, int flag)
652 {
653 int ret, i, sev;
654 double num;
655 struct CheckmediajoB *default_job;
656 char sev_text[20];
657
658 if(xorriso->check_media_default != NULL)
659 Checkmediajob_copy(xorriso->check_media_default, job, 0);
660 for(i= old_idx; i < end_idx; i++) {
661 if(strncmp(argv[i], "abort_file=", 11) == 0) {
662 ret= Sfile_str(job->abort_file_path, argv[i] + 11, 0);
663 if(ret <= 0)
664 goto ex;
665 } else if(strncmp(argv[i], "async_chunks=", 13) == 0) {
666 num= Scanf_io_size(argv[i] + 13, 1);
667 if(num >= 0 && num <= 1024)
668 job->async_chunks= num;
669 else
670 goto bad_value;
671 } else if(strncmp(argv[i], "bad_limit=", 10) == 0) {
672 if(strcmp(argv[i] + 10, "good") == 0)
673 xorriso->check_media_bad_limit= Xorriso_read_quality_gooD;
674 else if(strcmp(argv[i] + 10, "md5_match") == 0)
675 xorriso->check_media_bad_limit= Xorriso_read_quality_md5_matcH;
676 else if(strcmp(argv[i] + 10, "slow") == 0)
677 xorriso->check_media_bad_limit= Xorriso_read_quality_sloW;
678 else if(strcmp(argv[i] + 10, "partial") == 0)
679 xorriso->check_media_bad_limit= Xorriso_read_quality_partiaL;
680 else if(strcmp(argv[i] + 10, "valid") == 0)
681 xorriso->check_media_bad_limit= Xorriso_read_quality_valiD;
682 else if(strcmp(argv[i] + 10, "untested") == 0)
683 xorriso->check_media_bad_limit= Xorriso_read_quality_untesteD;
684 else if(strcmp(argv[i] + 10, "md5_mismatch") == 0)
685 xorriso->check_media_bad_limit= Xorriso_read_quality_md5_mismatcH;
686 else if(strcmp(argv[i] + 10, "invalid") == 0)
687 xorriso->check_media_bad_limit= Xorriso_read_quality_invaliD;
688 else if(strcmp(argv[i] + 10, "tao_end") == 0)
689 xorriso->check_media_bad_limit= Xorriso_read_quality_tao_enD;
690 else if(strcmp(argv[i] + 10, "off_track") == 0)
691 xorriso->check_media_bad_limit= Xorriso_read_quality_off_tracK;
692 else if(strcmp(argv[i] + 10, "unreadable") == 0)
693 xorriso->check_media_bad_limit= Xorriso_read_quality_unreadablE;
694 else
695 goto unknown_value;
696 } else if(strncmp(argv[i], "data_to=", 8) == 0) {
697 ret= Sfile_str(job->data_to_path, argv[i] + 8, 0);
698 if(ret <= 0)
699 goto ex;
700 } else if(strncmp(argv[i], "chunk_size=", 11) == 0) {
701 num= Scanf_io_size(argv[i] + 11, 1);
702 if(num >= 2048 || num == 0)
703 job->min_block_size= num / 2048;
704 else
705 goto bad_value;
706 } else if(strncmp(argv[i], "event=", 6) == 0) {
707 strncpy(sev_text, argv[i] + 6, 19);
708 sev_text[19]= 0;
709 ret= Xorriso__text_to_sev(sev_text, &sev, 0);
710 if(ret <= 0) {
711 strcpy(xorriso->info_text, "-check_media event=");
712 Text_shellsafe(sev_text, xorriso->info_text, 1);
713 strcat(xorriso->info_text, " : Not a known severity name");
714 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
715 goto ex;
716 }
717 strcpy(job->event_severity, sev_text);
718 } else if(strncmp(argv[i], "map_with_volid=", 15) == 0) {
719 if(strcmp(argv[i] + 15, "on") == 0)
720 job->map_with_volid= 1;
721 else if(strcmp(argv[i] + 15, "off") == 0)
722 job->map_with_volid= 0;
723 else
724 goto unknown_value;
725 } else if(strncmp(argv[i], "max_lba=", 8) == 0 ||
726 strncmp(argv[i], "min_lba=", 8) == 0) {
727 num= -1;
728 sscanf(argv[i] + 8, "%lf", &num);
729 if(num > 0x7fffffff || num < 0)
730 num= -1;
731 if(strncmp(argv[i], "max_lba=", 8) == 0)
732 job->max_lba= num;
733 else
734 job->min_lba= num;
735 } else if(strncmp(argv[i], "patch_lba0=", 11) == 0) {
736 job->patch_lba0_msc1= -1;
737 if(strcmp(argv[i] + 11, "on") == 0)
738 job->patch_lba0= 1;
739 else if(strcmp(argv[i] + 11, "off") == 0)
740 job->patch_lba0= 0;
741 else if(strcmp(argv[i] + 11, "force") == 0)
742 job->patch_lba0= 2;
743 else if(argv[i][11] >= '1' && argv[i][11] <= '9') {
744 num= -1;
745 sscanf(argv[i] + 11, "%lf", &num);
746 if(num > 0x7fffffff || num < 0)
747 goto bad_value;
748 job->patch_lba0_msc1= num;
749 job->patch_lba0= (num >= 32) + (strstr(argv[i] + 11, ":force") != NULL);
750 } else
751 goto unknown_value;
752 } else if(strncmp(argv[i], "report=", 7) == 0) {
753 if(strcmp(argv[i] + 7, "blocks") == 0)
754 job->report_mode= 0;
755 else if(strcmp(argv[i] + 7, "files") == 0)
756 job->report_mode= 1;
757 else if(strcmp(argv[i] + 7, "blocks_files") == 0)
758 job->report_mode= 2;
759 else
760 goto unknown_value;
761 } else if(strcmp(argv[i], "reset=now") == 0) {
762 ret= Checkmediajob_new(&default_job, 0);
763 if(ret <= 0) {
764 sprintf(xorriso->info_text,
765 "-check_media: Cannot reset options due to lack of resources");
766 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FATAL", 0);
767 ret= -1; goto ex;
768 }
769 Checkmediajob_copy(default_job, job, 0);
770 Checkmediajob_destroy(&default_job, 0);
771 xorriso->check_media_bad_limit= Xorriso_read_quality_invaliD;
772 } else if(strncmp(argv[i], "retry=", 6) == 0) {
773 if(strcmp(argv[i] + 6, "on") == 0)
774 job->retry= 1;
775 else if(strcmp(argv[i] + 6, "off") == 0)
776 job->retry= -1;
777 else if(strcmp(argv[i] + 6, "default") == 0)
778 job->retry= 0;
779 else
780 goto unknown_value;
781 } else if(strncmp(argv[i], "sector_map=", 11) == 0) {
782 ret= Sfile_str(job->sector_map_path, argv[i] + 11, 0);
783 if(ret <= 0)
784 goto ex;
785 } else if(strncmp(argv[i], "slow_limit=", 11) == 0) {
786 sscanf(argv[i] + 11, "%lf", &(job->slow_threshold_seq));
787 } else if(strncmp(argv[i], "time_limit=", 11) == 0 ||
788 strncmp(argv[i], "item_limit=", 11) == 0 ) {
789 num= -1;
790 sscanf(argv[i] + 11, "%lf", &num);
791 if(num > 0x7fffffff || num < 0)
792 num= -1;
793 if(strncmp(argv[i], "time_limit=", 11) == 0)
794 job->time_limit= num;
795 else
796 job->item_limit= num;
797 } else if(strncmp(argv[i], "use=", 4) == 0) {
798 if(strcmp(argv[i] + 4, "outdev") == 0)
799 job->use_dev= 1;
800 else if(strcmp(argv[i] + 4, "indev") == 0)
801 job->use_dev= 0;
802 else if(strcmp(argv[i] + 4, "sector_map") == 0)
803 job->use_dev= 2;
804 else
805 goto unknown_value;
806 } else if(strncmp(argv[i], "what=", 5) == 0) {
807 if(strcmp(argv[i]+5, "tracks") == 0)
808 job->mode= 0;
809 else if(strcmp(argv[i]+5, "image")== 0)
810 job->mode= 1;
811 else if(strcmp(argv[i]+5, "disc")== 0)
812 job->mode= 2;
813 else {
814 unknown_value:;
815 sprintf(xorriso->info_text,
816 "-check_media: Unknown value with option %s", argv[i]);
817 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
818 ret= 0; goto ex;
819 bad_value:;
820 sprintf(xorriso->info_text,
821 "-check_media: Unsuitable value with option %s", argv[i]);
822 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
823 ret= 0; goto ex;
824 }
825 } else {
826 sprintf(xorriso->info_text, "-check_media: Unknown option '%s'", argv[i]);
827 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "FAILURE", 0);
828 ret= 0; goto ex;
829 }
830 }
831 ret= 1;
832 ex:;
833 return(ret);
834 }
835
836
837 /* @param report Buffer of at least 10*SfileadrL
838 @param flag bit0= only report non-default settings
839 @return <=0 error , 1 ok , 2 with bit0: every option is on default setting
840 */
841 int Xorriso_check_media_list_job(struct XorrisO *xorriso,
842 struct CheckmediajoB *job,
843 char *report, int flag)
844 {
845 int all, ret;
846 char *default_report= NULL, quality_name[80];
847 struct CheckmediajoB *dflt= NULL;
848
849 Xorriso_alloc_meM(default_report, char, 161);
850
851 all= !(flag&1);
852 report[0]= 0;
853 ret= Checkmediajob_new(&dflt, 0);
854 if(ret <= 0)
855 {ret= -1; goto ex;}
856 sprintf(report, "-check_media_defaults");
857 if(!all)
858 strcat(report, " reset=now");
859 if(all || job->use_dev != dflt->use_dev)
860 sprintf(report + strlen(report), " use=%s",
861 job->use_dev == 1 ? "outdev" :
862 job->use_dev == 2 ? "sector_map" : "indev");
863 if(all || job->mode != dflt->mode)
864 sprintf(report + strlen(report), " what=%s",
865 job->mode == 1 ? "disc" : "tracks");
866 if(all || job->min_lba != dflt->min_lba)
867 sprintf(report + strlen(report), " min_lba=%d", job->min_lba);
868 if(all || job->max_lba != dflt->max_lba)
869 sprintf(report + strlen(report), " max_lba=%d", job->max_lba);
870 if(all || job->retry != dflt->retry)
871 sprintf(report + strlen(report), " retry=%s",
872 job->retry == 1 ? "on" : job->retry == -1 ? "off" : "default");
873 if(all || job->time_limit != dflt->time_limit)
874 sprintf(report + strlen(report), " time_limit=%d", job->time_limit);
875 if(all || job->item_limit != dflt->item_limit)
876 sprintf(report + strlen(report), " item_limit=%d", job->item_limit);
877 if(all || strcmp(job->abort_file_path, dflt->abort_file_path)) {
878 strcat(report, " abort_file=");
879 Text_shellsafe(job->abort_file_path, report + strlen(report), 0);
880 }
881 if(strlen(report) > 4 * SfileadrL)
882 {ret= 0; goto ex;}
883 if(all || strcmp(job->data_to_path, dflt->data_to_path)) {
884 strcat(report, " data_to=");
885 Text_shellsafe(job->data_to_path, report + strlen(report), 0);
886 }
887 if(strlen(report) > 4 * SfileadrL)
888 {ret= 0; goto ex;}
889 if(all || strcmp(job->sector_map_path, dflt->sector_map_path)) {
890 strcat(report, " sector_map=");
891 Text_shellsafe(job->sector_map_path, report + strlen(report), 0);
892 }
893 if(all || job->map_with_volid != dflt->map_with_volid)
894 sprintf(report + strlen(report), " map_with_volid=%s",
895 job->map_with_volid == 1 ? "on" : "off");
896 if(all || job->patch_lba0 != dflt->patch_lba0) {
897 sprintf(report + strlen(report), " patch_lba0=");
898 if(job->patch_lba0 == 0)
899 sprintf(report + strlen(report), "off");
900 else if(job->patch_lba0_msc1 >= 0)
901 sprintf(report + strlen(report), "%d%s",
902 job->patch_lba0_msc1, job->patch_lba0 == 2 ? ":force" : "");
903 else
904 sprintf(report + strlen(report), "%s",
905 job->patch_lba0 == 2 ? "force" : "on");
906 }
907 if(all || job->report_mode != dflt->report_mode)
908 sprintf(report + strlen(report), " report=%s",
909 job->report_mode == 0 ? "blocks" :
910 job->report_mode == 1 ? "files" : "blocks_files");
911 if(all || job->slow_threshold_seq != dflt->slow_threshold_seq)
912 sprintf(report + strlen(report), " slow_limit=%f", job->slow_threshold_seq);
913 if(all || xorriso->check_media_bad_limit != Xorriso_read_quality_invaliD)
914 sprintf(report + strlen(report), " bad_limit=%s",
915 Spotlist__quality_name(xorriso->check_media_bad_limit, quality_name,
916 Xorriso_read_quality_invaliD, 0) + 2);
917 if(all || job->min_block_size != dflt->min_block_size)
918 sprintf(report + strlen(report), " chunk_size=%ds", job->min_block_size);
919 if(all || strcmp(job->event_severity, "ALL") != 0)
920 sprintf(report + strlen(report), " event=%s", job->event_severity);
921 if(strlen(report) > 4 * SfileadrL)
922 {ret= 0; goto ex;}
923 ret= 1;
924 ex:;
925 strcat(report, " ");
926 strcat(report, xorriso->list_delimiter);
927 Checkmediajob_destroy(&dflt, 0);
928 if(default_report != NULL) {
929 sprintf(default_report, "-check_media_defaults reset=now %s",
930 xorriso->list_delimiter);
931 if(ret > 0 && strcmp(report, default_report) == 0)
932 ret= 2;
933 }
934 Xorriso_free_meM(default_report);
935 return(ret);
936 }
937
938
939 int Xorriso_sectormap_to_spotlist(struct XorrisO *xorriso,
940 struct CheckmediajoB *job,
941 struct SpotlisT **spotlist,
942 int flag)
943 {
944 struct SectorbitmaP *map;
945 int ret, i, sectors, sector_size, value, old_value= -1, old_start= -1;
946
947 map= job->sector_map;
948 if(map == NULL)
949 return(-1);
950 ret= Spotlist_new(spotlist, 0);
951 if(ret <= 0)
952 {ret= -1; goto ex;}
953 Sectorbitmap_get_layout(map, §ors, §or_size, 0);
954 sector_size/= 2048;
955 if(job->max_lba >= 0)
956 sectors= (job->max_lba + 1) / sector_size;
957 i= 0;
958 if(job->min_lba >= 0)
959 i= job->min_lba / sector_size;
960 for(; i < sectors; i++) {
961 value= Sectorbitmap_is_set(map, i, 0);
962 if(value == old_value)
963 continue;
964 if(old_value >= 0) {
965 ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start,
966 (old_value ? Xorriso_read_quality_valiD :
967 Xorriso_read_quality_invaliD), 0);
968 if(ret <= 0)
969 goto ex;
970 if(job->item_limit > 0 &&
971 Spotlist_count(*spotlist, 0) + 1 >= job->item_limit) {
972 sprintf(xorriso->info_text, "-check_media: Reached item_limit=%d",
973 job->item_limit);
974 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, 0, "NOTE", 0);
975 if(sectors - i > 1) {
976 ret= Spotlist_add_item(*spotlist, i * sector_size,
977 (sectors - i - 1) * sector_size,
978 Xorriso_read_quality_untesteD, 0);
979 if(ret <= 0)
980 goto ex;
981 }
982 ret= 2; goto ex;
983 }
984 }
985 old_value= value;
986 old_start= i * sector_size;
987 }
988 if(old_value >= 0) {
989 ret= Spotlist_add_item(*spotlist, old_start, i * sector_size - old_start,
990 (old_value ? Xorriso_read_quality_valiD :
991 Xorriso_read_quality_invaliD), 0);
992 if(ret <= 0)
993 goto ex;
994 }
995 ret= 1;
996 ex:;
997 if(ret <= 0)
998 Spotlist_destroy(spotlist, 0);
999 return(ret);
1000 }
1001
1002
1003 /* @param flag bit0= mark untested areas as valid
1004 bit1= leave untested areas as they are
1005 */
1006 int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso,
1007 struct SpotlisT *spotlist,
1008 int read_chunk,
1009 struct SectorbitmaP **map,
1010 int flag)
1011 {
1012 struct SectorbitmaP *m;
1013 int map_sectors= -1, map_sector_size= -1, valid;
1014 int list_sectors, list_blocks, sector_size, sector_blocks;
1015 int replace_map= 0, count, i, lba, blocks, quality, ret, pass;
1016
1017 sector_size= Spotlist_sector_size(spotlist, read_chunk, 0);
1018 sector_blocks= sector_size / 2048;
1019 if(*map != NULL)
1020 Sectorbitmap_get_layout(*map, &map_sectors, &map_sector_size, 0);
1021
1022 count= Spotlist_count(spotlist, 0);
1023 list_blocks= Spotlist_block_count(spotlist, 0);
1024
1025 /* >>> ??? insist in list_blocks % sector_blocks == 0 */
1026
1027 list_sectors= list_blocks / sector_blocks;
1028 if(list_sectors * sector_blocks < list_blocks)
1029 list_sectors++;
1030 if(*map != NULL && map_sectors * (map_sector_size / 2048) >= list_blocks &&
1031 map_sector_size == sector_size)
1032 m= *map;
1033 else {
1034 if(*map != NULL) {
1035 if(((off_t) (*map)->sectors) * ((off_t) (*map)->sector_size) >
1036 ((off_t) list_sectors) * ((off_t) sector_size))
1037 list_sectors= (((off_t) (*map)->sectors) *
1038 ((off_t) (*map)->sector_size)) / ((off_t) sector_size)
1039 + 1;
1040 }
1041 ret= Sectorbitmap_new(&m, list_sectors, sector_size, 0);
1042 if(ret <= 0)
1043 return(-1);
1044 replace_map= 1;
1045 if(*map != NULL) {
1046 ret= Sectorbitmap_copy(*map, m, 0);
1047 if(ret <= 0) {
1048 Sectorbitmap_destroy(&m, 0);
1049 return(0);
1050 }
1051 }
1052 }
1053
1054 count= Spotlist_count(spotlist, 0);
1055 /* first set good bits, then eventually override by bad bits */
1056 for(pass= 0; pass < 2; pass++) {
1057 for(i= 0; i < count; i++) {
1058 ret= Spotlist_get_item(spotlist, i, &lba, &blocks, &quality, 0);
1059 if(ret <= 0)
1060 continue;
1061 valid= quality > xorriso->check_media_bad_limit;
1062 if(quality == Xorriso_read_quality_untesteD && (flag & 1))
1063 valid= 1;
1064 if(quality == Xorriso_read_quality_untesteD && (flag & 2))
1065 continue;
1066 if(pass == 0 && !valid)
1067 continue;
1068 else if(pass == 1 && valid)
1069 continue;
1070 Sectorbitmap_set_range(m, lba / sector_blocks, blocks / sector_blocks,
1071 valid);
1072 }
1073 }
1074 if(replace_map) {
1075 Sectorbitmap_destroy(map, 0);
1076 *map= m;
1077 }
1078 return(1);
1079 }
1080
1081
1082 int Xorriso_open_job_data_to(struct XorrisO *xorriso,
1083 struct CheckmediajoB *job, int flag)
1084 {
1085 if(job->data_to_path[0] == 0)
1086 return(2);
1087 if(strcmp(job->data_to_path, "-") == 0) {
1088 job->data_to_fd= 1;
1089 } else {
1090 job->data_to_fd= open(job->data_to_path, O_RDWR | O_CREAT | O_BINARY,
1091 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
1092 S_IROTH | S_IWOTH);
1093 }
1094 if(job->data_to_fd == -1) {
1095 sprintf(xorriso->info_text, "Cannot open path ");
1096 Text_shellsafe(job->data_to_path, xorriso->info_text, 1);
1097 Xorriso_msgs_submit(xorriso, 0, xorriso->info_text, errno, "FAILURE", 0);
1098 return(0);
1099 }
1100 return(1);
1101 }
1102
1103
1104 int Xorriso_update_in_sector_map(struct XorrisO *xorriso,
1105 struct SpotlisT *spotlist, int read_chunk,
1106 struct CheckmediajoB *job, int flag)
1107 {
1108 int sectors, sector_size, sector_blocks, ret;
1109 struct SectorbitmaP *map;
1110
1111 Sectorbitmap_destroy(&(xorriso->in_sector_map), 0);
1112 if(job->use_dev == 1)
1113 return(1);
1114 map= job->sector_map;
1115 sectors= Spotlist_block_count(spotlist, 0);
1116 if(sectors <= 0)
1117 return(0);
1118 sector_size= Spotlist_sector_size(spotlist, read_chunk, 0);
1119 sector_blocks= sector_size / 2048;
1120 if(sector_blocks > 1)
1121 sectors= sectors / sector_blocks + !!(sectors % sector_blocks);
1122 ret= Sectorbitmap_new(&(xorriso->in_sector_map), sectors, sector_size, 0);
1123 if(ret <= 0)
1124 return(ret);
1125 if(map != NULL)
1126 Sectorbitmap_copy(map, xorriso->in_sector_map, 0);
1127 ret= Xorriso_spotlist_to_sectormap(xorriso, spotlist, read_chunk,
1128 &(xorriso->in_sector_map), 1);
1129 return(ret);
1130 }
1131