libisoburn  1.5.4
About: libisoburn is a frontend for the libraries libburn and libisofs which enables creation and expansion of ISO-9660 filesystems on all media and file types supported by libburn. It implements the API and command interpreter of program xorriso, and installs this program as small dynamically linked binary. xorriso is suitable for incremental data backup and for production of bootable ISO 9660 images. A statically linked version is available as GNU xorriso.
  Fossies Dox: libisoburn-1.5.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

check_media.c
Go to the documentation of this file.
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 {
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",
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 {
213  (quality == Xorriso_read_quality_md5_mismatcH && quality > bad_limit) ||
215  strcpy(name, "0 ");
216  else if(quality <= bad_limit)
217  strcpy(name, "- ");
218  else
219  strcpy(name, "+ ");
221  strcat(name, "good");
223  strcat(name, "md5_match");
225  strcat(name, "slow");
227  strcat(name, "partial");
229  strcat(name, "valid");
231  strcat(name, "untested");
233  strcat(name, "md5_mismatch");
235  strcat(name, "invalid");
237  strcat(name, "tao_end");
239  strcat(name, "off_track");
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;
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 */
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 
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 
499  int *sectors, int *sector_size, int flag)
500 {
501  *sectors= o->sectors;
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);
642  return(1);
643 }
644 
645 
646 /* -------------------------- End CheckmediajoB --------------------------- */
647 
648 
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)
674  else if(strcmp(argv[i] + 10, "md5_match") == 0)
676  else if(strcmp(argv[i] + 10, "slow") == 0)
678  else if(strcmp(argv[i] + 10, "partial") == 0)
680  else if(strcmp(argv[i] + 10, "valid") == 0)
682  else if(strcmp(argv[i] + 10, "untested") == 0)
684  else if(strcmp(argv[i] + 10, "md5_mismatch") == 0)
686  else if(strcmp(argv[i] + 10, "invalid") == 0)
688  else if(strcmp(argv[i] + 10, "tao_end") == 0)
690  else if(strcmp(argv[i] + 10, "off_track") == 0)
692  else if(strcmp(argv[i] + 10, "unreadable") == 0)
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);
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 */
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);
914  sprintf(report + strlen(report), " bad_limit=%s",
915  Spotlist__quality_name(xorriso->check_media_bad_limit, quality_name,
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 
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;}
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 :
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,
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 :
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 */
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) {
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 
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 
int Xorriso_spotlist_to_sectormap(struct XorrisO *xorriso, struct SpotlisT *spotlist, int read_chunk, struct SectorbitmaP **map, int flag)
Definition: check_media.c:1006
int Spotlist_get_item(struct SpotlisT *o, int idx, int *start_lba, int *blocks, int *quality, int flag)
Definition: check_media.c:182
int Sectorbitmap_from_file(struct SectorbitmaP **o, char *path, char *msg, int *os_errno, int flag)
Definition: check_media.c:288
int Sectorbitmap_copy(struct SectorbitmaP *from, struct SectorbitmaP *to, int flag)
Definition: check_media.c:507
int Xorriso_check_media_list_job(struct XorrisO *xorriso, struct CheckmediajoB *job, char *report, int flag)
Definition: check_media.c:841
int Spotlistitem_destroy(struct SpotlistiteM **o, int flag)
Definition: check_media.c:66
int Xorriso_update_in_sector_map(struct XorrisO *xorriso, struct SpotlisT *spotlist, int read_chunk, struct CheckmediajoB *job, int flag)
Definition: check_media.c:1104
int Checkmediajob_destroy(struct CheckmediajoB **o, int flag)
Definition: check_media.c:604
#define O_BINARY
Definition: check_media.c:30
int Sectorbitmap_set(struct SectorbitmaP *o, int sector, int flag)
Definition: check_media.c:438
int Xorriso_check_media_setup_job(struct XorrisO *xorriso, struct CheckmediajoB *job, char **argv, int old_idx, int end_idx, int flag)
Definition: check_media.c:649
int Xorriso_open_job_data_to(struct XorrisO *xorriso, struct CheckmediajoB *job, int flag)
Definition: check_media.c:1082
int Sectorbitmap_new(struct SectorbitmaP **o, int sectors, int sector_size, int flag)
Definition: check_media.c:252
int Sectorbitmap_to_file(struct SectorbitmaP *o, char *path, char *info, char *msg, int *os_errno, int flag)
Definition: check_media.c:375
int Sectorbitmap_is_set(struct SectorbitmaP *o, int sector, int flag)
Definition: check_media.c:477
char * Spotlist__quality_name(int quality, char name[80], int bad_limit, int flag)
Definition: check_media.c:208
int Sectorbitmap_get_layout(struct SectorbitmaP *o, int *sectors, int *sector_size, int flag)
Definition: check_media.c:498
int Sectorbitmap_clone(struct SectorbitmaP *from, struct SectorbitmaP **clone, int flag)
Definition: check_media.c:549
int Spotlist_add_item(struct SpotlisT *o, int start_lba, int blocks, int quality, int flag)
Definition: check_media.c:120
int Spotlist_destroy(struct SpotlisT **o, int flag)
Definition: check_media.c:102
int Checkmediajob_copy(struct CheckmediajoB *from, struct CheckmediajoB *to, int flag)
Definition: check_media.c:617
int Spotlist_count(struct SpotlisT *o, int flag)
Definition: check_media.c:147
int Spotlist_sector_size(struct SpotlisT *o, int read_chunk, int flag)
Definition: check_media.c:166
int Spotlist_block_count(struct SpotlisT *o, int flag)
Definition: check_media.c:153
int Checkmediajob_new(struct CheckmediajoB **o, int flag)
Definition: check_media.c:568
int Sectorbitmap_bytes_are_set(struct SectorbitmaP *o, off_t start_byte, off_t end_byte, int flag)
Definition: check_media.c:485
int Spotlist_new(struct SpotlisT **o, int flag)
Definition: check_media.c:85
int Spotlistitem_new(struct SpotlistiteM **o, int start_lba, int blocks, int quality, int flag)
Definition: check_media.c:49
int Sectorbitmap_destroy(struct SectorbitmaP **o, int flag)
Definition: check_media.c:276
int Xorriso_sectormap_to_spotlist(struct XorrisO *xorriso, struct CheckmediajoB *job, struct SpotlisT **spotlist, int flag)
Definition: check_media.c:939
int Sectorbitmap_set_range(struct SectorbitmaP *o, int start_sector, int sectors, int flag)
Definition: check_media.c:452
#define Xorriso_read_quality_partiaL
Definition: check_media.h:85
#define Xorriso_read_quality_sloW
Definition: check_media.h:84
#define Xorriso_read_quality_off_tracK
Definition: check_media.h:91
#define Xorriso_read_quality_md5_matcH
Definition: check_media.h:83
#define Xorriso_read_quality_tao_enD
Definition: check_media.h:90
#define Xorriso_read_quality_gooD
Definition: check_media.h:82
#define Xorriso_read_quality_md5_mismatcH
Definition: check_media.h:88
#define Xorriso_read_quality_invaliD
Definition: check_media.h:89
#define Xorriso_read_quality_valiD
Definition: check_media.h:86
#define Xorriso_read_quality_unreadablE
Definition: check_media.h:92
#define Xorriso_read_quality_untesteD
Definition: check_media.h:87
#define SfileadrL
int Xorriso__text_to_sev(char *severity_name, int *severity_number, int flag)
Definition: lib_mgt.c:387
double Scanf_io_size(char *text, int flag)
Convert a text into a number of type double and multiply it by unit code [kmgtpe] (2^10 to 2^60) or [...
Definition: misc_funct.c:182
char * Text_shellsafe(char *in_text, char *out_text, int flag)
Definition: misc_funct.c:1044
int Sfile_str(char target[4096], char *source, int flag)
Definition: sfile.c:836
#define TSOB_FELD(typ, count)
Definition: sfile.h:15
#define Xorriso_free_meM(pt)
Definition: sfile.h:27
#define Xorriso_alloc_meM(pt, typ, count)
Definition: sfile.h:19
off_t data_to_offset
Definition: check_media.h:119
struct SectorbitmaP * sector_map
Definition: check_media.h:126
char data_to_path[SfileadrL]
Definition: check_media.h:117
char event_severity[20]
Definition: check_media.h:139
char abort_file_path[SfileadrL]
Definition: check_media.h:115
double slow_threshold_seq
Definition: check_media.h:144
off_t data_to_limit
Definition: check_media.h:120
char sector_map_path[SfileadrL]
Definition: check_media.h:125
time_t start_time
Definition: check_media.h:110
unsigned char * map
Definition: check_media.h:58
int current_idx
Definition: check_media.c:81
struct SpotlistiteM * current_item
Definition: check_media.c:80
int list_count
Definition: check_media.c:79
struct SpotlistiteM * list_end
Definition: check_media.c:78
struct SpotlistiteM * list_start
Definition: check_media.c:77
struct SpotlistiteM * next
Definition: check_media.c:45
char list_delimiter[81]
struct SectorbitmaP * in_sector_map
char info_text[10 *4096]
int check_media_bad_limit
struct CheckmediajoB * check_media_default
int Xorriso_msgs_submit(struct XorrisO *xorriso, int error_code, char msg_text[], int os_errno, char severity[], int flag)
Submit a problem message to the xorriso problem reporting and handling system.
Definition: text_io.c:2504