"Fossies" - the Fresh Open Source Software Archive

Member "dvdisaster-0.79.5/rs02-recognize.c" (25 Oct 2015, 8743 Bytes) of package /linux/misc/dvdisaster-0.79.5.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 "rs02-recognize.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.79.3_vs_0.79.5.

    1 /*  dvdisaster: Additional error correction for optical media.
    2  *  Copyright (C) 2004-2015 Carsten Gnoerlich.
    3  *
    4  *  Email: carsten@dvdisaster.org  -or-  cgnoerlich@fsfe.org
    5  *  Project homepage: http://www.dvdisaster.org
    6  *
    7  *  This file is part of dvdisaster.
    8  *
    9  *  dvdisaster is free software: you can redistribute it and/or modify
   10  *  it under the terms of the GNU General Public License as published by
   11  *  the Free Software Foundation, either version 3 of the License, or
   12  *  (at your option) any later version.
   13  *
   14  *  dvdisaster is distributed in the hope that it will be useful,
   15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17  *  GNU General Public License for more details.
   18  *
   19  *  You should have received a copy of the GNU General Public License
   20  *  along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
   21  */
   22 
   23 #include "dvdisaster.h"
   24 
   25 #include "rs02-includes.h"
   26 #include "udf.h"
   27 
   28 /***
   29  *** Recognize RS02 error correction data in the image
   30  ***/
   31 
   32 /*
   33  * Dialog components for disabling RS02 search
   34  */
   35 
   36 static void no_rs02_cb(GtkWidget *widget, gpointer data)
   37 {  int state  = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
   38   
   39    Closure->examineRS02 = !state;
   40 
   41    UpdatePrefsExhaustiveSearch();
   42 }
   43 
   44 static void insert_buttons(GtkDialog *dialog)
   45 {  GtkWidget *check,*align;
   46 
   47    gtk_dialog_add_buttons(dialog, 
   48               _utf("Skip RS02 test"), 1,
   49               _utf("Continue searching"), 0, NULL);
   50 
   51    align = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
   52    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), align, FALSE, FALSE, 0);
   53 
   54    check = gtk_check_button_new_with_label(_utf("Disable RS02 initialization in the preferences"));
   55    gtk_container_add(GTK_CONTAINER(align), check);
   56    gtk_container_set_border_width(GTK_CONTAINER(align), 10);
   57    g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(no_rs02_cb), NULL);
   58 
   59    gtk_widget_show(align);
   60    gtk_widget_show(check);
   61 } 
   62 
   63 /*
   64  * See whether a given header is valid for RS02
   65  */
   66 
   67 enum { HEADER_FOUND, TRY_NEXT_HEADER, TRY_NEXT_MODULO};
   68 
   69 static int try_sector(Image *image, gint64 pos, EccHeader **ehptr, unsigned char *secbuf)
   70 {  EccHeader *eh;
   71    unsigned char fingerprint[16];
   72    guint32 recorded_crc;
   73    guint32 real_crc;
   74    int fp_read = 0;
   75 
   76    /* Try reading the sector */
   77 
   78    Verbose("try_sector: trying sector %lld\n", pos);
   79 
   80    if(ImageReadSectors(image, secbuf, pos, 2) != 2)
   81    {  Verbose("try_sector: read error, trying next header\n");
   82       return TRY_NEXT_HEADER;
   83    }
   84 
   85    eh = (EccHeader*)secbuf;
   86 
   87    /* See if the magic cookie is there. If not, searching within
   88       this modulo makes no sense for write-once media.
   89       However if the medium is rewriteable, there might be trash
   90       data behind the image. So finding an invalid sector
   91       does not imply there is not RS02 data present.
   92       Workaround for mistakenly recognizing RS03 headers added. */
   93 
   94    if(strncmp((char*)eh->cookie, "*dvdisaster*RS02", 16))
   95    {  if(image->type == IMAGE_MEDIUM && image->dh->rewriteable)
   96       {   Verbose("try_sector: no cookie but rewriteable medium: skipping header\n");
   97       return TRY_NEXT_HEADER;
   98       }
   99       else
  100       {   Verbose("try_sector: no cookie, skipping current modulo\n");
  101       return TRY_NEXT_MODULO;
  102       }
  103    }
  104    else Verbose("try_sector: header at %lld: magic cookie found\n", (long long int)pos);
  105 
  106    /* Calculate CRC */
  107 
  108    recorded_crc = eh->selfCRC;
  109 
  110 #ifdef HAVE_BIG_ENDIAN
  111    eh->selfCRC = 0x47504c00;
  112 #else
  113    eh->selfCRC = 0x4c5047;
  114 #endif
  115    real_crc = Crc32((unsigned char*)eh, sizeof(EccHeader));
  116 
  117    if(real_crc != recorded_crc)
  118    {  Verbose("try_sector: CRC failed, skipping header\n");
  119       return TRY_NEXT_HEADER;
  120    }
  121 
  122    eh = g_malloc(sizeof(EccHeader));
  123    memcpy(eh, secbuf, sizeof(EccHeader));
  124 #ifdef HAVE_BIG_ENDIAN
  125    SwapEccHeaderBytes(eh);
  126 #endif
  127    eh->selfCRC = recorded_crc;
  128 
  129    Verbose("try_sector: CRC okay\n");
  130 
  131    /* Compare medium fingerprint with that recorded in Ecc header.
  132       Note that GetImageFingerprint provides internal caching;
  133       the sector is not read repeatedly */
  134 
  135    fp_read = GetImageFingerprint(image, fingerprint, eh->fpSector);
  136           
  137    if(!fp_read)  /* be optimistic if fingerprint sector is unreadable */
  138    {  *ehptr = eh;
  139       Verbose("try_sector: read error in fingerprint sector\n");
  140       return HEADER_FOUND;
  141    }
  142 
  143    if(!memcmp(fingerprint, eh->mediumFP, 16))  /* good fingerprint */
  144    {  *ehptr = eh;
  145       Verbose("try_sector: fingerprint okay, header good\n");
  146       return HEADER_FOUND;
  147    }
  148 
  149    /* This might be a header from a larger previous session.
  150       Discard it and continue */
  151 
  152    Verbose("try_sector: fingerprint mismatch, skipping sector\n");
  153    g_free(eh);
  154    
  155    return TRY_NEXT_HEADER;
  156 }
  157 
  158 /*
  159  * RS02 header search
  160  */
  161 
  162 int RS02Recognize(Image *image)
  163 {  AlignedBuffer *ab = CreateAlignedBuffer(4096);
  164    Bitmap *try_next_header, *try_next_modulo;
  165    gint64 pos;
  166    gint64 header_modulo;
  167    int read_count = 0;
  168    int answered_continue = FALSE;
  169    gint64 max_sectors = 0;
  170 
  171    switch(image->type)
  172    { case IMAGE_FILE:
  173        Verbose("RS02Recognize: file %s\n", image->file->path);
  174        break;
  175 
  176      case IMAGE_MEDIUM:
  177        Verbose("RS02Recognize: medium %s\n", image->dh->device);
  178        break;
  179 
  180      default:
  181        Verbose("RS02Recognize: unknown type %d\n", image->type);
  182        break;
  183    }
  184 
  185    /*** Quick search at fixed offsets relative to ISO filesystem */
  186 
  187    if(image->isoInfo)
  188    {  gint64 iso_size = image->isoInfo->volumeSize; 
  189 
  190       /* Iso size is correct; look for root sector at +2 */
  191 
  192       if(try_sector(image, iso_size, &image->eccHeader, ab->buf) == HEADER_FOUND)
  193       {  Verbose("Root sector search at +0 successful\n");
  194      FreeAlignedBuffer(ab);
  195      return TRUE;
  196       }
  197 
  198       /* Strange stuff. Sometimes the iso size is increased by 150
  199      sectors by the burning software. */
  200 
  201       if(try_sector(image, iso_size-150, &image->eccHeader, ab->buf) == HEADER_FOUND)
  202       {  Verbose("Root sector search at -150 successful\n");
  203      FreeAlignedBuffer(ab);
  204      return TRUE;
  205       }
  206    }
  207 
  208    /*** No exhaustive search on optical media unless explicitly requested. */
  209 
  210    if(!Closure->examineRS02 && image->type == IMAGE_MEDIUM)
  211    {  Verbose("RS02Recognize: skipping exhaustive RS02 search\n");
  212       FreeAlignedBuffer(ab);
  213       return FALSE;
  214    }
  215 
  216    /*** Normal exhaustive search */
  217 
  218    header_modulo = (gint64)1<<62;
  219 
  220    switch(image->type)
  221    {  case IMAGE_FILE:
  222      max_sectors = image->file->size/2048;
  223      break;
  224       case IMAGE_MEDIUM:
  225      max_sectors = MAX(image->dh->readCapacity, image->dh->userAreaSize);
  226      break;
  227    }
  228    if(max_sectors == 0)
  229       Stop("max_sectors uninitialized");
  230 
  231    try_next_header = CreateBitmap0(max_sectors);
  232    try_next_modulo = CreateBitmap0(max_sectors);
  233 
  234    if(image->type == IMAGE_MEDIUM)
  235       Verbose("Medium rewriteable: %s\n", image->dh->rewriteable ? "TRUE" : "FALSE");
  236 
  237    /*** Search for the headers */
  238 
  239    if(image->type == IMAGE_FILE)  /* Seeking on hard disc is cheap */
  240       answered_continue = TRUE;
  241 
  242    while(header_modulo >= 32)
  243    {  pos = max_sectors & ~(header_modulo - 1);
  244 
  245       Verbose("FindHeaderInMedium: Trying modulo %lld\n", header_modulo);
  246 
  247       while(pos > 0)
  248       {  int result;
  249     
  250      if(Closure->stopActions)
  251        goto bail_out;
  252 
  253      if(GetBit(try_next_header, pos))
  254      {  Verbose("Sector %lld cached; skipping\n", pos);
  255         goto check_next_header;
  256      }
  257 
  258      if(GetBit(try_next_modulo, pos))
  259      {  Verbose("Sector %lld cached; skipping modulo\n", pos);
  260          goto check_next_modulo;
  261      }
  262 
  263      result = try_sector(image, pos, &image->eccHeader, ab->buf);
  264 
  265      switch(result)
  266      {  case TRY_NEXT_HEADER:
  267            SetBit(try_next_header, pos);
  268            read_count++;
  269            if(!answered_continue && read_count > 5)
  270            {  if(Closure->guiMode)
  271               {  int answer = ModalDialog(GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, insert_buttons,
  272                           _("Faster medium initialization\n\n"
  273                         "Searching this medium for error correction data may take a long time.\n"
  274                         "Press \"Skip RS02 test\" if you are certain that this medium was\n"
  275                         "not augmented with RS02 error correction data."));
  276          
  277             if(answer) goto bail_out;
  278             answered_continue = TRUE;
  279           }
  280            }
  281            goto check_next_header;
  282         case TRY_NEXT_MODULO:
  283            SetBit(try_next_modulo, pos);
  284            goto check_next_modulo;
  285         case HEADER_FOUND:
  286            FreeBitmap(try_next_header);
  287            FreeBitmap(try_next_modulo);
  288            FreeAlignedBuffer(ab);
  289            return TRUE;
  290      }
  291 
  292       check_next_header:
  293     pos -= header_modulo;
  294       }
  295 
  296    check_next_modulo:
  297       header_modulo >>= 1;
  298    }
  299 
  300 bail_out:
  301    FreeBitmap(try_next_header);
  302    FreeBitmap(try_next_modulo);
  303    FreeAlignedBuffer(ab);
  304    return FALSE;
  305 }
  306