1 /* dvdisaster: Additional error correction for optical media. 2 * Copyright (C) 2004-2015 Carsten Gnoerlich. 3 * 4 * The Reed-Solomon error correction draws a lot of inspiration - and even code - 5 * from Phil Karn's excellent Reed-Solomon library: http://www.ka9q.net/code/fec/ 6 * 7 * Email: carsten@dvdisaster.org -or- cgnoerlich@fsfe.org 8 * Project homepage: http://www.dvdisaster.org 9 * 10 * This file is part of dvdisaster. 11 * 12 * dvdisaster is free software: you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation, either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * dvdisaster is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with dvdisaster. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 #include "dvdisaster.h" 27 28 #include "rs01-includes.h" 29 30 /*** 31 *** Interpret our redundancy settings 32 *** 33 * a) "normal" -> nroots=32; "high" -> nroots=64 34 * b) "n" -> nroots = n 35 * c) "n%" -> use closest nroots for given redundancy in percent 36 * d) "nm" -> choose redundancy so that .ecc file does not exceed n megabytes 37 */ 38 39 static guint64 ecc_file_size(guint64 sectors, int nr) 40 { int nd = GF_FIELDMAX - nr; 41 guint64 bytesize; encode_next_layer_portable(ReedSolomonTables * rt,unsigned char * data,unsigned char * parity,guint64 layer_size,int shift)42 43 bytesize = 4096 + 4*sectors + 2048*nr*((sectors+nd-1)/nd); 44 45 return (bytesize+0xfffff)/0x100000; /* size in MiB */ 46 } 47 48 static int calculate_redundancy(char *image_name) 49 { int nr = 0; 50 char last = 0; 51 double p; 52 int ignore; 53 guint64 fs,sectors,filesize; 54 55 if(Closure->redundancy) /* get last char of redundancy parameter */ 56 { int len = strlen(Closure->redundancy); 57 58 if(len) last = Closure->redundancy[len-1]; 59 } 60 61 switch(last) 62 { case '%' : p = atof(Closure->redundancy); 63 if(p<3.2 || p>64.5) Stop(_("Redundancy %4.1f%% out of useful range [3.2%%..64.5%%]"),p); 64 nr = (int)round((GF_FIELDMAX*p) / (100.0+p)); 65 break; 66 67 case 'm' : if(!LargeStat(image_name, &filesize)) 68 { nr = 32; /* If the image file is not present, simply return 32. */ 69 break; /* Later stages will fail anyways, but can report the error */ 70 } /* in a more meaningful context. */ 71 72 CalcSectors(filesize, §ors, &ignore); 73 74 fs = strtoll(Closure->redundancy, NULL, 10); 75 if(fs < ecc_file_size(sectors, 8) || fs > ecc_file_size(sectors, 100)) 76 Stop(_("Ecc file size %lldm out of useful range [%lld .. %lld]"), 77 fs, ecc_file_size(sectors, 8), ecc_file_size(sectors, 100)); 78 for(nr=100; nr>8; nr--) 79 if(fs >= ecc_file_size(sectors, nr)) 80 break; 81 break; 82 83 default: 84 if(!Closure->redundancy || !strcmp(Closure->redundancy, "normal")) nr = 32; 85 else if(!strcmp(Closure->redundancy, "high")) nr = 64; 86 else nr = atoi(Closure->redundancy); 87 break; 88 } 89 90 if(nr < 8 || nr > 100) 91 Stop(_("Redundancy %d out of useful range [8..100]."),nr); 92 93 return nr; 94 } 95 96 /*** 97 *** Remove the image file 98 ***/ 99 100 static void unlink_image(GtkWidget *label) 101 { 102 if(LargeUnlink(Closure->imageName)) 103 { PrintLog(_("\nImage file %s deleted.\n"),Closure->imageName); 104 105 if(Closure->guiMode) 106 SetLabelText(GTK_LABEL(label), 107 _("\nImage file %s deleted.\n"), Closure->imageName); 108 } 109 else 110 { if(!Closure->guiMode) 111 PrintLog("\n"); 112 113 ModalWarning(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, NULL, encode_next_layer_64bit(ReedSolomonTables * rt,unsigned char * data,unsigned char * parity,guint64 layer_size,int shift)114 _("Image file %s not deleted: %s\n"), 115 Closure->imageName, strerror(errno)); 116 } 117 } 118 119 /*** 120 *** Create parity information for the medium sectors. 121 ***/ 122 123 /* 124 * Local data package used during encoding 125 */ 126 127 typedef struct 128 { Method *self; 129 RS01Widgets *wl; 130 GaloisTables *gt; 131 ReedSolomonTables *rt; 132 Image *image; 133 int earlyTermination; 134 unsigned char *data; 135 unsigned char *parity; 136 char *msg; 137 GTimer *timer; 138 } ecc_closure; 139 140 static void ecc_cleanup(gpointer data) 141 { ecc_closure *ec = (ecc_closure*)data; 142 143 UnregisterCleanup(); 144 145 if(Closure->guiMode) 146 { if(ec->earlyTermination) 147 SetLabelText(GTK_LABEL(ec->wl->encFootline), 148 _("<span %s>Aborted by unrecoverable error.</span>"), 149 Closure->redMarkup); 150 AllowActions(TRUE); 151 } 152 153 /** Clean up */ 154 155 if(ec->gt) FreeGaloisTables(ec->gt); 156 if(ec->rt) FreeReedSolomonTables(ec->rt); 157 if(ec->data) g_free(ec->data); 158 if(ec->parity) g_free(ec->parity); 159 160 if(ec->image) CloseImage(ec->image); 161 if(ec->msg) g_free(ec->msg); 162 if(ec->timer) g_timer_destroy(ec->timer); 163 164 if(Closure->enableCurveSwitch) 165 { Closure->enableCurveSwitch = FALSE; 166 RS01ShowCurveButton(ec->self); 167 } 168 169 g_free(ec); 170 171 if(Closure->guiMode) 172 g_thread_exit(0); 173 } 174 175 /* 176 * Create the parity file. 177 */ 178 179 enum { NORMAL, HIGH, GENERIC }; 180 181 void RS01Create(void) 182 { Method *self = FindMethod("RS01"); 183 RS01Widgets *wl = (RS01Widgets*)self->widgetList; 184 GaloisTables *gt; 185 ReedSolomonTables *rt; 186 ecc_closure *ec = g_malloc0(sizeof(ecc_closure)); 187 struct MD5Context md5Ctxt; 188 EccHeader *eh; 189 Image *image; 190 guint64 block_idx[256]; /* must be >= ndata */ 191 guint64 s,si,n; 192 int i; 193 int percent = 0,max_percent,progress = 0, last_percent = -1; 194 guint64 n_parity_blocks,n_layer_sectors; 195 guint64 n_parity_bytes,n_layer_bytes; 196 guint64 chunk; 197 int layer; 198 int loop_type = GENERIC; 199 gint32 nroots; /* These are copied to increase performance. */ 200 gint32 ndata; 201 gint32 *gf_index_of; 202 gint32 *enc_alpha_to; 203 gint32 *rs_gpoly; 204 205 /*** Register the cleanup procedure for GUI mode */ 206 207 ec->self = self; 208 ec->wl = wl; 209 ec->earlyTermination = TRUE; 210 RegisterCleanup(_("Error correction file creation aborted"), ecc_cleanup, ec); 211 212 /*** Set up the Galois field arithmetic */ 213 214 /* Calculate number of roots (= max. number of erasures) 215 and number of data bytes from redundancy setting */ 216 217 if(!Closure->redundancy || !strcmp(Closure->redundancy, "normal")) 218 loop_type = NORMAL; 219 else if(!strcmp(Closure->redundancy, "high")) loop_type = HIGH; 220 221 i = calculate_redundancy(Closure->imageName); 222 gt = ec->gt = CreateGaloisTables(RS_GENERATOR_POLY); 223 rt = ec->rt = CreateReedSolomonTables(gt, RS_FIRST_ROOT, RS_PRIM_ELEM, i); 224 225 nroots = rt->nroots; 226 ndata = rt->ndata; 227 rs_gpoly = rt->gpoly; EncodeNextLayer(ReedSolomonTables * rt,unsigned char * data,unsigned char * parity,guint64 layer_size,int shift)228 enc_alpha_to = gt->encAlphaTo; 229 gf_index_of = gt->indexOf; 230 231 /*** Announce what we are going to do */ 232 233 ec->msg = g_strdup_printf(_("Encoding with Method RS01: %d roots, %4.1f%% redundancy."), 234 nroots, 235 ((double)nroots*100.0)/(double)ndata); 236 237 if(Closure->guiMode) 238 SetLabelText(GTK_LABEL(wl->encHeadline), 239 _("<big>Creating the error correction file.</big>\n<i>%s</i>"), ec->msg); 240 241 /*** Test the image file and create the CRC sums */ 242 243 /* Get rid of old ecc file (if any exists) */ 244 245 if(LargeStat(Closure->eccName, &n)) 246 { 247 if(ConfirmEccDeletion(Closure->eccName)) 248 LargeUnlink(Closure->eccName); 249 else 250 { SetLabelText(GTK_LABEL(ec->wl->encFootline), 251 _("<span %s>Aborted to keep existing ecc file.</span>"), 252 Closure->redMarkup); 253 ec->earlyTermination = FALSE; 254 goto terminate; 255 } 256 } 257 DescribeRSEncoder(char ** algorithm,char ** iostrategy)258 /* Open image and ecc files */ 259 260 PrintLog(_("\nOpening %s"), Closure->imageName); 261 262 image = OpenImageFromFile(Closure->imageName, O_RDONLY, IMG_PERMS); 263 ec->image = image; 264 if(!image) 265 { PrintLog(": %s.\n", strerror(errno)); 266 Stop(_("Image file %s: %s."),Closure->imageName, strerror(errno)); 267 } 268 if(image->inLast == 2048) 269 PrintLog(_(": %lld medium sectors.\n"), image->sectorSize); 270 else PrintLog(_(": %lld medium sectors and %d bytes.\n"), 271 image->sectorSize-1, image->inLast); 272 273 if(!Closure->eccName || !strlen(Closure->eccName)) 274 Stop(_("No error correction file specified!\n")); 275 276 image->eccFile = LargeOpen(Closure->eccName, O_RDWR | O_CREAT, IMG_PERMS); 277 if(!image->eccFile) 278 Stop(_("Can't open %s:\n%s"),Closure->eccName,strerror(errno)); 279 280 ec->timer = g_timer_new(); 281 282 if(Closure->crcCache) /* use CRC values created during last read */ 283 { guint32 crc_idx; 284 int percent, last_percent = 0; 285 char *msg = _("Writing sector checksums: %3d%%"); 286 287 if(Closure->guiMode) 288 SetLabelText(GTK_LABEL(wl->encLabel1), 289 _("<b>1. Writing image sector checksums:</b>")); 290 291 memcpy(image->mediumSum, Closure->md5Cache, 16); 292 MD5Init(&md5Ctxt); /* md5sum of CRC portion of ecc file */ 293 294 /* Write out the cached CRC sectors */ 295 296 if(!LargeSeek(image->eccFile, (gint64)sizeof(EccHeader))) 297 Stop(_("Failed skipping the ecc header: %s"),strerror(errno)); 298 299 for(crc_idx=0; crc_idx<image->sectorSize; crc_idx+=1024) 300 { int ci,n,size; 301 guint32 *crcbuf; 302 303 if(crc_idx + 1024 > image->sectorSize) 304 ci = image->sectorSize - crc_idx; 305 else ci = 1024; 306 307 size = ci*sizeof(guint32); 308 crcbuf = &Closure->crcCache[crc_idx]; 309 310 n = LargeWrite(image->eccFile, crcbuf, size); 311 MD5Update(&md5Ctxt, (unsigned char*)crcbuf, size); 312 313 if(size != n) 314 Stop(_("Error writing CRC information: %s"), strerror(errno)); 315 316 percent = (100*crc_idx)/image->sectorSize; 317 if(last_percent != percent) 318 { PrintProgress(msg,percent); 319 320 if(Closure->guiMode) 321 SetProgress(wl->encPBar1, percent, 100); 322 323 last_percent = percent; 324 } 325 } 326 327 PrintProgress(msg, 100); 328 } 329 else /* Scan image for missing sectors and calculate the checksums */ 330 { if(Closure->guiMode) 331 SetLabelText(GTK_LABEL(wl->encLabel1), 332 _("<b>1. Calculating image sector checksums:</b>")); 333 334 RS01ScanImage(self, image, &md5Ctxt, CREATE_CRC); 335 336 if(image->sectorsMissing) 337 { LargeClose(image->eccFile); /* Will be deleted anyways; no need to test for errors */ 338 image->eccFile = NULL; 339 340 LargeUnlink(Closure->eccName); /* Do not leave a CRC-only .ecc file behind */ 341 342 if(Closure->stopActions) 343 { 344 if(Closure->stopActions == STOP_CURRENT_ACTION) /* suppress memleak warning when closing window */ 345 SetLabelText(GTK_LABEL(wl->encFootline), 346 _("<span %s>Aborted by user request!</span> (partial error correction file removed)"), 347 Closure->redMarkup); 348 ec->earlyTermination = FALSE; /* suppress respective error message */ 349 goto terminate; 350 } 351 else 352 { if(Closure->guiMode) 353 SetProgress(wl->encPBar1, 100, 100); 354 355 Stop(_("%lld sectors unread or missing due to errors.\n"), image->sectorsMissing); 356 } 357 } 358 } 359 360 PrintTimeToLog(ec->timer, "for CRC writing/generation.\n"); 361 362 if(Closure->guiMode) 363 { SetProgress(wl->encPBar1, 100, 100); 364 ShowWidget(wl->encPBar2); 365 ShowWidget(wl->encLabel2); 366 } 367 368 if(!Closure->guiMode) 369 PrintLog("%s\n",ec->msg); 370 371 /*** Prepare Ecc file header. 372 The .eccSum will be filled in after all ecc blocks have been created. */ 373 374 image->eccFileHeader = eh = g_malloc0(sizeof(EccHeader)); 375 memcpy(eh->cookie, "*dvdisaster*", 12); 376 memcpy(eh->method, "RS01", 4); 377 eh->methodFlags[0] = 1; 378 gint64_to_uchar(eh->sectors, image->sectorSize); 379 eh->dataBytes = ndata; 380 eh->eccBytes = nroots; 381 382 eh->creatorVersion = Closure->version; 383 eh->fpSector = FINGERPRINT_SECTOR; 384 eh->inLast = image->inLast; 385 386 /* dvdisaster 0.66 brings some extensions which are not compatible with 387 prior versions. These are: 388 - If the methodFlags contains any other bits set than methodFlags[0] == 1, 389 prior versions will incorrectly reject ecc files as being produced by 390 version 0.40.7 due to a bug in the version processing code. 391 So ecc files tagged with -devel or -rc status will not work with prior 392 versions. But they are experimental versions available only through CVS, 393 so this issue is not as big as it appears. 394 - Version 0.66 records the inLast value in the ecc file to facilitate 395 processing non-image files. Previous versions do not use this field 396 and may round up file length to the next multiple of 2048 when doing 397 error correction. 398 */ 399 400 if(image->inLast != 2048) 401 eh->neededVersion = 6600; 402 else eh->neededVersion = 5500; 403 404 memcpy(eh->mediumFP, image->imageFP, 16); 405 memcpy(eh->mediumSum, image->mediumSum, 16); 406 407 if(!LargeSeek(image->eccFile, (gint64)sizeof(EccHeader) + image->sectorSize*sizeof(guint32))) 408 Stop(_("Failed skipping ecc+crc header: %s"),strerror(errno)); 409 410 /*** Allocate buffers for the parity calculation and image data caching. 411 412 The algorithm builds the parity file consecutively in chunks of n_parity_blocks. 413 We use all the amount of memory allowed by cacheMiB for caching the parity blocks. */ 414 415 n_parity_blocks = ((guint64)Closure->cacheMiB<<20) / (guint64)nroots; 416 n_parity_blocks &= ~0x7ff; /* round down to multiple of 2048 */ 417 n_parity_bytes = (guint64)nroots * n_parity_blocks; 418 419 /* Each chunk of parity blocks is built iteratively by processing the data in layers 420 (first all bytes at pos 0, then pos 1, until ndata layers have been processed). 421 So one buffer of n_layer_bytes = n_parity_blocks needs to be buffered. 422 For practical reasons we require that the layer size is a multiple of the 423 medium sector size of 2048 bytes. */ 424 425 n_layer_bytes = n_parity_blocks; 426 n_layer_sectors = n_parity_blocks/2048; 427 428 if(n_layer_sectors*2048 != n_parity_blocks) 429 Stop("Internal error: parity blocks are not a multiple of sector size.\n"); 430 431 ec->parity = g_try_malloc(n_parity_bytes); 432 ec->data = g_try_malloc(n_layer_bytes); 433 434 if(!ec->parity || !ec->data) 435 Stop(_("Failed allocating memory for I/O cache.\n" 436 "Cache size is currently %d MiB.\n" 437 "Try reducing it.\n"), 438 Closure->cacheMiB); 439 440 /*** Setup the block counters for mapping medium sectors to ecc blocks 441 The image is divided into ndata sections; 442 with each section spanning s sectors. */ 443 444 s = (image->sectorSize+ndata-1)/ndata; 445 446 for(si=0, i=0; i<ndata; si+=s, i++) 447 block_idx[i] = si; 448 449 /*** Create ecc information for the medium image. */ 450 451 max_percent = ndata * ((s / n_layer_sectors) + 1); 452 g_timer_start(ec->timer); 453 454 /* Process the image. 455 From each section a chunk of n_layer_sectors is read in at once. 456 So after (s/n_layer_sectors)+1 iterations the whole image has been processed. */ 457 458 for(chunk=0; chunk<s; chunk+=n_layer_sectors) 459 { guint64 actual_layer_bytes,actual_layer_sectors; 460 461 /* Prepare the parity data for the next chunk. */ 462 463 memset(ec->parity, 0, n_parity_bytes); 464 465 /* The last chunk may contain fewer sectors. */ 466 467 if(chunk+n_layer_sectors < s) 468 actual_layer_sectors = n_layer_sectors; 469 else actual_layer_sectors = s-chunk; 470 471 actual_layer_bytes = 2048*actual_layer_sectors; 472 473 /* Work each of the ndata data layers 474 into the parity data of the current chunk. */ 475 476 switch(loop_type) 477 { case NORMAL: /* Inner loop unrolled for nroots = 32. */ 478 {int sp=1; /* sp==1 makes sure sp==0 after ndata bytes [since (223+1) mod 32 = 0]*/ 479 480 for(layer=0; layer<ndata; layer++) 481 { int offset = 0; 482 unsigned char *par_idx = ec->parity; 483 484 if(Closure->stopActions) /* User hit the Stop button */ 485 { if(Closure->stopActions == STOP_CURRENT_ACTION) /* suppress memleak warning when closing window */ 486 SetLabelText(GTK_LABEL(wl->encFootline), 487 _("<span %s>Aborted by user request!</span> (partial error correction file removed)"), 488 Closure->redMarkup); 489 ec->earlyTermination = FALSE; /* suppress respective error message */ 490 LargeClose(image->eccFile); 491 image->eccFile = NULL; 492 LargeUnlink(Closure->eccName); /* Do not leave partial .ecc file behind */ 493 goto terminate; 494 } 495 496 /* Read the next data sectors of this layer. */ 497 498 for(si=0; si<actual_layer_sectors; si++) 499 { RS01ReadSector(image, ec->data+offset, block_idx[layer]); 500 block_idx[layer]++; 501 offset += 2048; 502 } 503 504 /* Now process the data bytes of the current layer. */ 505 506 for(si=0; si<actual_layer_bytes; si++) 507 { register int feedback; 508 509 feedback = gf_index_of[ec->data[si] ^ par_idx[sp]]; 510 511 if(feedback != GF_ALPHA0) /* non-zero feedback term */ 512 { register int spk = sp; 513 514 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 249]; 515 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 59]; 516 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 66]; 517 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 4]; 518 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 43]; 519 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 126]; 520 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 251]; 521 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 97]; 522 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 30]; 523 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 3]; 524 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 213]; 525 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 50]; 526 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 66]; 527 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 170]; 528 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 5]; 529 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 24]; 530 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 5]; 531 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 170]; 532 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 66]; 533 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 50]; 534 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 213]; 535 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 3]; 536 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 30]; 537 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 97]; 538 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 251]; 539 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 126]; 540 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 43]; 541 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 4]; 542 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 66]; 543 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 59]; 544 par_idx[((++spk)&31)] ^= enc_alpha_to[feedback + 249]; 545 546 par_idx[sp] = enc_alpha_to[feedback]; /* feedback + 0 */ 547 } 548 else /* zero feedback term */ 549 par_idx[sp] = 0; 550 551 par_idx += nroots; 552 } 553 554 sp = (sp+1) & 31; /* shift */ 555 556 /* Report progress */ 557 558 progress++; 559 percent = (1000*progress)/max_percent; 560 if(last_percent != percent) 561 { if(Closure->guiMode) 562 SetProgress(wl->encPBar2, percent, 1000); 563 else 564 PrintProgress(_("Ecc generation: %3d.%1d%%"), percent/10, percent%10); 565 last_percent = percent; 566 } 567 } 568 } 569 break; 570 571 case HIGH: /* Inner loop is unrolled for nroots = 64. */ 572 {int sp=1; /* sp==1 makes sure sp==0 after ndata bytes [since (191+1) mod 64 = 0] */ 573 for(layer=0; layer<ndata; layer++) 574 { int offset = 0; 575 unsigned char *par_idx = ec->parity; 576 577 if(Closure->stopActions) /* User hit the Stop button */ 578 { if(Closure->stopActions == STOP_CURRENT_ACTION) /* suppress memleak warning when closing window */ 579 SetLabelText(GTK_LABEL(wl->encFootline), 580 _("<span %s>Aborted by user request!</span> (partial error correction file removed)"), 581 Closure->redMarkup); 582 ec->earlyTermination = FALSE; /* suppress respective error message */ 583 LargeClose(image->eccFile); 584 image->eccFile = NULL; 585 LargeUnlink(Closure->eccName); /* Do not leave partial .ecc file behind */ 586 goto terminate; 587 } 588 589 /* Read the next data sectors of this layer. */ 590 591 for(si=0; si<actual_layer_sectors; si++) 592 { RS01ReadSector(image, ec->data+offset, block_idx[layer]); 593 block_idx[layer]++; 594 offset += 2048; 595 } 596 597 /* Now process the data bytes of the current layer. */ 598 599 for(si=0; si<actual_layer_bytes; si++) 600 { register int feedback; 601 602 feedback = gf_index_of[ec->data[si] ^ par_idx[sp]]; 603 604 if(feedback != GF_ALPHA0) /* non-zero feedback term */ 605 { register int spk = sp; 606 607 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 98]; 608 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 247]; 609 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 160]; 610 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 15]; 611 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 96]; 612 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 27]; 613 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 87]; 614 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 175]; 615 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 64]; 616 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 170]; 617 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 53]; 618 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 39]; 619 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 236]; 620 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 39]; 621 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 58]; 622 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 82]; 623 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 44]; 624 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 89]; 625 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 97]; 626 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 182]; 627 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 80]; 628 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 120]; 629 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 40]; 630 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 104]; 631 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 73]; 632 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 73]; 633 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 12]; 634 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 152]; 635 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 205]; 636 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 96]; 637 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 50]; 638 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 21]; 639 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 147]; 640 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 35]; 641 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 241]; 642 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 30]; 643 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 242]; 644 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 145]; 645 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 242]; 646 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 115]; 647 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 148]; 648 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 70]; 649 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 127]; 650 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 71]; 651 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 83]; 652 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 172]; 653 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 224]; 654 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 104]; 655 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 177]; 656 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 0]; 657 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 39]; 658 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 194]; 659 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 50]; 660 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 9]; 661 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 0]; 662 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 208]; 663 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 217]; 664 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 254]; 665 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 165]; 666 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 181]; 667 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 168]; 668 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 97]; 669 par_idx[((++spk)&63)] ^= enc_alpha_to[feedback + 45]; 670 671 par_idx[sp] = enc_alpha_to[feedback + 44]; 672 } 673 else /* zero feedback term */ 674 par_idx[sp] = 0; 675 676 par_idx += nroots; 677 } 678 679 sp = (sp+1) & 63; /* shift */ 680 681 /* Report progress */ 682 683 progress++; 684 percent = (1000*progress)/max_percent; 685 if(last_percent != percent) 686 { if(Closure->guiMode) 687 SetProgress(wl->encPBar2, percent, 1000); 688 else 689 PrintProgress(_("Ecc generation: %3d.%1d%%"), percent/10, percent%10); 690 last_percent = percent; 691 } 692 } 693 } 694 break; 695 696 default: /* general case for nroots other than 32 or 64 */ 697 {int sp = nroots - ndata % nroots; /* => (ndata + sp) mod nroots = 0 so that parity */ 698 /* is aligned at sp=0 after ndata iterations */ 699 if(sp==nroots) sp=0; 700 701 for(layer=0; layer<ndata; layer++) 702 { int offset = 0; 703 unsigned char *par_idx = ec->parity; 704 705 if(Closure->stopActions) /* User hit the Stop button */ 706 { if(Closure->stopActions == STOP_CURRENT_ACTION) /* suppress memleak warning when closing window */ 707 SetLabelText(GTK_LABEL(wl->encFootline), 708 _("<span %s>Aborted by user request!</span>"), 709 Closure->redMarkup); 710 ec->earlyTermination = FALSE; /* suppress respective error message */ 711 LargeClose(image->eccFile); 712 image->eccFile = NULL; 713 LargeUnlink(Closure->eccName); /* Do not leave partial .ecc file behind */ 714 goto terminate; 715 } 716 717 /* Read the next data sectors of this layer. */ 718 719 for(si=0; si<actual_layer_sectors; si++) 720 { RS01ReadSector(image, ec->data+offset, block_idx[layer]); 721 block_idx[layer]++; 722 offset += 2048; 723 } 724 725 /* Now process the data bytes of the current layer. */ 726 727 for(si=0; si<actual_layer_bytes; si++) 728 { register int feedback; 729 730 feedback = gf_index_of[ec->data[si] ^ par_idx[sp]]; 731 732 if(feedback != GF_ALPHA0) /* non-zero feedback term */ 733 { register int spk = sp+1; 734 register int *gpoly = rs_gpoly + nroots; 735 736 switch(nroots-spk) 737 { 738 case 110: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 739 case 109: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 740 case 108: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 741 case 107: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 742 case 106: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 743 case 105: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 744 case 104: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 745 case 103: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 746 case 102: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 747 case 101: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 748 case 100: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 749 case 99: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 750 case 98: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 751 case 97: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 752 case 96: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 753 case 95: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 754 case 94: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 755 case 93: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 756 case 92: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 757 case 91: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 758 case 90: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 759 case 89: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 760 case 88: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 761 case 87: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 762 case 86: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 763 case 85: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 764 case 84: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 765 case 83: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 766 case 82: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 767 case 81: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 768 case 80: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 769 case 79: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 770 case 78: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 771 case 77: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 772 case 76: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 773 case 75: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 774 case 74: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 775 case 73: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 776 case 72: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 777 case 71: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 778 case 70: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 779 case 69: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 780 case 68: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 781 case 67: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 782 case 66: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 783 case 65: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 784 case 64: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 785 case 63: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 786 case 62: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 787 case 61: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 788 case 60: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 789 case 59: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 790 case 58: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 791 case 57: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 792 case 56: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 793 case 55: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 794 case 54: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 795 case 53: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 796 case 52: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 797 case 51: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 798 case 50: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 799 case 49: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 800 case 48: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 801 case 47: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 802 case 46: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 803 case 45: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 804 case 44: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 805 case 43: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 806 case 42: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 807 case 41: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 808 case 40: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 809 case 39: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 810 case 38: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 811 case 37: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 812 case 36: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 813 case 35: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 814 case 34: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 815 case 33: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 816 case 32: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 817 case 31: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 818 case 30: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 819 case 29: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 820 case 28: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 821 case 27: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 822 case 26: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 823 case 25: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 824 case 24: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 825 case 23: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 826 case 22: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 827 case 21: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 828 case 20: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 829 case 19: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 830 case 18: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 831 case 17: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 832 case 16: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 833 case 15: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 834 case 14: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 835 case 13: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 836 case 12: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 837 case 11: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 838 case 10: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 839 case 9: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 840 case 8: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 841 case 7: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 842 case 6: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 843 case 5: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 844 case 4: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 845 case 3: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 846 case 2: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 847 case 1: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 848 } 849 850 spk = 0; 851 852 switch(sp) 853 { 854 case 110: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 855 case 109: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 856 case 108: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 857 case 107: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 858 case 106: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 859 case 105: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 860 case 104: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 861 case 103: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 862 case 102: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 863 case 101: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 864 case 100: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 865 case 99: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 866 case 98: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 867 case 97: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 868 case 96: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 869 case 95: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 870 case 94: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 871 case 93: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 872 case 92: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 873 case 91: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 874 case 90: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 875 case 89: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 876 case 88: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 877 case 87: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 878 case 86: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 879 case 85: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 880 case 84: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 881 case 83: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 882 case 82: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 883 case 81: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 884 case 80: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 885 case 79: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 886 case 78: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 887 case 77: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 888 case 76: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 889 case 75: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 890 case 74: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 891 case 73: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 892 case 72: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 893 case 71: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 894 case 70: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 895 case 69: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 896 case 68: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 897 case 67: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 898 case 66: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 899 case 65: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 900 case 64: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 901 case 63: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 902 case 62: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 903 case 61: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 904 case 60: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 905 case 59: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 906 case 58: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 907 case 57: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 908 case 56: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 909 case 55: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 910 case 54: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 911 case 53: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 912 case 52: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 913 case 51: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 914 case 50: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 915 case 49: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 916 case 48: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 917 case 47: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 918 case 46: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 919 case 45: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 920 case 44: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 921 case 43: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 922 case 42: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 923 case 41: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 924 case 40: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 925 case 39: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 926 case 38: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 927 case 37: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 928 case 36: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 929 case 35: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 930 case 34: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 931 case 33: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 932 case 32: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 933 case 31: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 934 case 30: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 935 case 29: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 936 case 28: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 937 case 27: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 938 case 26: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 939 case 25: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 940 case 24: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 941 case 23: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 942 case 22: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 943 case 21: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 944 case 20: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 945 case 19: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 946 case 18: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 947 case 17: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 948 case 16: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 949 case 15: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 950 case 14: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 951 case 13: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 952 case 12: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 953 case 11: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 954 case 10: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 955 case 9: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 956 case 8: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 957 case 7: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 958 case 6: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 959 case 5: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 960 case 4: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 961 case 3: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 962 case 2: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 963 case 1: par_idx[spk++] ^= enc_alpha_to[feedback + *--gpoly]; 964 } 965 966 par_idx[sp] = enc_alpha_to[feedback + rs_gpoly[0]]; 967 } 968 else /* zero feedback term */ 969 par_idx[sp] = 0; 970 971 par_idx += nroots; 972 } 973 974 if(++sp>=nroots) sp=0; /* shift */ 975 976 /* Report progress */ 977 978 progress++; 979 percent = (1000*progress)/max_percent; 980 if(last_percent != percent) 981 { if(Closure->guiMode) 982 SetProgress(wl->encPBar2, percent, 1000); 983 else 984 PrintProgress(_("Ecc generation: %3d.%1d%%"), percent/10, percent%10); 985 last_percent = percent; 986 } 987 } 988 } 989 break; 990 } 991 992 /* Write the nroots bytes of parity information */ 993 994 n = LargeWrite(image->eccFile, ec->parity, nroots*actual_layer_bytes); 995 996 if(n != nroots*actual_layer_bytes) 997 Stop(_("could not write to ecc file \"%s\":\n%s"),Closure->eccName,strerror(errno)); 998 999 MD5Update(&md5Ctxt, ec->parity, nroots*actual_layer_bytes); 1000 } 1001 1002 /*** Complete the ecc header and write it out */ 1003 1004 MD5Final(eh->eccSum, &md5Ctxt); 1005 1006 LargeSeek(image->eccFile, 0); 1007 #ifdef HAVE_BIG_ENDIAN 1008 SwapEccHeaderBytes(eh); 1009 #endif 1010 n = LargeWrite(image->eccFile, eh, sizeof(EccHeader)); 1011 if(n != sizeof(EccHeader)) 1012 Stop(_("Can't write ecc header:\n%s"),strerror(errno)); 1013 1014 if(!LargeClose(image->eccFile)) 1015 Stop(_("Error closing error correction file:\n%s"), strerror(errno)); 1016 image->eccFile = NULL; 1017 1018 PrintTimeToLog(ec->timer, "for ECC generation.\n"); 1019 1020 PrintProgress(_("Ecc generation: 100.0%%\n")); 1021 PrintLog(_("Error correction file \"%s\" created.\n" 1022 "Make sure to keep this file on a reliable medium.\n"), 1023 Closure->eccName); 1024 1025 if(Closure->guiMode) 1026 { SetProgress(wl->encPBar2, 100, 100); 1027 1028 SetLabelText(GTK_LABEL(wl->encFootline), 1029 _("The error correction file has been successfully created.\n" 1030 "Make sure to keep this file on a reliable medium.")); 1031 } 1032 1033 /*** If the --unlink option or respective GUI switch is set, 1034 unlink the image. */ 1035 1036 if(Closure->unlinkImage) 1037 { if(ec->image) CloseImage(ec->image); 1038 ec->image = NULL; 1039 unlink_image(Closure->guiMode ? wl->encFootline2 : NULL); 1040 } 1041 1042 /*** Clean up */ 1043 1044 ec->earlyTermination = FALSE; 1045 1046 terminate: 1047 ecc_cleanup((gpointer)ec); 1048 } 1049 1050