"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/xorriso/check_media.c" (30 Jan 2021, 32965 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.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.5.2_vs_1.5.4.

    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, &sectors, &sector_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