"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "read-adaptive.c" between
dvdisaster-0.79.3.tar.gz and dvdisaster-0.79.5.tar.gz

About: dvdisaster provides a margin of safety against data loss on CD, DVD and BD media caused by aging or scratches. Development version.

read-adaptive.c  (dvdisaster-0.79.3):read-adaptive.c  (dvdisaster-0.79.5)
/* dvdisaster: Additional error correction for optical media. /* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2010 Carsten Gnoerlich. * Copyright (C) 2004-2015 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
* *
* This program is free software; you can redistribute it and/or modify * Email: carsten@dvdisaster.org -or- cgnoerlich@fsfe.org
* Project homepage: http://www.dvdisaster.org
*
* This file is part of dvdisaster.
*
* dvdisaster is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * dvdisaster is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
*/ */
#include "dvdisaster.h" #include "dvdisaster.h"
#include "scsi-layer.h" #include "scsi-layer.h"
#include "udf.h" #include "udf.h"
#include "rs02-includes.h" #include "rs02-includes.h"
//#define CHECK_VISITED 1 /* This gives only reasonable output */ //#define CHECK_VISITED 1 /* This gives only reasonable output */
/* when the .ecc file is present while reading! */ /* when the .ecc file is present while reading! */
/*** /***
*** Replace and remove structs and functions in this section!
***/
#define READABLE_IMAGE 0
#define READABLE_ECC 0
#define WRITEABLE_IMAGE (1<<0)
#define WRITEABLE_ECC (1<<1)
#define PRINT_MODE (1<<4)
#define CREATE_CRC ((1<<1) | (1<<5))
typedef struct _EccInfo
{ LargeFile *file; /* file handle for ecc file */
struct _EccHeader *eh; /* the header struct below */
gint64 sectors; /* gint64 version of eh->sectors */
struct MD5Context md5Ctxt; /* md5 context of crc portion of file */
} EccInfo;
static void free_ecc_info(EccInfo *ei)
{
if(ei->file)
if(!LargeClose(ei->file))
Stop(_("Error closing error correction file:\n%s"), strerror(errno));
if(ei->eh) g_free(ei->eh);
g_free(ei);
}
static EccInfo* open_ecc_file(int mode)
{ EccInfo *ei = NULL;
int file_flags;
/*** Sanity check for ecc file reads */
if(!(mode & WRITEABLE_ECC))
{ guint64 ecc_size;
if(!LargeStat(Closure->eccName, &ecc_size))
{ if(!(mode & PRINT_MODE))
Stop(_("Can't open %s:\n%s"),Closure->eccName,strerror(errno));
return NULL;
}
if(ecc_size < 4096)
Stop(_("Invalid or damaged ecc file"));
}
/*** Open the ecc file */
ei = g_malloc0(sizeof(EccInfo));
ei->eh = g_malloc0(sizeof(EccHeader));
file_flags = mode & WRITEABLE_ECC ? O_RDWR | O_CREAT : O_RDONLY;
if(!(ei->file = LargeOpen(Closure->eccName, file_flags, IMG_PERMS)))
{ free_ecc_info(ei);
ei = NULL;
if(!(mode & PRINT_MODE)) /* missing ecc file no problem in print mode */
Stop(_("Can't open %s:\n%s"),Closure->eccName,strerror(errno));
return NULL;
}
if(!(mode & WRITEABLE_ECC))
{ int n = LargeRead(ei->file, ei->eh, sizeof(EccHeader));
if(n != sizeof(EccHeader))
{ free_ecc_info(ei);
Stop(_("Can't read ecc header:\n%s"),strerror(errno));
}
/*** Endian annoyance */
#ifdef HAVE_BIG_ENDIAN
SwapEccHeaderBytes(ei->eh);
#endif
/*** See if we can use the ecc file */
if(strncmp((char*)ei->eh->cookie, "*dvdisaster*", 12))
{ free_ecc_info(ei);
Stop(_("Invalid or damaged ecc file"));
}
if(Closure->version < ei->eh->neededVersion)
PrintCLI(_("* Warning: This ecc file requires dvdisaster-%d.%d!\n"
"* Proceeding could trigger incorrect behaviour.\n"
"* Please read the image without using this ecc file
\n"
"* or visit http://www.dvdisaster.org for an upgrade
.\n\n"),
ei->eh->neededVersion/10000,
(ei->eh->neededVersion%10000)/100);
ei->sectors = uchar_to_gint64(ei->eh->sectors);
LargeSeek(ei->file, 0);
}
return ei;
}
/*
* Load crc buffer from RS01 error correction file
*/
CrcBuf *GetCRCFromRS01_obsolete(EccInfo *ei) /* FIXME: obsolete */
{ CrcBuf *cb = g_malloc(sizeof(CrcBuf));
guint32 *buf;
gint64 crc_sectors,crc_remainder;
gint64 i,j,sec_idx;
cb->crcbuf = g_malloc(ei->sectors * sizeof(guint32));
cb->size = ei->sectors;
cb->valid = CreateBitmap0(ei->sectors);
buf = cb->crcbuf;
/* Seek to beginning of CRC sums */
if(!LargeSeek(ei->file, (gint64)sizeof(EccHeader)))
Stop(_("Failed skipping the ecc header: %s"),strerror(errno));
/* Read crc sums. A sector of 2048 bytes contains 512 CRC sums. */
crc_sectors = ei->sectors / 512;
sec_idx = 0;
for(i=0; i<crc_sectors; i++)
{ if(LargeRead(ei->file, buf, 2048) != 2048)
Stop(_("Error reading CRC information: %s"),strerror(errno));
buf += 512;
for(j=0; j<512; j++, sec_idx++)
SetBit(cb->valid, sec_idx);
}
crc_remainder = sizeof(guint32)*(ei->sectors % 512);
if(crc_remainder)
{ if(LargeRead(ei->file, buf, crc_remainder) != crc_remainder)
Stop(_("Error reading CRC information: %s"),strerror(errno));
for( ; sec_idx<ei->sectors; sec_idx++)
SetBit(cb->valid, sec_idx);
}
return cb;
}
/*
* Load crc buffer from RS02 error correction data
*
* Lots of casts from (void*) since we're transporting
* nonpublic structs.
*/
CrcBuf *GetCRCFromRS02_obsolete(void *layv, void *dhv, LargeFile *image)
{ RS02Layout *lay = (RS02Layout*)layv;
DeviceHandle *dh = (DeviceHandle*)dhv;
AlignedBuffer *ab = CreateAlignedBuffer(2048);
CrcBuf *cb = g_malloc(sizeof(CrcBuf));
gint64 block_idx[256];
gint64 image_sectors,crc_sector;
gint64 s,i;
int crc_idx, crc_valid = FALSE;
image_sectors = lay->eccSectors+lay->dataSectors;
cb->crcbuf = g_malloc(image_sectors * sizeof(guint32));
cb->size = image_sectors;
cb->valid = CreateBitmap0(image_sectors);
/* Initialize ecc block index pointers.
The first CRC set (of lay->ndata checksums) relates to
ecc block lay->firstCrcLayerIndex + 1. */
for(s=0, i=0; i<lay->ndata; s+=lay->sectorsPerLayer, i++)
block_idx[i] = s + lay->firstCrcLayerIndex + 1;
crc_idx = 512; /* force crc buffer reload */
crc_sector = lay->dataSectors+2; /* first crc data sector on medium */
/* Cycle through the ecc blocks and descramble CRC sums in
ascending sector numbers. */
for(s=0; s<lay->sectorsPerLayer; s++)
{ gint64 si = (s + lay->firstCrcLayerIndex + 1) % lay->sectorsPerLayer;
/* Wrap the block_idx[] ptrs at si == 0 */
if(!si)
{ gint64 bs;
for(bs=0, i=0; i<lay->ndata; bs+=lay->sectorsPerLayer, i++)
block_idx[i] = bs;
}
/* Go through all data sectors of current ecc block */
for(i=0; i<lay->ndata; i++)
{ gint64 bidx = block_idx[i];
if(bidx < lay->dataSectors) /* only data sectors have CRCs */
{
/* Refill crc cache if needed */
if(crc_idx >= 512)
{ crc_valid = !ReadSectorsFast(dh, ab->buf, crc_sector++, 1);
crc_idx = 0;
}
/* Sort crc into appropriate place */
if(crc_valid)
{ cb->crcbuf[bidx] = ((guint32*)ab->buf)[crc_idx];
SetBit(cb->valid, bidx);
}
crc_idx++;
block_idx[i]++;
}
}
}
FreeAlignedBuffer(ab);
return cb;
}
/***
*** Local data package used during reading *** Local data package used during reading
***/ ***/
enum { IMAGE_ONLY, ECC_IN_FILE, ECC_IN_IMAGE }; enum { IMAGE_ONLY, ECC_IN_FILE, ECC_IN_IMAGE };
typedef struct typedef struct
{ DeviceHandle *dh; /* device we are reading from */ { Image *medium; /* Medium (disc) we are reading from */
DeviceHandle *dh; /* device we are reading from */
gint64 sectors; /* sectors in medium (maybe cooked value from fi le system) */ gint64 sectors; /* sectors in medium (maybe cooked value from fi le system) */
LargeFile *image; /* image file */ gint64 expectedSectors; /* sectors expected from information in ecc data
*/
LargeFile *image; /* image file for saving the sectors */
int readMode; /* see above enum for choices */ int readMode; /* see above enum for choices */
EccInfo *ei; /* ecc info and header struct */ EccInfo *ei; /* ecc info and header struct */
EccHeader *eh; /* if ecc information is present */ EccHeader *eh; /* if ecc information is present */
int rs01LayerSectors; /* length of each RS01 ecc layer in sectors */ int rs01LayerSectors; /* length of each RS01 ecc layer in sectors */
RS02Layout *lay; /* layout of RS02 type ecc data */ RS02Layout *lay; /* layout of RS02 type ecc data */
AlignedBuffer *ab; /* buffer suitable for reading from the drive */ AlignedBuffer *ab; /* buffer suitable for reading from the drive */
unsigned char *buf; /* buffer component from above */ unsigned char *buf; /* buffer component from above */
Bitmap *map; /* bitmap for keeping track of read sectors */ Bitmap *map; /* bitmap for keeping track of read sectors */
CrcBuf *crcBuf; /* preloaded CRC info from ecc data */ CrcBuf *crcBuf; /* preloaded CRC info from ecc data */
skipping to change at line 151 skipping to change at line 378
if(Closure->guiMode) if(Closure->guiMode)
{ if(rc->earlyTermination) { if(rc->earlyTermination)
SetAdaptiveReadFootline(_("Aborted by unrecoverable error."), Closure->r edText); SetAdaptiveReadFootline(_("Aborted by unrecoverable error."), Closure->r edText);
AllowActions(TRUE); AllowActions(TRUE);
} }
if(rc->image) if(rc->image)
if(!LargeClose(rc->image)) if(!LargeClose(rc->image))
Stop(_("Error closing image file:\n%s"), strerror(errno)); Stop(_("Error closing image file:\n%s"), strerror(errno));
if(rc->dh) CloseDevice(rc->dh);
if(rc->ei) FreeEccInfo(rc->ei); if(rc->medium) CloseImage(rc->medium);
if(rc->ei) free_ecc_info(rc->ei);
if(rc->subtitle) g_free(rc->subtitle); if(rc->subtitle) g_free(rc->subtitle);
if(rc->segmentState) g_free(rc->segmentState); if(rc->segmentState) g_free(rc->segmentState);
if(rc->ab) FreeAlignedBuffer(rc->ab); if(rc->ab) FreeAlignedBuffer(rc->ab);
if(rc->intervals) g_free(rc->intervals); if(rc->intervals) g_free(rc->intervals);
if(rc->crcBuf) FreeCrcBuf(rc->crcBuf); if(rc->crcBuf) FreeCrcBuf(rc->crcBuf);
if(rc->fingerprint) g_free(rc->fingerprint); if(rc->fingerprint) g_free(rc->fingerprint);
skipping to change at line 255 skipping to change at line 483
(long long int)rc->intervals[2*i]+rc->intervals[2*i+1]-1); (long long int)rc->intervals[2*i]+rc->intervals[2*i+1]-1);
} }
/*** /***
*** Convenience functions for printing the progress message *** Convenience functions for printing the progress message
***/ ***/
static void print_progress(read_closure *rc, int immediate) static void print_progress(read_closure *rc, int immediate)
{ int n; { int n;
int total = rc->readable+rc->correctable; int total = rc->readable+rc->correctable;
int percent = (int)((1000LL*(long long)total)/rc->sectors); int percent = (int)((1000LL*(long long)total)/rc->expectedSectors);
if(Closure->guiMode) if(Closure->guiMode)
return; return;
if( rc->lastPercent >= percent if( rc->lastPercent >= percent
&& rc->lastCorrectable == rc->correctable && rc->lastCorrectable == rc->correctable
&& rc->lastUnreadable == rc->unreadable && rc->lastUnreadable == rc->unreadable
&& !immediate) && !immediate)
return; return;
skipping to change at line 278 skipping to change at line 506
rc->lastUnreadable = rc->unreadable; rc->lastUnreadable = rc->unreadable;
if(rc->ei) if(rc->ei)
n = g_snprintf(rc->progressMsg, 256, n = g_snprintf(rc->progressMsg, 256,
_("Repairable: %2d.%1d%% (correctable: %lld; now reading [%ll d..%lld], size %lld)"), _("Repairable: %2d.%1d%% (correctable: %lld; now reading [%ll d..%lld], size %lld)"),
percent/10, percent%10, rc->correctable, percent/10, percent%10, rc->correctable,
rc->intervalStart, rc->intervalStart+rc->intervalSize-1, rc-> intervalSize); rc->intervalStart, rc->intervalStart+rc->intervalSize-1, rc-> intervalSize);
else else
n = g_snprintf(rc->progressMsg, 256, n = g_snprintf(rc->progressMsg, 256,
_("Repairable: %2d.%1d%% (missing: %lld; now reading [%lld..% lld], size %lld)"), _("Repairable: %2d.%1d%% (missing: %lld; now reading [%lld..% lld], size %lld)"),
percent/10, percent%10, rc->sectors-rc->readable, percent/10, percent%10, rc->expectedSectors-rc->readable,
rc->intervalStart, rc->intervalStart+rc->intervalSize-1, rc-> intervalSize); rc->intervalStart, rc->intervalStart+rc->intervalSize-1, rc-> intervalSize);
if(n>255) n = 255; if(n>255) n = 255;
/* If the new message is shorter, overwrite old message with spaces */ /* If the new message is shorter, overwrite old message with spaces */
if(rc->progressMsgLen > n) if(rc->progressMsgLen > n)
{ rc->progressSp[rc->progressMsgLen] = 0; { rc->progressSp[rc->progressMsgLen] = 0;
rc->progressBs[rc->progressMsgLen] = 0; rc->progressBs[rc->progressMsgLen] = 0;
PrintCLI("%s%s", rc->progressSp, rc->progressBs); PrintCLI("%s%s", rc->progressSp, rc->progressBs);
skipping to change at line 351 skipping to change at line 579
if(color == Closure->greenSector) if(color == Closure->greenSector)
{ rc->segmentState[segment]++; { rc->segmentState[segment]++;
if(rc->segmentState[segment] >= rc->sectorsPerSegment) if(rc->segmentState[segment] >= rc->sectorsPerSegment)
new = color; new = color;
/* Last segment represents less sectors */ /* Last segment represents less sectors */
if( segment == Closure->readAdaptiveSpiral->segmentClipping - 1 if( segment == Closure->readAdaptiveSpiral->segmentClipping - 1
&& rc->segmentState[segment] >= rc->sectors % rc->sectorsPerSegment) && rc->segmentState[segment] >= rc->expectedSectors % rc->sectorsPerS egment)
new = color; new = color;
} }
if(new != old) if(new != old)
{ ChangeSegmentColor(color, segment); { ChangeSegmentColor(color, segment);
changed = TRUE; changed = TRUE;
} }
} }
else changed = TRUE; else changed = TRUE;
if(changed) if(changed)
UpdateAdaptiveResults(rc->readable, rc->correctable, UpdateAdaptiveResults(rc->readable, rc->correctable,
rc->sectors-rc->readable-rc->correctable, rc->expectedSectors-rc->readable-rc->correctable,
(int)((1000LL*(rc->readable+rc->correctable))/rc->sect (int)((1000LL*(rc->readable+rc->correctable))/rc->expe
ors)); ctedSectors));
} }
/*** /***
*** Basic device and image handling and sanity checks. *** Basic device and image handling and sanity checks.
***/ ***/
/* /*
* Open CD/DVD device and .ecc file. * Open optical drive and .ecc file.
* Determine reading mode. * Determine reading mode.
*/ */
static void open_and_determine_mode(read_closure *rc) static void open_and_determine_mode(read_closure *rc)
{ unsigned char fp[16]; { unsigned char fp[16];
/* open the device */ /* open the device */
rc->dh = OpenAndQueryDevice(Closure->device); rc->medium = OpenImageFromDevice(Closure->device);
rc->dh = rc->medium->dh;
rc->readMode = IMAGE_ONLY; rc->readMode = IMAGE_ONLY;
/* save some useful information for the missing sector marker */ /* save some useful information for the missing sector marker */
if(GetMediumFingerprint(rc->dh, fp, FINGERPRINT_SECTOR)) if(GetImageFingerprint(rc->medium, fp, FINGERPRINT_SECTOR))
{ rc->fingerprint = g_malloc(16); { rc->fingerprint = g_malloc(16);
memcpy(rc->fingerprint, fp, 16); memcpy(rc->fingerprint, fp, 16);
} }
if(rc->dh->isoInfo && rc->dh->isoInfo->volumeLabel[0]) if(rc->medium->isoInfo && rc->medium->isoInfo->volumeLabel[0])
rc->volumeLabel = g_strdup(rc->dh->isoInfo->volumeLabel); rc->volumeLabel = g_strdup(rc->medium->isoInfo->volumeLabel);
/* See if we have ecc information available. /* See if we have ecc information available.
Prefer the error correction file over augmented images if both are availab le. */ Prefer the error correction file over augmented images if both are availab le. */
/* See if the medium contains RS02 type ecc information */ /* See if the medium contains RS02 type ecc information */
rc->ei = OpenEccFile(READABLE_ECC | PRINT_MODE); rc->ei = open_ecc_file(READABLE_ECC | PRINT_MODE);
if(rc->ei) /* RS01 type ecc */ if(rc->ei) /* RS01 type ecc */
{ rc->readMode = ECC_IN_FILE; { rc->readMode = ECC_IN_FILE;
rc->eh = rc->ei->eh; rc->eh = rc->ei->eh;
rc->rs01LayerSectors = (rc->ei->sectors+rc->eh->dataBytes-1)/rc->eh->dataB ytes; rc->rs01LayerSectors = (rc->ei->sectors+rc->eh->dataBytes-1)/rc->eh->dataB ytes;
SetAdaptiveReadMinimumPercentage((1000*(rc->eh->dataBytes-rc->eh->eccBytes ))/rc->eh->dataBytes); SetAdaptiveReadMinimumPercentage((1000*(rc->eh->dataBytes-rc->eh->eccBytes ))/rc->eh->dataBytes);
} }
else if(rc->dh->rs02Header) /* see if we have RS02 type ecc */ else /* see if we have RS02 type ecc */
if(rc->medium->eccHeader && !strncmp((char*)rc->medium->eccHeader->method,"RS
02",4))
{ rc->readMode = ECC_IN_IMAGE; { rc->readMode = ECC_IN_IMAGE;
rc->eh = rc->dh->rs02Header; rc->eh = rc->medium->eccHeader;
rc->lay = CalcRS02Layout(uchar_to_gint64(rc->eh->sectors), rc->eh->eccByte rc->lay = RS02LayoutFromImage(rc->medium);
s);
SetAdaptiveReadMinimumPercentage((1000*rc->lay->ndata)/255); SetAdaptiveReadMinimumPercentage((1000*rc->lay->ndata)/255);
if(Closure->version < rc->eh->neededVersion)
PrintCLI(_("* Warning: This image requires dvdisaster-%d.%d!\n"
"* Proceeding could trigger incorrect behaviour.\n"
"* Please visit http://www.dvdisaster.org for an upg
rade.\n\n"),
rc->eh->neededVersion/10000,
(rc->eh->neededVersion%10000)/100);
if(Closure->verbose) /* for testing purposes */ if(Closure->verbose) /* for testing purposes */
{ gint64 s,sinv,slice,idx; { gint64 s,sinv,slice,idx;
for(s=0; s<rc->dh->sectors-1; s++) for(s=0; s<rc->dh->sectors-1; s++)
{ RS02SliceIndex(rc->lay, s, &slice, &idx); { RS02SliceIndex(rc->lay, s, &slice, &idx);
sinv = RS02SectorIndex(rc->lay, slice, idx); sinv = RS02SectorIndex(rc->lay, slice, idx);
if(slice == -1) if(slice == -1)
Verbose("Header %lld found at sector %lld\n", idx, s); Verbose("Header %lld found at sector %lld\n", idx, s);
else else
skipping to change at line 461 skipping to change at line 698
/* /*
* Validate image size against length noted in the ecc header * Validate image size against length noted in the ecc header
*/ */
static void check_size(read_closure *rc) static void check_size(read_closure *rc)
{ {
/* Number of sectors depends on ecc data */ /* Number of sectors depends on ecc data */
switch(rc->readMode) switch(rc->readMode)
{ case IMAGE_ONLY: { case IMAGE_ONLY:
rc->sectors = rc->dh->sectors; rc->expectedSectors = rc->sectors = rc->dh->sectors;
return; return;
case ECC_IN_FILE: case ECC_IN_FILE:
rc->sectors = rc->ei->sectors; rc->sectors = rc->ei->sectors;
break; break;
case ECC_IN_IMAGE: case ECC_IN_IMAGE:
rc->sectors = rc->lay->eccSectors + rc->lay->dataSectors; rc->sectors = rc->lay->eccSectors + rc->lay->dataSectors;
break; break;
} }
rc->expectedSectors = rc->sectors; /* keep value from ecc */
/* Compare size with answer from drive */ /* Compare size with answer from drive */
if(rc->sectors < rc->dh->sectors) if(rc->sectors < rc->dh->sectors)
{ int answer; { int answer;
answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL, answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL,
_("Medium contains %lld sectors more as recorded in t he .ecc file\n" _("Medium contains %lld sectors more as recorded in t he .ecc file\n"
"(Medium: %lld sectors; expected from .ecc file: %l ld sectors).\n" "(Medium: %lld sectors; expected from .ecc file: %l ld sectors).\n"
"Only the first %lld medium sectors will be process ed.\n"), "Only the first %lld medium sectors will be process ed.\n"),
skipping to change at line 555 skipping to change at line 793
} }
/* /*
* Compare medium fingerprint against fingerprint stored in error correction fil e * Compare medium fingerprint against fingerprint stored in error correction fil e
*/ */
static void check_ecc_fingerprint(read_closure *rc) static void check_ecc_fingerprint(read_closure *rc)
{ guint8 digest[16]; { guint8 digest[16];
int fp_read; int fp_read;
fp_read = GetMediumFingerprint(rc->dh, digest, rc->eh->fpSector); fp_read = GetImageFingerprint(rc->medium, digest, rc->eh->fpSector);
if(!fp_read) /* Not readable. Bad luck. */ if(!fp_read) /* Not readable. Bad luck. */
{ int answer; { int answer;
answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL, answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL,
_("Sector %d is missing. Can not compare medium and e cc fingerprints.\n" _("Sector %d is missing. Can not compare medium and e cc fingerprints.\n"
"Double check that the medium and the ecc file belo ng together.\n"), "Double check that the medium and the ecc file belo ng together.\n"),
rc->eh->fpSector); rc->eh->fpSector);
if(!answer) if(!answer)
skipping to change at line 605 skipping to change at line 843
/* Try to read fingerprint sectors from medium and image */ /* Try to read fingerprint sectors from medium and image */
if(!LargeSeek(rc->image, (gint64)(2048*fingerprint_sector))) if(!LargeSeek(rc->image, (gint64)(2048*fingerprint_sector)))
return 0; /* can't tell, assume okay */ return 0; /* can't tell, assume okay */
n = LargeRead(rc->image, rc->buf, 2048); n = LargeRead(rc->image, rc->buf, 2048);
MD5Init(&md5ctxt); MD5Init(&md5ctxt);
MD5Update(&md5ctxt, rc->buf, 2048); MD5Update(&md5ctxt, rc->buf, 2048);
MD5Final(image_fp, &md5ctxt); MD5Final(image_fp, &md5ctxt);
fp_read = GetMediumFingerprint(rc->dh, medium_fp, fingerprint_sector); fp_read = GetImageFingerprint(rc->medium, medium_fp, fingerprint_sector);
if(n != 2048 || !fp_read || (CheckForMissingSector(rc->buf, fingerprint_secto r, NULL, 0) != SECTOR_PRESENT)) if(n != 2048 || !fp_read || (CheckForMissingSector(rc->buf, fingerprint_secto r, NULL, 0) != SECTOR_PRESENT))
return 0; /* can't tell, assume okay */ return 0; /* can't tell, assume okay */
/* If both could be read, compare them */ /* If both could be read, compare them */
if(memcmp(image_fp, medium_fp, 16)) if(memcmp(image_fp, medium_fp, 16))
{ {
if(!Closure->guiMode) if(!Closure->guiMode)
Stop(_("Image file does not match the CD/DVD.")); Stop(_("Image file does not match the optical disc."));
else else
{ int answer = ConfirmImageDeletion(Closure->imageName); { int answer = ConfirmImageDeletion(Closure->imageName);
if(!answer) if(!answer)
{ rc->earlyTermination = FALSE; { rc->earlyTermination = FALSE;
SetAdaptiveReadFootline(_("Reading aborted. Please select a different image file."), SetAdaptiveReadFootline(_("Reading aborted. Please select a different image file."),
Closure->redText); Closure->redText);
cleanup((gpointer)rc); cleanup((gpointer)rc);
} }
else else
skipping to change at line 643 skipping to change at line 881
return 0; /* okay */ return 0; /* okay */
} }
/* /*
* Compare image size with medium. * Compare image size with medium.
* TODO: image with byte sizes being not a multiple of 2048. * TODO: image with byte sizes being not a multiple of 2048.
*/ */
void check_image_size(read_closure *rc, gint64 image_file_sectors) void check_image_size(read_closure *rc, gint64 image_file_sectors)
{ {
if(image_file_sectors > rc->sectors) if(image_file_sectors > rc->expectedSectors)
{ int answer; { int answer;
answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL, answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL,
_("Image file is %lld sectors longer than inserted me dium\n" _("Image file is %lld sectors longer than inserted me dium\n"
"(Image file: %lld sectors; medium: %lld sectors).\ n"), "(Image file: %lld sectors; medium: %lld sectors).\ n"),
image_file_sectors-rc->sectors, image_file_sectors, r image_file_sectors-rc->expectedSectors,
c->sectors); image_file_sectors, rc->expectedSectors);
if(!answer) if(!answer)
{ SetAdaptiveReadFootline(_("Aborted by user request!"), Closure->redText ); { SetAdaptiveReadFootline(_("Aborted by user request!"), Closure->redText );
rc->earlyTermination = FALSE; rc->earlyTermination = FALSE;
cleanup((gpointer)rc); cleanup((gpointer)rc);
} }
rc->highestWrittenSector = rc->sectors-1; rc->highestWrittenSector = rc->sectors-1;
} }
else rc->highestWrittenSector = image_file_sectors-1; else rc->highestWrittenSector = image_file_sectors-1;
skipping to change at line 671 skipping to change at line 910
/*** /***
*** Load the crc buf from RS01/RS02 error correction data. *** Load the crc buf from RS01/RS02 error correction data.
***/ ***/
static void load_crc_buf(read_closure *rc) static void load_crc_buf(read_closure *rc)
{ {
switch(rc->readMode) switch(rc->readMode)
{ case ECC_IN_FILE: { case ECC_IN_FILE:
SetAdaptiveReadSubtitle(_utf("Loading CRC data.")); SetAdaptiveReadSubtitle(_utf("Loading CRC data."));
rc->crcBuf = GetCRCFromRS01(rc->ei); rc->crcBuf = GetCRCFromRS01_obsolete(rc->ei);
break; break;
case ECC_IN_IMAGE: case ECC_IN_IMAGE:
SetAdaptiveReadSubtitle(_utf("Loading CRC data.")); SetAdaptiveReadSubtitle(_utf("Loading CRC data."));
rc->crcBuf = GetCRCFromRS02(rc->lay, rc->dh, rc->image); rc->crcBuf = GetCRCFromRS02_obsolete(rc->lay, rc->dh, rc->image);
break; break;
default: default:
rc->crcBuf = NULL; rc->crcBuf = NULL;
break; break;
} }
} }
/*** /***
*** Examine existing image file. *** Examine existing image file.
*** ***
skipping to change at line 730 skipping to change at line 969
n = LargeRead(rc->image, rc->buf, 2048); n = LargeRead(rc->image, rc->buf, 2048);
if(n != 2048) /* && (s != rc->sectors - 1 || n != ii->inLast)) */ if(n != 2048) /* && (s != rc->sectors - 1 || n != ii->inLast)) */
Stop(_("premature end in image (only %d bytes): %s\n"),n,strerror(errno)) ; Stop(_("premature end in image (only %d bytes): %s\n"),n,strerror(errno)) ;
/* Look for the dead sector marker */ /* Look for the dead sector marker */
current_missing = CheckForMissingSector(rc->buf, s, NULL, 0); current_missing = CheckForMissingSector(rc->buf, s, NULL, 0);
if(current_missing) if(current_missing)
{ mark_sector(rc, s, Closure->redSector); { int fixme=0;
ExplainMissingSector(rc->buf, s, current_missing, TRUE); mark_sector(rc, s, Closure->redSector);
ExplainMissingSector(rc->buf, s, current_missing, SOURCE_IMAGE, &fixme);
} }
/* Compare checksums if available */ /* Compare checksums if available */
if(rc->crcBuf) if(rc->crcBuf)
crc_result = CheckAgainstCrcBuffer(rc->crcBuf, s, rc->buf); crc_result = CheckAgainstCrcBuffer(rc->crcBuf, s, rc->buf);
else crc_result = CRC_UNKNOWN; else crc_result = CRC_UNKNOWN;
switch(crc_result) switch(crc_result)
{ case CRC_GOOD: { case CRC_GOOD:
skipping to change at line 811 skipping to change at line 1051
last_percent = percent; last_percent = percent;
} }
} }
/*** If the image is shorter than the medium and the missing part /*** If the image is shorter than the medium and the missing part
was not already included in the last interval, was not already included in the last interval,
insert another interval for the missing portion. */ insert another interval for the missing portion. */
if(s<rc->lastSector && !tail_included) /* truncated image? */ if(s<rc->lastSector && !tail_included) /* truncated image? */
add_interval(rc, s, rc->lastSector-s+1); { gint first, length;
/* Make sure the remainder lies with the specified reading range */
if(s<rc->firstSector)
first=rc->firstSector;
else first=s;
length = rc->lastSector-first+1;
if(length > 0)
add_interval(rc, first, length);
}
/*** Now that all readable sectors are known, /*** Now that all readable sectors are known,
determine those which can already be corrected. */ determine those which can already be corrected. */
if(Closure->guiMode) if(Closure->guiMode)
SetAdaptiveReadSubtitle(_("Determining correctable sectors")); SetAdaptiveReadSubtitle(_("Determining correctable sectors"));
/* RS01 type error correction. */ /* RS01 type error correction. */
if(rc->readMode == ECC_IN_FILE) if(rc->readMode == ECC_IN_FILE)
skipping to change at line 893 skipping to change at line 1144
} }
} }
} }
} }
} }
/*** Tell user results of image file analysis */ /*** Tell user results of image file analysis */
if(rc->readMode == ECC_IN_FILE || rc->readMode == ECC_IN_IMAGE) if(rc->readMode == ECC_IN_FILE || rc->readMode == ECC_IN_IMAGE)
PrintLog(_("Analysing existing image file: %lld readable, %lld correctab le, %lld still missing.\n"), PrintLog(_("Analysing existing image file: %lld readable, %lld correctab le, %lld still missing.\n"),
rc->readable, rc->correctable, rc->sectors-rc->readable-rc->corr ectable); rc->readable, rc->correctable, rc->expectedSectors-rc->readable- rc->correctable);
else PrintLog(_("Analysing existing image file: %lld readable, %lld still mis sing.\n"), else PrintLog(_("Analysing existing image file: %lld readable, %lld still mis sing.\n"),
rc->readable, rc->sectors-rc->readable-rc->correctable); rc->readable, rc->expectedSectors-rc->readable-rc->correctable);
if(Closure->guiMode) if(Closure->guiMode)
UpdateAdaptiveResults(rc->readable, rc->correctable, UpdateAdaptiveResults(rc->readable, rc->correctable,
rc->sectors-rc->readable-rc->correctable, rc->expectedSectors-rc->readable-rc->correctable,
(int)((1000LL*(rc->readable+rc->correctable))/rc->sect (int)((1000LL*(rc->readable+rc->correctable))/rc->expe
ors)); ctedSectors));
// print_intervals(rc); // print_intervals(rc);
} }
/*** Mark RS02 header sectors as correctable. /*** Mark RS02 header sectors as correctable.
These are not part of any ecc block and have no influence on These are not part of any ecc block and have no influence on
the decision when enough data has been gathered for error correction. the decision when enough data has been gathered for error correction.
Since they are needed for recognizing the image we will rewrite all Since they are needed for recognizing the image we will rewrite all
them from the copy we got in rc->eh, but this can only be done when them from the copy we got in rc->eh, but this can only be done when
the image file has been fully created. */ the image file has been fully created. */
static void mark_rs02_headers(read_closure *rc) static void mark_rs02_headers(read_closure *rc)
skipping to change at line 1027 skipping to change at line 1278
rc->earlyTermination = FALSE; /* suppress respective error message */ rc->earlyTermination = FALSE; /* suppress respective error message */
cleanup((gpointer)rc); cleanup((gpointer)rc);
} }
/* Cycle the progress animation */ /* Cycle the progress animation */
if(j++ % 2000) if(j++ % 2000)
{ int seq = (j/2000)%10; { int seq = (j/2000)%10;
if(!Closure->guiMode) if(!Closure->guiMode)
{ g_printf(anim[seq]); { g_printf("%s", anim[seq]);
fflush(stdout); /* at least needed for Windows */ fflush(stdout);
} }
} }
/* Show progress in the spiral */ /* Show progress in the spiral */
if(Closure->guiMode) if(Closure->guiMode)
{ int segment = i / rc->sectorsPerSegment; { int segment = i / rc->sectorsPerSegment;
if(Closure->readAdaptiveSpiral->segmentColor[segment] == Closure->backgr ound) if(Closure->readAdaptiveSpiral->segmentColor[segment] == Closure->backgr ound)
ChangeSegmentColor(Closure->whiteSector, segment); ChangeSegmentColor(Closure->whiteSector, segment);
skipping to change at line 1083 skipping to change at line 1334
rc->highestWrittenSector = correctable; rc->highestWrittenSector = correctable;
} }
} }
/* /*
* The adaptive read strategy * The adaptive read strategy
*/ */
void ReadMediumAdaptive(gpointer data) void ReadMediumAdaptive(gpointer data)
{ read_closure *rc; { read_closure *rc;
gint64 s; guint64 s;
gint64 image_file_size; guint64 image_file_size;
int status,i,n; int status,i,n;
/*** Initialize the read closure. */ /*** Initialize the read closure. */
rc = g_malloc0(sizeof(read_closure)); rc = g_malloc0(sizeof(read_closure));
rc->ab = CreateAlignedBuffer(MAX_CLUSTER_SIZE); rc->ab = CreateAlignedBuffer(MAX_CLUSTER_SIZE);
rc->buf = rc->ab->buf; rc->buf = rc->ab->buf;
memset(rc->progressBs, '\b', 256); memset(rc->progressBs, '\b', 256);
skipping to change at line 1107 skipping to change at line 1358
/*** Register the cleanup procedure so that Stop() can abort us properly. */ /*** Register the cleanup procedure so that Stop() can abort us properly. */
rc->earlyTermination = TRUE; rc->earlyTermination = TRUE;
RegisterCleanup(_("Reading aborted"), cleanup, rc); RegisterCleanup(_("Reading aborted"), cleanup, rc);
if(Closure->guiMode) if(Closure->guiMode)
SetLabelText(GTK_LABEL(Closure->readAdaptiveHeadline), "<big>%s</big>\n<i>% s</i>", SetLabelText(GTK_LABEL(Closure->readAdaptiveHeadline), "<big>%s</big>\n<i>% s</i>",
_("Preparing for reading the medium image."), _("Preparing for reading the medium image."),
_("Medium: not yet determined")); _("Medium: not yet determined"));
/* Please note: Commenting the follwing Stop() out will provide
adaptive reading for RS01 and RS02, but behaviour with RS03
is unpredictable und undefind. Therefore feel free to re-enable
adaptive reading for your own use, but do not distibute such
binaries to unsuspecting users.
Adaptive reading will be re-introduced for all codecs
in one of the next versions. */
#if 1
Stop(_("Adaptive reading is unavailable in this version.\n"
"It will be re-introduced in one of the next versions."));
#endif
/*** Open Device and .ecc file. Determine read mode. */ /*** Open Device and .ecc file. Determine read mode. */
open_and_determine_mode(rc); open_and_determine_mode(rc);
if(rc->readMode == IMAGE_ONLY)
{ PrintCLI(_("* Warning: Using adaptive reading without error correction dat
a\n"
"* has little advantage over linear reading, but may\n"
"* cause significant wear on the drive due to excessive
\n"
"* seek operations.\n"
"* Please consider using linear reading instead.\n"));
}
/*** Compare image and ecc fingerprints (only if RS01 type .ecc is available) */ /*** Compare image and ecc fingerprints (only if RS01 type .ecc is available) */
if(rc->readMode == ECC_IN_FILE) if(rc->readMode == ECC_IN_FILE)
check_ecc_fingerprint(rc); check_ecc_fingerprint(rc);
/*** Validate image size against ecc data */ /*** Validate image size against ecc data */
check_size(rc); check_size(rc);
/*** Limit the read range from users choice */ /*** Limit the read range from users choice */
skipping to change at line 1133 skipping to change at line 1405
rc->intervalStart = rc->firstSector; rc->intervalStart = rc->firstSector;
rc->intervalEnd = rc->lastSector; rc->intervalEnd = rc->lastSector;
rc->intervalSize = rc->intervalEnd - rc->intervalStart + 1; rc->intervalSize = rc->intervalEnd - rc->intervalStart + 1;
/*** Initialize the sector bitmap if ecc information is present. /*** Initialize the sector bitmap if ecc information is present.
This is used to stop when sufficient data for error correction This is used to stop when sufficient data for error correction
becomes available. */ becomes available. */
if( rc->readMode == ECC_IN_FILE if( rc->readMode == ECC_IN_FILE
|| rc->readMode == ECC_IN_IMAGE) || rc->readMode == ECC_IN_IMAGE)
rc->map = CreateBitmap0(rc->sectors); rc->map = CreateBitmap0(rc->expectedSectors);
#ifdef CHECK_VISITED #ifdef CHECK_VISITED
rc->count = g_malloc0((int)rc->sectors+160); rc->count = g_malloc0((int)rc->expectedSectors+160);
#endif #endif
/*** Initialize segment state counters (only in GUI mode) */ /*** Initialize segment state counters (only in GUI mode) */
if(Closure->guiMode) if(Closure->guiMode)
{ //rc->sectorsPerSegment = 1 + (rc->sectors / ADAPTIVE_READ_SPIRAL_SIZE); { //rc->sectorsPerSegment = 1 + (rc->sectors / ADAPTIVE_READ_SPIRAL_SIZE);
rc->sectorsPerSegment = ((rc->sectors+ADAPTIVE_READ_SPIRAL_SIZE-1) / ADAPT IVE_READ_SPIRAL_SIZE); rc->sectorsPerSegment = ((rc->expectedSectors+ADAPTIVE_READ_SPIRAL_SIZE-1) / ADAPTIVE_READ_SPIRAL_SIZE);
rc->segmentState = g_malloc0(ADAPTIVE_READ_SPIRAL_SIZE * sizeof(int)); rc->segmentState = g_malloc0(ADAPTIVE_READ_SPIRAL_SIZE * sizeof(int));
// ClipReadAdaptiveSpiral(rc->sectors/rc->sectorsPerSegment); // ClipReadAdaptiveSpiral(rc->sectors/rc->sectorsPerSegment);
ClipReadAdaptiveSpiral((rc->sectors+rc->sectorsPerSegment-1)/rc->sectorsPe rSegment); ClipReadAdaptiveSpiral((rc->expectedSectors+rc->sectorsPerSegment-1)/rc->s ectorsPerSegment);
} }
/*** Initialize the interval list */ /*** Initialize the interval list */
rc->intervals = g_malloc(8*sizeof(gint64)); rc->intervals = g_malloc(8*sizeof(gint64));
rc->maxIntervals = 4; rc->maxIntervals = 4;
rc->nIntervals = 0; rc->nIntervals = 0;
/*** Start with a fresh image file if none is already present. */ /*** Start with a fresh image file if none is already present. */
skipping to change at line 1218 skipping to change at line 1490
/* Build the interval list */ /* Build the interval list */
build_interval_from_image(rc); build_interval_from_image(rc);
/* Mark still missing RS02 header sectors as correctable. */ /* Mark still missing RS02 header sectors as correctable. */
mark_rs02_headers(rc); mark_rs02_headers(rc);
/* Already enough information available? */ /* Already enough information available? */
if(rc->readable + rc->correctable >= rc->sectors) if(rc->readable + rc->correctable >= rc->expectedSectors)
{ char *t = _("\nSufficient data for reconstructing the image is availabl e.\n"); { char *t = _("\nSufficient data for reconstructing the image is availabl e.\n");
PrintLog(t);
if(Closure->guiMode) if(rc->readMode != IMAGE_ONLY)
SetAdaptiveReadFootline(t, Closure->greenText); { PrintLog(t);
if(Closure->guiMode)
SetAdaptiveReadFootline(t, Closure->greenText);
}
goto finished; goto finished;
} }
/* Nope, begin with first interval */ /* Nope, begin with first interval */
if(!rc->nIntervals) /* may happen when reading range is restricted too mu ch */ if(!rc->nIntervals) /* may happen when reading range is restricted too mu ch */
goto finished; goto finished;
rc->intervalStart = rc->intervals[0]; rc->intervalStart = rc->intervals[0];
rc->intervalSize = rc->intervals[1]; rc->intervalSize = rc->intervals[1];
skipping to change at line 1245 skipping to change at line 1520
} }
/*** Read the medium image. */ /*** Read the medium image. */
if(Closure->guiMode) if(Closure->guiMode)
SetAdaptiveReadSubtitle(rc->subtitle); SetAdaptiveReadSubtitle(rc->subtitle);
for(;;) for(;;)
{ int cluster_mask = rc->dh->clusterSize-1; { int cluster_mask = rc->dh->clusterSize-1;
Verbose("... Processing Interval [%lld..%lld], size %d\n",
rc->intervalStart, rc->intervalStart+rc->intervalSize-1, rc->interv
alSize);
/* If we jumped beyond the highest writtensector, /* If we jumped beyond the highest writtensector,
fill the gap with dead sector markers. */ fill the gap with dead sector markers.
Note that we do not have to fill anything if
rc->intervalStart == rc->highestWrittenSector+1
as then next sector after rc->highestWrittenSector will
be written anyways. */
if(rc->intervalStart > rc->highestWrittenSector) if(rc->intervalStart > rc->highestWrittenSector+1)
fill_gap(rc); fill_gap(rc);
/*** Try reading the next interval */ /*** Try reading the next interval */
print_progress(rc, TRUE); print_progress(rc, TRUE);
for(s=rc->intervalStart; s<=rc->intervalEnd; ) /* s is incremented elsewhe re */ for(s=rc->intervalStart; s<=rc->intervalEnd; ) /* s is incremented elsewhe re */
{ int nsectors,cnt; { int nsectors,cnt;
if(Closure->stopActions) /* somebody hit the Stop button */ if(Closure->stopActions) /* somebody hit the Stop button */
skipping to change at line 1418 skipping to change at line 1700
rc->highestWrittenSector = b; rc->highestWrittenSector = b;
break; break;
} }
/*** Warn the user if we see dead sector markers on the image. /*** Warn the user if we see dead sector markers on the image.
Note: providing the fingerprint is not necessary as any Note: providing the fingerprint is not necessary as any
incoming missing sector marker indicates a huge problem. */ incoming missing sector marker indicates a huge problem. */
err = CheckForMissingSector(rc->buf+i*2048, b, NULL, 0); err = CheckForMissingSector(rc->buf+i*2048, b, NULL, 0);
if(err != SECTOR_PRESENT) if(err != SECTOR_PRESENT)
{ ExplainMissingSector(rc->buf+i*2048, b, err, FALSE); { int fixme;
ExplainMissingSector(rc->buf+i*2048, b, err, SOURCE_MEDIUM, &fi
xme);
if(rc->map) /* Avoids confusion in the ecc stage */ if(rc->map) /* Avoids confusion in the ecc stage */
ClearBit(rc->map, b); ClearBit(rc->map, b);
rc->readable--; rc->readable--;
} }
} }
/* See if additional sectors become correctable. */ /* See if additional sectors become correctable. */
if(rc->readMode == ECC_IN_FILE) /* RS01 type ecc data */ if(rc->readMode == ECC_IN_FILE) /* RS01 type ecc data */
skipping to change at line 1519 skipping to change at line 1802
if we added sectors beyond the image size. */ if we added sectors beyond the image size. */
s+=nsectors; s+=nsectors;
#if 0 /* obsoleted since it is carried out right after the LargeWrite() above */ #if 0 /* obsoleted since it is carried out right after the LargeWrite() above */
if(s>rc->highestWrittenSector) rc->highestWrittenSector=s; if(s>rc->highestWrittenSector) rc->highestWrittenSector=s;
#endif #endif
/* Stop reading if enough data for error correction /* Stop reading if enough data for error correction
has been gathered */ has been gathered */
if(rc->readable + rc->correctable >= rc->sectors) if(rc->readable + rc->correctable >= rc->expectedSectors)
{ char *t = _("\nSufficient data for reconstructing the image is ava ilable.\n"); { char *t = _("\nSufficient data for reconstructing the image is ava ilable.\n");
print_progress(rc, TRUE); print_progress(rc, TRUE);
PrintLog(t); if(rc->readMode != IMAGE_ONLY)
if(Closure->guiMode && rc->ei) { PrintLog(t);
SetAdaptiveReadFootline(t, Closure->foreground); if(Closure->guiMode && rc->ei)
SetAdaptiveReadFootline(t, Closure->foreground);
}
if(Closure->eject) if(Closure->eject)
LoadMedium(rc->dh, FALSE); LoadMedium(rc->dh, FALSE);
goto finished; goto finished;
} }
} /* end of if(!status) (successful reading of sector(s)) */ } /* end of if(!status) (successful reading of sector(s)) */
else /* Process the read error. */ else /* Process the read error. */
{ unsigned char buf[2048]; { unsigned char buf[2048];
PrintCLI("\n"); PrintCLI("\n");
skipping to change at line 1589 skipping to change at line 1874
//print_intervals(rc); //print_intervals(rc);
} }
break; /* fall out of reading loop */ break; /* fall out of reading loop */
} }
print_progress(rc, FALSE); print_progress(rc, FALSE);
} }
/* If we reach this, the current interval has either been read completely /* If we reach this, the current interval has either been read completely
or the loop was terminated early by a read error. or the loop was terminated early by a read error.
In both cases, the current interval has already been remove from the qu eue In both cases, the current interval has already been removed from the q ueue
and the queue contains only the still unprocessed intervals. */ and the queue contains only the still unprocessed intervals. */
if(s>=rc->intervalEnd) /* we fell out of the reading loop with interval co mpleted */ if(s>=rc->intervalEnd) /* we fell out of the reading loop with interval co mpleted */
{ print_progress(rc, TRUE); { print_progress(rc, TRUE);
PrintCLI("\n"); PrintCLI("\n");
} }
/* Pop the next interval from the queue, /* Pop the next interval from the queue,
prepare one half from it for processing prepare one half from it for processing
and push the other half back on the queue. */ and push the other half back on the queue. */
skipping to change at line 1638 skipping to change at line 1923
/* Apply interval size termination criterion */ /* Apply interval size termination criterion */
if(rc->intervalSize < Closure->sectorSkip) if(rc->intervalSize < Closure->sectorSkip)
goto finished; goto finished;
} }
finished: finished:
#ifdef CHECK_VISITED #ifdef CHECK_VISITED
{ int i,cnt=0; { int i,cnt=0;
for(i=0; i<(int)rc->sectors; i++) for(i=0; i<(int)rc->expectedSectors; i++)
{ cnt+=rc->count[i]; { cnt+=rc->count[i];
if(rc->count[i] != 1) if(rc->count[i] != 1)
printf("Sector %d: %d\n",i,rc->count[i]); printf("Sector %d: %d\n",i,rc->count[i]);
} }
printf("\nTotal visited %d (%d)\n",cnt,i); printf("\nTotal visited %d (%d)\n",cnt,i);
for(i=(int)rc->sectors; i<(int)rc->sectors+160; i++) for(i=(int)rc->expectedSectors; i<(int)rc->expectedSectors+160; i++)
if(rc->count[i] != 0) if(rc->count[i] != 0)
printf("SECTOR %d: %d\n",i,rc->count[i]); printf("SECTOR %d: %d\n",i,rc->count[i]);
} }
#endif #endif
/* Force output of final results */ /* Force output of final results */
if(Closure->guiMode) if(Closure->guiMode)
{ ChangeSpiralCursor(Closure->readAdaptiveSpiral, -1); { ChangeSpiralCursor(Closure->readAdaptiveSpiral, -1);
mark_sector(rc, 0, NULL); mark_sector(rc, 0, NULL);
} }
/*** Summarize results. */ /*** Summarize results. */
/* We were in ECC_IN_FILE or ECC_IN_IMAGE mode, /* We were in ECC_IN_FILE or ECC_IN_IMAGE mode,
but did not recover sufficient data. */ but did not recover sufficient data. */
if(rc->map && (rc->readable + rc->correctable < rc->sectors)) if(rc->map && (rc->readable + rc->correctable < rc->expectedSectors))
{ int total = rc->readable+rc->correctable; { int total = rc->readable+rc->correctable;
int percent = (int)((1000LL*(long long)total)/rc->sectors); int percent = (int)((1000LL*(long long)total)/rc->expectedSectors);
char *t = g_strdup_printf(_("Only %2d.%1d%% of the image are readable or c orrectable"), char *t = g_strdup_printf(_("Only %2d.%1d%% of the image are readable or c orrectable"),
percent/10, percent%10); percent/10, percent%10);
PrintLog(_("\n%s\n" PrintLog(_("\n%s\n"
"(%lld readable, %lld correctable, %lld still missing).\n"), "(%lld readable, %lld correctable, %lld still missing).\n"),
t, rc->readable, rc->correctable, rc->sectors-total); t, rc->readable, rc->correctable, rc->expectedSectors-total);
if(Closure->guiMode) if(Closure->guiMode)
SetAdaptiveReadFootline(t, Closure->foreground); SetAdaptiveReadFootline(t, Closure->foreground);
g_free(t); g_free(t);
exitCode = EXIT_FAILURE; exitCode = EXIT_FAILURE;
} }
/* Results for reading in IMAGE_ONLY mode */ /* Results for reading in IMAGE_ONLY mode */
if(rc->readMode == IMAGE_ONLY) if(rc->readMode == IMAGE_ONLY)
{ if(rc->readable == rc->sectors) { if(rc->readable == rc->expectedSectors)
{ char *t = _("\nGood! All sectors have been read.\n"); { char *t = _("\nGood! All sectors have been read.\n");
PrintLog(t); PrintLog(t);
if(Closure->guiMode) if(Closure->guiMode)
SetAdaptiveReadFootline(t, Closure->foreground); SetAdaptiveReadFootline(t, Closure->foreground);
if(Closure->eject) if(Closure->eject)
LoadMedium(rc->dh, FALSE); LoadMedium(rc->dh, FALSE);
} }
else else
{ int percent = (int)((1000LL*rc->readable)/rc->sectors); { int percent = (int)((1000LL*rc->readable)/rc->expectedSectors);
char *t = g_strdup_printf(_("No unreadable intervals with >= %d sectors left."), char *t = g_strdup_printf(_("No unreadable intervals with >= %d sectors left."),
Closure->sectorSkip); Closure->sectorSkip);
PrintLog(_("\n%s\n" PrintLog(_("\n%s\n"
"%2d.%1d%% of the image have been read (%lld sectors).\n"), "%2d.%1d%% of the image have been read (%lld sectors).\n"),
t, percent/10, percent%10, rc->readable); t, percent/10, percent%10, rc->readable);
if(Closure->guiMode) if(Closure->guiMode)
SetAdaptiveReadFootline(t, Closure->foreground); SetAdaptiveReadFootline(t, Closure->foreground);
g_free(t); g_free(t);
exitCode = EXIT_FAILURE; exitCode = EXIT_FAILURE;
} }
} }
#if 0 #if 0
for(i=0; i<rc->sectors; i++) for(i=0; i<rc->expectedSectors; i++)
if(!GetBit(rc->map, i)) if(!GetBit(rc->map, i))
printf("Missing: %d\n", i); printf("Missing: %d\n", i);
#endif #endif
//print_intervals(rc);
/*** Close and clean up */ /*** Close and clean up */
rc->earlyTermination = FALSE; rc->earlyTermination = FALSE;
terminate: terminate:
cleanup((gpointer)rc); cleanup((gpointer)rc);
} }
 End of changes. 63 change blocks. 
75 lines changed or deleted 369 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS