New upstream version 0.79.5

This commit is contained in:
TANIGUCHI Takaki
2017-02-02 22:24:37 +09:00
parent 2f23ea4b4a
commit 9ad5d25d65
1931 changed files with 104660 additions and 254637 deletions

View File

@@ -1,25 +1,26 @@
/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2012 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
* Copyright (C) 2004-2015 Carsten Gnoerlich.
*
* The Reed-Solomon error correction draws a lot of inspiration - and even code -
* from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/
*
* 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
* 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.
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA,
* or direct your browser at http://www.gnu.org.
* along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dvdisaster.h"
@@ -56,10 +57,9 @@ typedef struct
{ RS01Widgets *wl;
GaloisTables *gt;
ReedSolomonTables *rt;
Image *image;
int earlyTermination;
char *msg;
ImageInfo *ii;
EccInfo *ei;
unsigned char *imgBlock[256];
guint32 *crcBuf[256];
} fix_closure;
@@ -68,7 +68,7 @@ static void fix_cleanup(gpointer data)
{ fix_closure *fc = (fix_closure*)data;
int i;
Closure->cleanupProc = NULL;
UnregisterCleanup();
if(Closure->guiMode)
{ if(fc->earlyTermination)
@@ -81,9 +81,8 @@ static void fix_cleanup(gpointer data)
/** Clean up */
if(fc->image) CloseImage(fc->image);
if(fc->msg) g_free(fc->msg);
if(fc->ii) FreeImageInfo(fc->ii);
if(fc->ei) FreeEccInfo(fc->ei);
for(i=0; i<256; i++)
{ if(fc->imgBlock[i])
@@ -105,23 +104,21 @@ static void fix_cleanup(gpointer data)
* Try to repair the image
*/
void RS01Fix(Method *method)
{ RS01Widgets *wl = (RS01Widgets*)method->widgetList;
void RS01Fix(Image *image)
{ Method *method = FindMethod("RS01");
RS01Widgets *wl = (RS01Widgets*)method->widgetList;
GaloisTables *gt;
ReedSolomonTables *rt;
fix_closure *fc = g_malloc0(sizeof(fix_closure));
ImageInfo *ii = NULL;
EccInfo *ei = NULL;
EccHeader *eh = NULL;
unsigned char parity[256];
int erasure_count,erasure_list[256],erasure_map[256];
int unexpected_failure;
gint64 block_idx[256];
gint64 s,si;
int i,j,k,n;
gint64 corrected, uncorrected;
gint64 last_corrected, last_uncorrected;
gint64 parity_block = 0;
guint64 expected_image_size;
int worst_ecc,damaged_ecc,damaged_sec,percent,last_percent = -1;
int cache_size,cache_sector,cache_offset = 0;
int local_plot_max;
@@ -133,20 +130,12 @@ void RS01Fix(Method *method)
/*** Register the cleanup procedure for GUI mode */
fc->image = image;
fc->wl = wl;
fc->earlyTermination = TRUE;
RegisterCleanup(_("Repairing of image aborted"), fix_cleanup, fc);
/*** Open the image and ecc files */
if(Closure->guiMode)
SetLabelText(GTK_LABEL(wl->fixHeadline),
_("<big>Repairing the image.</big>\n<i>%s</i>"),
_("Opening files..."));
ei = fc->ei = OpenEccFile(READABLE_ECC);
eh = ei->eh;
ii = fc->ii = OpenImageFile(eh, WRITEABLE_IMAGE);
eh = image->eccFileHeader;
/*** Announce what we are going to do. */
@@ -157,19 +146,44 @@ void RS01Fix(Method *method)
if(Closure->guiMode)
{ SetLabelText(GTK_LABEL(wl->fixHeadline),
_("<big>Repairing the image.</big>\n<i>%s</i>"),fc->msg);
RS01SetFixMaxValues(wl, eh->dataBytes, eh->eccBytes, ii->sectors);
RS01SetFixMaxValues(wl, eh->dataBytes, eh->eccBytes, image->sectorSize);
}
PrintLog(_("\nFix mode: Repairable sectors will be fixed in the image.\n"));
PrintLog(_("\nFix mode(%s): Repairable sectors will be fixed in the image.\n"),
"RS01");
/*** Do some trivial comparisons between the .ecc file and the image file */
if(!eh->inLast) /* field is unused/zero in versions prior to 0.66 */
eh->inLast = 2048;
if(ii->sectors > ei->sectors)
{ gint64 diff = ii->sectors - ei->sectors;
gint64 wanted_size = 2048LL*(ei->sectors-1LL) + (gint64)eh->inLast;
expected_image_size = 2048*(image->expectedSectors-1)+eh->inLast;
/* Special case: If the iso file is a few bytes too short
or too long, and the last bytes are zeroes, the
codec won't discover the mismatch from the CRC sum.
Fill up the missing bytes with zeroes here; this
will either be correct or picked up by the CRC
compare later. */
if(image->sectorSize == image->expectedSectors
&& image->inLast < eh->inLast)
{ int padding = eh->inLast - image->inLast;
unsigned char buf[padding];
int n;
memset(buf, 0, padding);
LargeSeek(image->file, image->file->size);
n = LargeWrite(image->file, buf, padding);
image->file->size += n;
image->inLast += n;
if(n != padding)
Stop(_("Failed writing to sector %lld in image [%s]: %s"),
image->sectorSize, "SC", strerror(errno));
}
if(image->file->size > expected_image_size)
{ gint64 diff = image->sectorSize - image->expectedSectors;
char *trans = _("The image file is %lld sectors longer as noted in the\n"
"ecc file. This might simply be zero padding, especially\n"
"on dual layer DVD media, but could also mean that\n"
@@ -191,10 +205,10 @@ void RS01Fix(Method *method)
goto terminate;
}
ii->sectors -= diff;
ii->inLast = eh->inLast;
image->sectorSize -= diff;
image->inLast = eh->inLast;
if(!LargeTruncate(ii->file, wanted_size))
if(!LargeTruncate(image->file, expected_image_size))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
}
@@ -213,10 +227,10 @@ void RS01Fix(Method *method)
goto terminate;
}
ii->sectors -= diff;
ii->inLast = eh->inLast;
image->sectorSize -= diff;
image->inLast = eh->inLast;
if(!LargeTruncate(ii->file, wanted_size))
if(!LargeTruncate(image->file, expected_image_size))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
PrintLog(_("Image has been truncated by %lld sectors.\n"), diff);
@@ -229,24 +243,23 @@ void RS01Fix(Method *method)
_("Add the --truncate option to the program call\n"
"to have the superfluous sectors removed."));
ii->sectors -= diff;
ii->inLast = eh->inLast;
image->sectorSize -= diff;
image->inLast = eh->inLast;
if(!LargeTruncate(ii->file, wanted_size))
if(!LargeTruncate(image->file, expected_image_size))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
PrintLog(_("Image has been truncated by %lld sectors.\n"), diff);
}
}
if(ii->sectors == ei->sectors && ii->inLast > eh->inLast)
{ int difference = ii->inLast - eh->inLast;
gint64 wanted_size = 2048LL*(ei->sectors-1LL) + (gint64)eh->inLast;
if(image->sectorSize == image->expectedSectors && image->inLast > eh->inLast)
{ int difference = image->inLast - eh->inLast;
if(Closure->guiMode)
{ int answer = ModalDialog(GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, NULL,
_("The image file is %d bytes longer than noted\n"
"in the ecc file. Shall the superflous bytes\n"
"in the ecc file. Shall the superfluous bytes\n"
"be removed from the image file?\n"),
difference);
@@ -267,14 +280,14 @@ void RS01Fix(Method *method)
"to have the superfluous sectors removed."),
difference);
if(!LargeTruncate(ii->file, wanted_size))
if(!LargeTruncate(image->file, expected_image_size))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
PrintLog(_("Image has been truncated by %d bytes.\n"), difference);
ii->inLast = eh->inLast;
image->inLast = eh->inLast;
}
if(ii->sectors < ei->sectors)
if(image->sectorSize < image->expectedSectors)
{ int answer;
answer = ModalWarning(GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, NULL,
@@ -290,7 +303,7 @@ void RS01Fix(Method *method)
}
}
if(!memcmp(ii->mediumFP, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16))
if(image->fpState != FP_PRESENT)
{ int answer;
answer = ModalWarning(GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, NULL,
@@ -306,7 +319,7 @@ void RS01Fix(Method *method)
goto terminate;
}
}
else if(memcmp(ii->mediumFP, eh->mediumFP, 16))
else if(memcmp(image->imageFP, eh->mediumFP, 16))
Stop(_("Fingerprints of image and ecc file do not match.\n"
"Image and ecc file do not belong together.\n"));
@@ -325,7 +338,7 @@ void RS01Fix(Method *method)
Our ecc blocks are built from ndata medium sectors spread over the full medium size.
We read cache_size * ndata medium sectors ahead. */
cache_size = 2*Closure->cacheMB; /* ndata medium sectors are approx. 0.5MB */
cache_size = 2*Closure->cacheMiB; /* ndata medium sectors are approx. 0.5MiB */
for(i=0; i<ndata; i++)
{ fc->imgBlock[i] = g_malloc(cache_size*2048);
@@ -335,7 +348,7 @@ void RS01Fix(Method *method)
/*** Setup the block counters for mapping medium sectors to
ecc blocks */
s = (ei->sectors+ndata-1)/ndata;
s = (image->expectedSectors+ndata-1)/ndata;
for(si=0, i=0; i<ndata; si+=s, i++)
block_idx[i] = si;
@@ -345,16 +358,16 @@ void RS01Fix(Method *method)
/*** Verify ecc information for the medium image. */
corrected = uncorrected = 0;
last_corrected = last_uncorrected = 0;
worst_ecc = damaged_ecc = damaged_sec = local_plot_max = 0;
for(si=0; si<s; si++)
{
if(Closure->stopActions) /* User hit the Stop button */
{ SwitchAndSetFootline(fc->wl->fixNotebook, 1,
fc->wl->fixFootline,
_("<span %s>Aborted by user request!</span>"),
Closure->redMarkup);
{ if(Closure->stopActions == STOP_CURRENT_ACTION) /* suppress memleak warning when closing window */
SwitchAndSetFootline(fc->wl->fixNotebook, 1,
fc->wl->fixFootline,
_("<span %s>Aborted by user request!</span>"),
Closure->redMarkup);
fc->earlyTermination = FALSE; /* suppress respective error message */
goto terminate;
}
@@ -369,10 +382,10 @@ void RS01Fix(Method *method)
for(i=0; i<ndata; i++)
{ int offset = 0;
for(j=0; j<cache_size; j++)
{ RS01ReadSector(ii, eh, fc->imgBlock[i]+offset, block_idx[i]+j);
{ RS01ReadSector(image, fc->imgBlock[i]+offset, block_idx[i]+j);
offset += 2048;
}
read_crc(ei->file, fc->crcBuf[i], block_idx[i], cache_size);
read_crc(image->eccFile, fc->crcBuf[i], block_idx[i], cache_size);
}
cache_sector = cache_offset = 0;
}
@@ -380,14 +393,13 @@ void RS01Fix(Method *method)
/* Determine erasures based on the "dead sector" marker */
erasure_count = 0;
unexpected_failure = 0;
for(i=0; i<ndata; i++)
{ guint32 crc = Crc32(fc->imgBlock[i]+cache_offset, 2048);
erasure_map[i] = 0;
if(block_idx[i] < ei->sectors) /* ignore the padding sectors! */
if(block_idx[i] < image->expectedSectors) /* ignore the padding sectors! */
{ int err=CheckForMissingSector(fc->imgBlock[i]+cache_offset, block_idx[i], NULL, 0);
if(err != SECTOR_PRESENT)
@@ -440,16 +452,16 @@ void RS01Fix(Method *method)
{ gint64 idx = block_idx[erasure_list[i]];
unsigned char buf[2048];
if(idx < ii->sectors)
if(idx < image->sectorSize)
continue; /* It's (already) dead, Jim ;-) */
if(!LargeSeek(ii->file, (gint64)(2048*idx)))
if(!LargeSeek(image->file, (gint64)(2048*idx)))
Stop(_("Failed seeking to sector %lld in image [%s]: %s"),
idx, "FD", strerror(errno));
CreateMissingSector(buf, idx, eh->mediumFP, eh->fpSector, NULL);
n = LargeWrite(ii->file, buf, 2048);
n = LargeWrite(image->file, buf, 2048);
if(n != 2048)
Stop(_("Failed writing to sector %lld in image [%s]: %s"),
idx, "WD", strerror(errno));
@@ -469,10 +481,10 @@ void RS01Fix(Method *method)
/* Read the parity bytes */
if(!LargeSeek(ei->file, (gint64)(sizeof(EccHeader) + ei->sectors*sizeof(guint32) + nroots*parity_block)))
if(!LargeSeek(image->eccFile, (gint64)(sizeof(EccHeader) + image->expectedSectors*sizeof(guint32) + nroots*parity_block)))
Stop(_("Failed seeking in ecc area: %s"), strerror(errno));
n = LargeRead(ei->file, parity, nroots);
n = LargeRead(image->eccFile, parity, nroots);
if(n != nroots)
Stop(_("Can't read ecc file:\n%s"),strerror(errno));
parity_block++;
@@ -703,14 +715,14 @@ void RS01Fix(Method *method)
/* Write the recovered sector */
if(!LargeSeek(ii->file, (gint64)(2048*idx)))
if(!LargeSeek(image->file, (gint64)(2048*idx)))
Stop(_("Failed seeking to sector %lld in image [%s]: %s"),
idx, "FW", strerror(errno));
if(idx < ei->sectors-1) length = 2048;
if(idx < image->expectedSectors-1) length = 2048;
else length = eh->inLast;
n = LargeWrite(ii->file, cache_offset+fc->imgBlock[erasure_list[i]], length);
n = LargeWrite(image->file, cache_offset+fc->imgBlock[erasure_list[i]], length);
if(n != length)
Stop(_("could not write medium sector %lld:\n%s"),idx,strerror(errno));
}
@@ -735,7 +747,6 @@ skip:
RS01AddFixValues(wl, percent, local_plot_max);
local_plot_max = 0;
//if(last_corrected != corrected || last_uncorrected != uncorrected)
RS01UpdateFixResults(wl, corrected, uncorrected);
}
else PrintProgress(_("Ecc progress: %3d.%1d%%"),percent/10,percent%10);