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,22 +1,23 @@
/* 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.
*
* 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"
@@ -28,12 +29,12 @@
***/
typedef struct
{ Method *self;
{ Image *image;
Method *self;
RS02Widgets *wl;
RS02Layout *lay;
GaloisTables *gt;
ReedSolomonTables *rt;
ImageInfo *ii;
EccHeader *eh;
unsigned char *data;
unsigned char *parity;
@@ -50,10 +51,10 @@ static void ecc_cleanup(gpointer data)
{ ecc_closure *ec = (ecc_closure*)data;
int i;
Closure->cleanupProc = NULL;
UnregisterCleanup();
if(Closure->guiMode)
{ if(ec->earlyTermination)
{ if(ec->earlyTermination && ec->wl)
SetLabelText(GTK_LABEL(ec->wl->encFootline),
_("<span %s>Aborted by unrecoverable error.</span>"),
Closure->redMarkup);
@@ -68,9 +69,9 @@ static void ecc_cleanup(gpointer data)
/*** Clean up */
if(ec->image) CloseImage(ec->image);
if(ec->gt) FreeGaloisTables(ec->gt);
if(ec->rt) FreeReedSolomonTables(ec->rt);
if(ec->ii) FreeImageInfo(ec->ii);
if(ec->eh) g_free(ec->eh);
if(ec->lay) g_free(ec->lay);
if(ec->data) g_free(ec->data);
@@ -100,17 +101,19 @@ static void abort_encoding(ecc_closure *ec, int truncate)
{ RS02Widgets *wl = ec->wl;
if(truncate && ec->lay)
{ if(!LargeTruncate(ec->ii->file, (gint64)(2048*ec->lay->dataSectors)))
{ if(!LargeTruncate(ec->image->file, (gint64)(2048*ec->lay->dataSectors)))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
SetLabelText(GTK_LABEL(wl->encFootline),
_("<span %s>Aborted by user request!</span> (partial ecc data removed from image)"),
Closure->redMarkup);
if(Closure->stopActions == STOP_CURRENT_ACTION)
SetLabelText(GTK_LABEL(wl->encFootline),
_("<span %s>Aborted by user request!</span> (partial ecc data removed from image)"),
Closure->redMarkup);
}
else
{ SetLabelText(GTK_LABEL(wl->encFootline),
_("<span %s>Aborted by user request!</span>"),
Closure->redMarkup);
{ if(Closure->stopActions == STOP_CURRENT_ACTION)
SetLabelText(GTK_LABEL(wl->encFootline),
_("<span %s>Aborted by user request!</span>"),
Closure->redMarkup);
}
ec->earlyTermination = FALSE; /* suppress respective error message */
@@ -124,29 +127,34 @@ static void abort_encoding(ecc_closure *ec, int truncate)
*/
static void remove_old_ecc(ecc_closure *ec)
{ EccHeader *old_eh;
old_eh = FindHeaderInImage(Closure->imageName);
if(old_eh)
{ gint64 data_sectors = uchar_to_gint64(old_eh->sectors);
LargeFile *tmp;
{
if(ec->image->eccHeader)
{ gint64 data_sectors = uchar_to_gint64(ec->image->eccHeader->sectors);
guint64 data_bytes;
int answer;
g_free(old_eh);
answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL,
_("Image \"%s\" already contains error correction information.\n"
"Truncating image to data part (%lld sectors).\n"),
Closure->imageName, data_sectors);
if(Closure->confirmDeletion || !Closure->guiMode)
answer = ModalWarning(GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL, NULL,
_("Image \"%s\" already contains error correction information.\n"
"Truncating image to data part (%lld sectors).\n"),
Closure->imageName, data_sectors);
else answer = TRUE;
if(!answer)
abort_encoding(ec, FALSE);
tmp = LargeOpen(Closure->imageName, O_RDWR, IMG_PERMS);
if(!tmp || !LargeTruncate(tmp, (gint64)(2048*data_sectors)))
if(ec->image->eccHeader->inLast != 2048)
data_bytes = (guint64)(2048*(data_sectors-1)+ec->image->eccHeader->inLast);
else data_bytes = (guint64)(2048*data_sectors);
if(!TruncateImage(ec->image, data_bytes))
Stop(_("Could not truncate %s: %s\n"),Closure->imageName,strerror(errno));
LargeClose(tmp);
PrintLog(_("Image size is now"));
if(ec->image->inLast == 2048)
PrintLog(_(": %lld medium sectors.\n"), ec->image->sectorSize);
else PrintLog(_(": %lld medium sectors and %d bytes.\n"),
ec->image->sectorSize-1, ec->image->inLast);
}
}
@@ -158,7 +166,7 @@ static void remove_old_ecc(ecc_closure *ec)
static void check_image(ecc_closure *ec)
{ struct MD5Context image_md5;
RS02Layout *lay = ec->lay;
ImageInfo *ii = ec->ii;
Image *image = ec->image;
gint64 sectors;
guint32 *crcptr;
int last_percent, percent;
@@ -166,8 +174,8 @@ static void check_image(ecc_closure *ec)
/* Discard old CRC cache no matter what it contains.
* We will create a new one a few lines below.
* Note that it is very unusual to augment an image with ecc data
* which was just from an actual medium, so optimizing for the cached
* CRCs is not necessary.
* which was just read from an actual medium, so optimizing
* for the cached CRCs is not necessary.
*/
if(Closure->crcCache)
@@ -178,7 +186,7 @@ static void check_image(ecc_closure *ec)
Closure->crcCache = crcptr = g_malloc(sizeof(guint32) * lay->dataSectors);
if(!LargeSeek(ii->file, 0))
if(!LargeSeek(image->file, 0))
Stop(_("Failed seeking to start of image: %s\n"), strerror(errno));
for(sectors = 0; sectors < lay->dataSectors; sectors++)
@@ -188,19 +196,19 @@ static void check_image(ecc_closure *ec)
if(Closure->stopActions) /* User hit the Stop button */
abort_encoding(ec, FALSE);
if(sectors < ii->sectors-1) expected = 2048;
if(sectors < image->sectorSize-1) expected = 2048;
else
{ memset(buf, 0, 2048);
expected = ii->inLast;
expected = image->inLast;
}
n = LargeRead(ii->file, buf, expected);
n = LargeRead(image->file, buf, expected);
if(n != expected)
Stop(_("Failed reading sector %lld in image: %s"),sectors,strerror(errno));
/* Look for the dead sector marker */
err = CheckForMissingSector(buf, sectors, ii->fpValid ? ii->mediumFP : NULL, FINGERPRINT_SECTOR);
err = CheckForMissingSector(buf, sectors, image->fpState == FP_PRESENT ? image->imageFP : NULL, FINGERPRINT_SECTOR);
if(err != SECTOR_PRESENT)
{ if(err == SECTOR_MISSING)
Stop(_("Image contains unread(able) sectors.\n"
@@ -234,7 +242,7 @@ static void check_image(ecc_closure *ec)
}
}
MD5Final(ii->mediumSum, &image_md5);
MD5Final(image->mediumSum, &image_md5);
}
@@ -245,31 +253,31 @@ static void check_image(ecc_closure *ec)
static void expand_image(ecc_closure *ec)
{ RS02Layout *lay = ec->lay;
ImageInfo *ii = ec->ii;
Image *image = ec->image;
int last_percent, percent;
gint64 sectors;
/* If the file does not end at a sector boundary,
fill it up with zeros. */
if(ii->inLast != 2048)
{ int fill = 2048 - ii->inLast;
if(image->inLast != 2048)
{ int fill = 2048 - image->inLast;
int n;
unsigned char zeros[fill];
memset(zeros, 0, fill);
if(!LargeSeek(ii->file, ii->size))
if(!LargeSeek(image->file, image->file->size))
Stop(_("Failed seeking to end of image: %s\n"), strerror(errno));
n = LargeWrite(ii->file, zeros, fill);
n = LargeWrite(image->file, zeros, fill);
if(n != fill)
Stop(_("Failed expanding the image: %s\n"), strerror(errno));
}
/* Now add the sectors needed for the ecc data */
if(!LargeSeek(ii->file, 2048*lay->dataSectors))
if(!LargeSeek(image->file, 2048*lay->dataSectors))
Stop(_("Failed seeking to end of image: %s\n"), strerror(errno));
last_percent = 0;
@@ -281,9 +289,9 @@ static void expand_image(ecc_closure *ec)
abort_encoding(ec, TRUE);
CreateMissingSector(buf, lay->dataSectors+sectors,
ii->mediumFP, FINGERPRINT_SECTOR,
image->imageFP, FINGERPRINT_SECTOR,
"RS02 generation placeholder");
n = LargeWrite(ii->file, buf, 2048);
n = LargeWrite(image->file, buf, 2048);
if(n != 2048)
Stop(_("Failed expanding the image: %s\n"), strerror(errno));
@@ -311,7 +319,7 @@ static void expand_image(ecc_closure *ec)
static void write_crc(ecc_closure *ec)
{ RS02Layout *lay = ec->lay;
ImageInfo *ii = ec->ii;
Image *image = ec->image;
EccHeader *eh = ec->eh;
gint64 crc_sector;
gint64 layer_sector;
@@ -332,7 +340,7 @@ static void write_crc(ecc_closure *ec)
/*** Calculate the CRCs */
if(!LargeSeek(ii->file, 2048*crc_sector))
if(!LargeSeek(image->file, 2048*crc_sector))
Stop(_("Failed seeking to sector %lld in image: %s"), crc_sector, strerror(errno));
for(layer_sector=0; layer_sector<lay->sectorsPerLayer; layer_sector++)
@@ -353,7 +361,7 @@ static void write_crc(ecc_closure *ec)
*crc_boot_ptr++ = Closure->crcCache[layer_index];
if(crc_idx >= 512)
{ int n = LargeWrite(ii->file, crc_buf, 2048);
{ int n = LargeWrite(image->file, crc_buf, 2048);
if(n != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), crc_sector, strerror(errno));
@@ -379,7 +387,7 @@ static void write_crc(ecc_closure *ec)
#else
crc_buf[n] = 0x4c5047;
#endif
n = LargeWrite(ii->file, crc_buf, 2048);
n = LargeWrite(image->file, crc_buf, 2048);
if(n != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), crc_sector, strerror(errno));
@@ -399,25 +407,25 @@ static void write_crc(ecc_closure *ec)
*/
static void prepare_header(ecc_closure *ec)
{ ImageInfo *ii = ec->ii;
{ Image *image = ec->image;
EccHeader *eh = ec->eh;
RS02Layout *lay = ec->lay;
memcpy(eh->cookie, "*dvdisaster*", 12);
memcpy(eh->method, "RS02", 4);
eh->methodFlags[0] = 0;
eh->methodFlags[3] = Closure->releaseFlags;
memcpy(eh->mediumFP, ii->mediumFP, 16);
memcpy(eh->mediumSum, ii->mediumSum, 16);
memcpy(eh->mediumFP, image->imageFP, 16);
memcpy(eh->mediumSum, image->mediumSum, 16);
memcpy(eh->eccSum, ec->eccSum, 16);
gint64_to_uchar(eh->sectors, ii->sectors);
gint64_to_uchar(eh->sectors, image->sectorSize);
eh->dataBytes = lay->ndata;
eh->eccBytes = lay->nroots;
eh->creatorVersion = Closure->version;
eh->neededVersion = 6600;
eh->fpSector = FINGERPRINT_SECTOR;
eh->inLast = ii->inLast;
eh->inLast = image->inLast;
eh->sectorsAddedByEcc = lay->eccSectors;
eh->selfCRC = 0x4c5047;
@@ -435,7 +443,7 @@ static void prepare_header(ecc_closure *ec)
static void create_reed_solomon(ecc_closure *ec)
{ RS02Layout *lay = ec->lay;
LargeFile *file = ec->ii->file;
Image *image = ec->image;
int nroots = lay->nroots;
int ndata = lay->ndata;
gint64 b_idx, block_idx[256];
@@ -459,7 +467,7 @@ static gint32 *enc_alpha_to;
/*** Adjust image bounds to include the CRC sectors */
ec->ii->sectors = lay->protectedSectors;
image->sectorSize = lay->protectedSectors;
/*** Create table for Galois field math */
@@ -473,9 +481,9 @@ static gint32 *enc_alpha_to;
/*** Allocate buffers for the parity calculation and image data caching.
The algorithm builds the parity file consecutively in chunks of n_parity_blocks.
We use all the amount of memory allowed by cacheMB for caching the parity blocks. */
We use all the amount of memory allowed by cacheMiB for caching the parity blocks. */
n_parity_blocks = ((guint64)Closure->cacheMB<<20) / (guint64)nroots; /* 1 MB = 2^20 */
n_parity_blocks = ((guint64)Closure->cacheMiB<<20) / (guint64)nroots; /* 1 MiB = 2^20 */
n_parity_blocks >>= 1; /* two buffer sets for scrambling */
n_parity_blocks &= ~0x7ff; /* round down to multiple of 2048 */
n_parity_bytes = (guint64)nroots * n_parity_blocks;
@@ -504,11 +512,11 @@ static gint32 *enc_alpha_to;
}
if(out_of_memory || !ec->parity || !ec->data)
{ LargeTruncate(ec->ii->file, (gint64)(2048*ec->lay->dataSectors));
{ LargeTruncate(image->file, (gint64)(2048*ec->lay->dataSectors));
Stop(_("Failed allocating memory for I/O cache.\n"
"Cache size is currently %d MB.\n"
"Cache size is currently %d MiB.\n"
"Try reducing it.\n"),
Closure->cacheMB);
Closure->cacheMiB);
}
/*** Setup the block counters for mapping medium sectors to ecc blocks
@@ -568,7 +576,7 @@ static gint32 *enc_alpha_to;
/* Read the next data sectors of this layer. */
for(si=0; si<actual_layer_sectors; si++)
{ RS02ReadSector(ec->ii, lay, ec->data+offset, block_idx[layer]);
{ RS02ReadSector(image, lay, ec->data+offset, block_idx[layer]);
block_idx[layer]++;
offset += 2048;
}
@@ -978,10 +986,10 @@ static gint32 *enc_alpha_to;
for(si=0; si<actual_layer_sectors; si++, idx+=2048)
{ gint64 s = RS02EccSectorIndex(lay, k, chunk + si);
if(!LargeSeek(file, 2048*s))
if(!LargeSeek(image->file, 2048*s))
Stop(_("Failed seeking to sector %lld in image: %s"), s, strerror(errno));
if(LargeWrite(file, ec->slice[k]+idx, 2048) != 2048)
if(LargeWrite(image->file, ec->slice[k]+idx, 2048) != 2048)
Stop(_("Failed writing to sector %lld in image: %s"), s, strerror(errno));
MD5Update(&ec->md5Ctxt[k], ec->slice[k]+idx, 2048);
@@ -1001,29 +1009,47 @@ static gint32 *enc_alpha_to;
/*** Restore image bounds to data portion */
ec->ii->sectors = lay->dataSectors;
image->sectorSize = lay->dataSectors;
}
/***
*** Append the parity information to the image
***/
void RS02Create(Method *method)
{ RS02Widgets *wl = (RS02Widgets*)method->widgetList;
void RS02Create(void)
{ Method *self = FindMethod("RS02");
RS02Widgets *wl = (RS02Widgets*)self->widgetList;
Image *image = NULL;
RS02Layout *lay;
ecc_closure *ec = g_malloc0(sizeof(ecc_closure));
ImageInfo *ii;
ec->earlyTermination = TRUE;
RegisterCleanup(_("Error correction data creation aborted"), ecc_cleanup, ec);
/*** Open image file */
PrintLog(_("\nOpening %s"), Closure->imageName);
image = OpenImageFromFile(Closure->imageName, O_RDWR, IMG_PERMS);
if(!image)
{ PrintLog(": %s.\n", strerror(errno));
Stop(_("Image file %s: %s."),Closure->imageName, strerror(errno));
return;
}
if(image->inLast == 2048)
PrintLog(_(": %lld medium sectors.\n"), image->sectorSize);
else PrintLog(_(": %lld medium sectors and %d bytes.\n"),
image->sectorSize-1, image->inLast);
/*** Register the cleanup procedure for GUI mode */
ec->self = method;
ec->image = image;
ec->self = self;
ec->wl = wl;
ec->eh = g_malloc0(sizeof(EccHeader));
ec->earlyTermination = TRUE;
ec->timer = g_timer_new();
RegisterCleanup(_("Error correction data creation aborted"), ecc_cleanup, ec);
if(Closure->guiMode) /* Preliminary fill text for the head line */
SetLabelText(GTK_LABEL(wl->encHeadline),
_("<big>Augmenting the image with error correction data.</big>\n<i>%s</i>"),
@@ -1033,16 +1059,14 @@ void RS02Create(Method *method)
remove_old_ecc(ec);
/*** Open image file and calculate a suitable redundancy .*/
/*** Calculate a suitable redundancy .*/
ii = ec->ii = OpenImageFile(NULL, WRITEABLE_IMAGE);
lay = ec->lay = CalcRS02Layout(ii->sectors, 0);
lay = ec->lay = CalcRS02Layout(image);
/*** Announce what we are going to do */
if(Closure->guiMode) /* Preliminary fill text for the head line */
{ ec->msg = g_strdup_printf(_("Encoding with Method RS02: %lld MB data, %lld MB ecc (%d roots; %4.1f%% redundancy)."),
{ ec->msg = g_strdup_printf(_("Encoding with Method RS02: %lld MiB data, %lld MiB ecc (%d roots; %4.1f%% redundancy)."),
lay->dataSectors/512, lay->eccSectors/512, lay->nroots, lay->redundancy);
SetLabelText(GTK_LABEL(wl->encHeadline),
@@ -1050,7 +1074,7 @@ void RS02Create(Method *method)
ec->msg);
}
else
{ ec->msg = g_strdup_printf(_("Augmenting image with Method RS02:\n %lld MB data, %lld MB ecc (%d roots; %4.1f%% redundancy)."),
{ ec->msg = g_strdup_printf(_("Augmenting image with Method RS02:\n %lld MiB data, %lld MiB ecc (%d roots; %4.1f%% redundancy)."),
lay->dataSectors/512, lay->eccSectors/512, lay->nroots, lay->redundancy);
PrintLog("%s\n",ec->msg);
@@ -1062,8 +1086,7 @@ void RS02Create(Method *method)
Stop(_("Not enough space on medium left for error correction data.\n"
"Data portion of image: %lld sect.; maximum possible size: %lld sect.\n"
"If reducing the image size or using a larger medium is\n"
"not an option, please create a separate error correction\n"
"file using the RS01 method.\n"),
"not an option, please create a separate error correction file."),
lay->dataSectors, lay->mediumCapacity);
if(lay->redundancy < 20)
@@ -1097,13 +1120,13 @@ void RS02Create(Method *method)
and write all copies of the header out */
prepare_header(ec);
WriteRS02Headers(ec->ii->file, ec->lay, ec->eh);
WriteRS02Headers(image->file, ec->lay, ec->eh);
PrintTimeToLog(ec->timer, "for ECC generation.\n");
PrintProgress(_("Ecc generation: 100.0%%\n"));
PrintLog(_("Image has been augmented with error correction data.\n"
"New image size is %lld MB (%lld sectors).\n"),
"New image size is %lld MiB (%lld sectors).\n"),
(lay->dataSectors + lay->eccSectors)/512,
lay->dataSectors+lay->eccSectors);
@@ -1112,7 +1135,7 @@ void RS02Create(Method *method)
SetLabelText(GTK_LABEL(wl->encFootline),
_("Image has been augmented with error correction data.\n"
"New image size is %lld MB (%lld sectors).\n"),
"New image size is %lld MiB (%lld sectors).\n"),
(lay->dataSectors + lay->eccSectors)/512,
lay->dataSectors+lay->eccSectors);
}