1 /*  dvdisaster: Additional error correction for optical media.
2  *  Copyright (C) 2004-2015 Carsten Gnoerlich.
3  *
4  *  Email: carsten@dvdisaster.org  -or-  cgnoerlich@fsfe.org
5  *  Project homepage: http://www.dvdisaster.org
6  *
7  *  This file is part of dvdisaster.
8  *
9  *  dvdisaster is free software: you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation, either version 3 of the License, or
12  *  (at your option) any later version.
13  *
14  *  dvdisaster is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef DVDISASTER_H
24 #define DVDISASTER_H
25 
26 /* "Dare to be gorgeous and unique.
27  *  But don't ever be cryptic or otherwise unfathomable.
28  *  Make it unforgettably great."
29  *
30  *  From "A Final Note on Style",
31  *  Amiga Intuition Reference Manual, 1986, p. 231
32  */
33 
34 /***
35  *** I'm too lazy to mess with #include dependencies.
36  *** Everything #includeable is rolled up herein...
37  */
38 
39 #define _GNU_SOURCE
40 
41 #include <glib.h>
42 #include <glib/gprintf.h>
43 #include <gtk/gtk.h>
44 
45 #include <ctype.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <getopt.h>
49 #ifdef WITH_NLS_YES
50  #include <libintl.h>
51  #include <locale.h>
52 #endif
53 #include <math.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <stdarg.h>
57 #include <stddef.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <unistd.h>
62 
63 #include "md5.h"
64 
65 #ifndef G_THREADS_ENABLED
66  #error "need multithreading glib2"
67 #endif
68 
69 /* Phrase extraction for gettext()
70    Note that these functions are even required when
71    WITH_NLS_NO is set! */
72 
73 #define _(string) sgettext(string)
74 #define _utf(string) sgettext_utf8(string)
75 
76 /* File permissions for images */
77 
78 #define IMG_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
79 
80 /* Using round() is preferred over rint() on systems which have it */
81 
82 #ifndef HAVE_ROUND
83  #define round(x) rint(x)
84 #endif
85 
86 /* Some standard media sizes */
87 
88 #define CDR_SIZE         (351*1024)
89 #define DVD_SL_SIZE      2295104  /* DVD+R/RW size used at least common denominator */
90 #define DVD_DL_SIZE 	 4171712  /* also seen: 4148992 4173824  */
91 #define BD_SL_SIZE      11826176
92 #define BD_DL_SIZE	23652352
93 
94 /* Maximum accepted media sizes (in 2K sectors) */
95 
96 #define MAX_CDR_SIZE     (100*60*75)     /* CDs can't have >100min w/o severe hacks  */
97 #define MAX_DVD_SL_SIZE  2500000         /* I have to guess here */
98 #define MAX_DVD_DL_SIZE  4600000         /* I have to guess here */
99 
100 /* Maximum number of parallel encoder/decoder threads */
101 
102 #define MAX_CODEC_THREADS 1024           /* not including IO and GUI */
103 #define MAX_OLD_CACHE_SIZE  8096         /* old cache for RS01/RS02  */
104 #define MAX_PREFETCH_CACHE_SIZE (512*1024)   /* upto 0.5TB RS03  */
105 
106 /* Choices for I/O strategy */
107 
108 #define IO_STRATEGY_READWRITE 0
109 #define IO_STRATEGY_MMAP 1
110 
111 /* SCSI driver selection on Linux */
112 
113 #define DRIVER_NONE 0
114 #define DRIVER_CDROM 1
115 #define DRIVER_SG 3
116 
117 /* Definitions for Closure->eccTarget */
118 
119 #define ECC_FILE  0
120 #define ECC_IMAGE 1
121 
122 /* Definitions for Closure->stopActions */
123 
124 #define STOP_CURRENT_ACTION 1
125 #define STOP_SHUTDOWN_ALL 2
126 
127 /***
128  *** Our global closure (encapsulation of global variables)
129  ***/
130 
131 typedef struct _GlobalClosure
132 {  int version;         /* Integer number representing current program version */
133    char *cookedVersion; /* version string formatted for GUI use */
134    char *versionString; /* more detailed version string */
135    char *device;        /* currently selected device to read from */
136    GPtrArray *deviceNames;  /* List of drive names */
137    GPtrArray *deviceNodes;  /* List of device nodes (C: or /dev/foo) */
138    char *imageName;     /* complete path of current image file */
139    char *eccName;       /* complete path of current ecc file */
140    GPtrArray *methodList; /* List of available methods */
141    char *methodName;    /* Name of currently selected codec */
142    gint64 readStart;    /* Range to read */
143    gint64 readEnd;
144    gint64 cdSize;       /* Maximum cd size (for RS02 type images) */
145    gint64 dvdSize1;     /* Maximum 1-layer dvd size (for augmented images) */
146    gint64 dvdSize2;     /* Maximum 2-layer dvd size (for augmented images) */
147    gint64 bdSize1;      /* Maximum 1-layer dvd size (for augmented images) */
148    gint64 bdSize2;      /* Maximum 2-layer dvd size (for augmented images) */
149    gint64 savedCDSize;  /* Undo values for above */
150    gint64 savedDVDSize1;
151    gint64 savedDVDSize2;
152    gint64 savedBDSize1;
153    gint64 savedBDSize2;
154    gint64 mediumSize;   /* Maximum medium size (for augmented images) */
155    int cacheMiB;        /* Cache setting for the parity codec, in megabytes */
156    int prefetchSectors; /* Prefetch setting per encoder thread */
157    int codecThreads;    /* Number of threads to use for RS encoders */
158    int encodingAlgorithm; /* Force a certain codec type for RS03 */
159    int encodingIOStrategy; /* Force a IO strategy for RS03 encoding */
160    int sectorSkip;      /* Number of sectors to skip after read error occurs */
161    char *redundancy;    /* Error correction code redundancy */
162    int eccTarget;       /* 0=file; 1=augmented image */
163    int readRaw;         /* Read CD sectors raw + verify them */
164    int rawMode;         /* mode for mode page */
165    int minReadAttempts; /* minimum reading attempts */
166    int maxReadAttempts; /* maximal reading attempts */
167    int internalAttempts;/* read attempts by the drive itself */
168    int adaptiveRead;    /* Use optimized strategy for reading defective images */
169    int speedWarning;    /* Print warning if speed changes by more than given percentage */
170    int fillUnreadable;  /* Byte value for filling unreadable sectors or -1 */
171    int spinupDelay;     /* Seconds to wait for drive to spin up */
172    int truncate;        /* confirms truncation of large images */
173    int noTruncate;      /* do not truncate image at the end */
174    int dsmVersion;      /* 1 means new style dead sector marker */
175    int unlinkImage;     /* delete image after ecc file creation */
176    int confirmDeletion; /* do not ask whether files should be deleted */
177    int driveSpeed;      /* currently unused */
178    int debugMode;       /* may activate additional features */
179    int debugCDump;      /* dump as #include file instead of hexdump */
180    int verbose;         /* may activate additional messages */
181    int quickVerify;     /* do only non time-consuming verify actions */
182    int screenShotMode;  /* screen shot mode */
183    int autoSuffix;      /* automatically extend files with suffices .iso/.ecc */
184    int ignoreIsoSize;   /* get size per READ CAPACITY; ignore all ISO/UDF meta data */
185    int examineRS02;     /* perform deep search for RS02 structures */
186    int examineRS03;     /* perform deep search for RS03 structures */
187    int readAndCreate;   /* automatically create .ecc file after reading an image */
188    int enableCurveSwitch; /* TRUE in readAndCreateMode after reading is complete */
189    int welcomeMessage;  /* just print dvdisaster logo if FALSE */
190    int dotFileVersion;  /* version of dotfile */
191    int simulateDefects; /* if >0, this is the percentage of simulated media defects */
192    char *simulateCD;    /* Simulate CD from given image */
193    int defectiveDump;   /* dump non-recoverable sectors into given path */
194    char *dDumpDir;      /* directory for above */
195    char *dDumpPrefix;   /* file name prefix for above */
196    int reverseCancelOK; /* if TRUE the button order is reversed */
197    int eject;           /* eject medium on success */
198    int readingPasses;   /* try to read medium n times */
199    int pauseAfter;      /* pause after given amount of minutes */
200    int pauseDuration;   /* duration of pause in minutes */
201    int pauseEject;      /* Eject medium during pause */
202    int ignoreFatalSense;/* Continue reading after potential fatal sense errors */
203    int useSSE2;         /* TRUE means to use SSE2 version of the codec. */
204    int useAltiVec;      /* TRUE means to use AltiVec version of the codec. */
205    int clSize;          /* Bytesize of cache line */
206    int useSCSIDriver;   /* Whether to use generic or sg driver on Linux */
207    int fixedSpeedValues;/* output fixed speed reading to make comparing debugging output easier */
208    char *homeDir;       /* path to users home dir */
209    char *dotFile;       /* path to .dvdisaster file */
210    char *logFile;       /* path to logfile */
211    int  logFileEnabled; /* logfile enabled */
212    int  logFileStamped; /* time stamp written to log file */
213    char *binDir;        /* place where the binary resides */
214    char *docDir;        /* place where our documentation resides */
215    char *viewer;        /* Name of preferred PDF viewer */
216 
217    GMutex progressLock; /* A mutex protected the stuff below */
218    char bs[256];        /* A string of 255 backspace characters */
219    char sp[256];        /* A string of 255 space characters */
220    int progressLength;  /* Length of last progress msg printed */
221 
222    GThread *mainThread; /* Thread of the main() routine */
223    void (*cleanupProc)(gpointer);  /* Procedure to cleanup running threads after an error condition */
224    gpointer cleanupData;
225    GThread *subThread;  /* Wait for this thread to terminate after an abort action */
226    char *errorTitle;    /* Title to show in error dialogs */
227    gint32 randomSeed;   /* for the random number generator */
228 
229    guint32 *crcCache;              /* sectorwise CRC32 for last image read */
230    char    *crcImageName;          /* file name of cached image */
231    unsigned char md5Cache[16];     /* md5sum of last image read */
232 
233 
234    /*** GUI-related things */
235 
236    int guiMode;              /* TRUE if GUI is active */
237    int stopActions;          /* crude method to stop ongoing action(s) */
238    int noMissingWarnings;    /* suppress warnings about inconsistent missing sectors */
239 
240    GtkWidget *logWidget;     /* Dialog for the log display */
241    GtkScrolledWindow *logScroll; /* and its scrolled window */
242    GtkTextBuffer *logBuffer; /* Text buffer for the log output */
243    GString *logString;       /* holds logging output for current action */
244    GMutex *logLock;          /* protects the logString */
245 
246    /*** Widgets of the main window */
247 
248    GtkWindow *window;        /* main window */
249    GtkTooltips *tooltips;    /* our global tooltips structure */
250    GdkPixbuf *windowIcon;    /* main window icon */
251 
252    GtkWidget *fileMenuImage;  /* Select image entry */
253    GtkWidget *fileMenuEcc;    /* Select Parity File entry */
254    GtkWidget *toolMenuAnchor; /* Anchor of tool menu */
255 
256    GtkWidget *driveCombo;    /* combo box for drive selection */
257 
258    GtkWidget *imageFileSel;  /* image file selector */
259    GtkWidget *imageEntry;    /* image name entry field */
260    GtkWidget *eccFileSel;    /* ecc file selector */
261    GtkWidget *eccEntry;      /* ecc name entry field */
262 
263    GtkWidget *notebook;      /* The notebook behind our central output area */
264    GtkLabel  *status;        /* The status label */
265 
266    GtkWidget *prefsButton;
267    GtkWidget *helpButton;
268 
269    GtkWidget *readButton;
270    GtkWidget *createButton;
271    GtkWidget *scanButton;
272    GtkWidget *fixButton;
273    GtkWidget *testButton;
274 
275    /*** The preferences window */
276 
277    GtkWindow *prefsWindow;
278    void *prefsContext;       /* local data for the preferences window */
279 
280    /*** The raw editor window */
281 
282    void *rawEditorContext;
283 
284    /*** The medium info window */
285 
286    GtkWidget *mediumWindow;   /* Dialog for the medium info window */
287    GtkWidget *mediumDrive;
288    void *mediumInfoContext;   /* private data */
289 
290    /*** Common stuff for drawing curves and spirals */
291 
292    GdkGC     *drawGC;
293    GdkColor  *background,*foreground,*grid;
294    GdkColor  *redText;
295    char      *redMarkup;
296    GdkColor  *greenText;
297    char      *greenMarkup;
298    GdkColor  *barColor;
299    GdkColor  *logColor;
300    GdkColor  *curveColor;
301    GdkColor  *redSector;
302    GdkColor  *yellowSector;
303    GdkColor  *greenSector;
304    GdkColor  *blueSector;
305    GdkColor  *whiteSector;
306    GdkColor  *darkSector;
307    char      *invisibleDash;
308 
309    /*** Widgets for the linear reading/scanning action */
310 
311    GtkWidget *readLinearHeadline;
312    GtkWidget *readLinearDrawingArea;
313    struct _Curve  *readLinearCurve;
314    struct _Spiral *readLinearSpiral;
315    GtkWidget *readLinearNotebook;
316    GtkWidget *readLinearSpeed;
317    GtkWidget *readLinearErrors;
318    GtkWidget *readLinearFootline;
319    GtkWidget *readLinearFootlineBox;
320    gint64 crcErrors, readErrors;  /* these are passed between threads and must therefore be global */
321    int    crcAvailable;           /* true when CRC data is available while reading/scanning */
322 
323    /*** Widgets for the adaptive reading action */
324 
325    GtkWidget *readAdaptiveHeadline;
326    GtkWidget *readAdaptiveDrawingArea;
327    struct _Spiral *readAdaptiveSpiral;
328    char *readAdaptiveSubtitle;
329    char *readAdaptiveErrorMsg;
330    int additionalSpiralColor;
331 
332 } GlobalClosure;
333 
334 extern GlobalClosure *Closure;  /* these should be the only global variables! */
335 extern int exitCode;            /* value to use on exit() */
336 
337 /***
338  ***
339  ***/
340 
341 #define MAX_FILE_SEGMENTS 100
342 
343 typedef struct _LargeFile
344 {  int fileHandle;
345    guint64 offset;
346    char *path;
347    guint64 size;
348    int flags;
349 } LargeFile;
350 
351 /***
352  *** Aligned 64bit data types
353  ***
354  * Needed to prevent 4 byte packing on 32bit systems.
355  */
356 
357 #define aligned_gint64 gint64 __attribute__((aligned(8)))
358 #define aligned_guint64 guint64 __attribute__((aligned(8)))
359 
360 /***
361  *** The .ecc file header
362  ***/
363 
364 #define FINGERPRINT_SECTOR 16 /* Sector currently used to calculate the fingerprint. */
365                               /* This is the ISO filesystem root sector which contains */
366                               /* the volume label and creation time stamps. */
367                               /* Versions upto 0.64 used sector 257, */
368                               /* but that was not a wise choice for CD media.*/
369 
370 #define MFLAG_DEVEL (1<<0)    /* for methodFlags[3] */
371 #define MFLAG_RC    (1<<1)
372 
373 #define MFLAG_DATA_MD5 (1<<0)  /* RS03: md5sum for data part available */
374 #define MFLAG_ECC_FILE (1<<1)  /* RS03: This is a ecc file */
375 
376 typedef struct _EccHeader
377 {  gint8 cookie[12];           /* "*dvdisaster*" */
378    gint8 method[4];            /* e.g. "RS01" */
379    gint8 methodFlags[4];       /* 0-2 for free use by the respective methods; 3 see above */
380    guint8 mediumFP[16];        /* fingerprint of FINGERPRINT SECTOR */
381    guint8 mediumSum[16];       /* complete md5sum of whole medium */
382    guint8 eccSum[16];          /* md5sum of ecc code section of .ecc file */
383    guint8 sectors[8];          /* number of sectors medium is supposed to have w/o ecc */
384    gint32 dataBytes;           /* data bytes per ecc block */
385    gint32 eccBytes;            /* ecc bytes per ecc block */
386    gint32 creatorVersion;      /* which dvdisaster version created this */
387    gint32 neededVersion;       /* oldest version which can decode this file */
388    gint32 fpSector;            /* sector used to calculate mediumFP */
389    guint32 selfCRC;            /* CRC32 of EccHeader -- since V0.66 --*/
390    guint8 crcSum[16];          /* md5sum of crc code section of RS02 .iso file  */
391    gint32 inLast;              /* bytes contained in last sector */
392    aligned_guint64 sectorsPerLayer;    /* layer size for RS03 */
393    aligned_guint64 sectorsAddedByEcc;  /* sectors added by RS02/RS03 */
394    gint8 padding[3960];        /* pad to 4096 bytes: room for future expansion */
395 
396   /* Note: Bytes 2048 and up are currently used by the RS02/RS03 codec
397            for a copy of the first ecc blocks CRC sums. */
398 } EccHeader;
399 
400 /***
401  *** The CRC block data structure
402  ***
403  * RS03 uses this data structure in its CRC layer.
404  */
405 
406 typedef struct _CrcBlock
407 {  guint32 crc[256];           /* Checksum for the data sectors */
408    gint8 cookie[12];           /* "*dvdisaster*" */
409    gint8 method[4];            /* e.g. "RS03" */
410    gint8 methodFlags[4];       /* 0-2 for free use by the respective methods; 3 see above */
411    gint32 creatorVersion;      /* which dvdisaster version created this */
412    gint32 neededVersion;       /* oldest version which can decode this file */
413    gint32 fpSector;            /* sector used to calculate mediumFP */
414    guint8 mediumFP[16];        /* fingerprint of FINGERPRINT SECTOR */
415    guint8 mediumSum[16];       /* complete md5sum of whole medium */
416    aligned_guint64 dataSectors;/* number of sectors of the payload (e.g. iso file sys) */
417    gint32 inLast;              /* bytes contained in last sector */
418    gint32 dataBytes;           /* data bytes per ecc block */
419    gint32 eccBytes;            /* ecc bytes per ecc block */
420    aligned_guint64 sectorsPerLayer; /* for recalculation of layout */
421    guint32 selfCRC;            /* CRC32 of ourself, zero padded to 2048 bytes */
422 } CrcBlock;
423 
424 /***
425  *** forward declarations
426  ***/
427 
428 extern struct _RawBuffer *rawbuffer_forward;
429 extern struct _DefectiveSectorHeader *dsh_forward;
430 extern struct _DeviceHandle *dh_forward;
431 
432 /***
433  *** bitmap.c
434  ***/
435 
436 typedef struct _Bitmap
437 {  guint32 *bitmap;
438    gint32 size;
439    gint32 words;
440 } Bitmap;
441 
442 Bitmap* CreateBitmap0(int);
443 #define GetBit(bm,bit) (bm->bitmap[(bit)>>5] & (1<<((bit)&31)))
444 #define SetBit(bm,bit) bm->bitmap[(bit)>>5] |= (1<<((bit)&31))
445 #define ClearBit(bm,bit) bm->bitmap[(bit)>>5] &= ~(1<<((bit)&31))
446 int CountBits(Bitmap*);
447 void FreeBitmap(Bitmap*);
448 
449 /***
450  *** build.h
451  ***/
452 
453 extern int buildCount;
454 
455 /***
456  *** cacheprobe.h
457  ***/
458 
459 int ProbeCacheLineSize();
460 
461 /***
462  *** closure.c
463  ***/
464 
465 void InitClosure(void);
466 void LocalizedFileDefaults(void);
467 void UpdateMarkup(char**, GdkColor*);
468 void DefaultColors(void);
469 void ClearCrcCache(void);
470 void FreeClosure(void);
471 void ReadDotfile(void);
472 void WriteSignature(void);
473 int  VerifySignature(void);
474 
475 /***
476  *** crc32.c
477  ***/
478 
479 guint32 Crc32(unsigned char*, int);
480 guint32 EDCCrc32(unsigned char*, int);
481 
482 /***
483  *** crcbuf.c
484  ***/
485 
486 typedef struct _CrcBuf
487 {  guint32 *crcbuf;
488    guint64 size;
489    Bitmap *valid;
490 } CrcBuf;
491 
492 enum
493 {  CRC_UNKNOWN,
494    CRC_BAD,
495    CRC_GOOD,
496    CRC_OUTSIDE_BOUND
497 };
498 
499 CrcBuf *CreateCrcBuf(guint64);
500 void FreeCrcBuf(CrcBuf*);
501 
502 int CheckAgainstCrcBuffer(CrcBuf*, gint64, unsigned char*);
503 
504 /***
505  *** curve.c
506  ***/
507 
508 enum
509 {  CURVE_PERCENT,
510    CURVE_MEGABYTES
511 };
512 
513 typedef struct _Curve
514 {  GtkWidget *widget;   /* drawing area which is hosting us */
515    PangoLayout *layout;
516    gdouble *fvalue;     /* floating point curve values */
517    gint    *ivalue;     /* integer bar curve values */
518    gint    *lvalue;     /* logarithmic integer curve */
519    gint    enable;      /* which of the above should be drawn */
520    gint lastValueIdx;   /* end of value array */
521    gint leftX,rightX;   /* Position of left and right y axis */
522    gint topY,bottomY;   /* Top and bottom end of i/f y axes */
523    gint topLY,bottomLY; /* Top and bottom end of l y axes */
524    char *leftLabel;     /* Label of left coordinate axis */
525    char *leftLogLabel;  /* Label of left log coordinate axis */
526    char *leftFormat;    /* Format of left coordinate axis numbering */
527    int bottomFormat;    /* what kind of data are we displaying? */
528    int margin;
529    int maxX,maxY,logMaxY; /* current max value at y axis */
530 } Curve;
531 
532 #define DRAW_ICURVE (1<<0)
533 #define DRAW_FCURVE (1<<1)
534 #define DRAW_LCURVE (1<<2)
535 
536 Curve* CreateCurve(GtkWidget*, char*, char*, int, int);
537 void ZeroCurve(Curve*);
538 void FreeCurve(Curve*);
539 
540 void UpdateCurveGeometry(Curve*, char*, int);
541 
542 int  CurveX(Curve*, gdouble);
543 int  CurveY(Curve*, gdouble);
544 int  CurveLogY(Curve*, gdouble);
545 void RedrawAxes(Curve*);
546 void RedrawCurve(Curve*, int);
547 
548 /***
549  *** debug.c
550  ***/
551 
552 void HexDump(unsigned char*, int, int);
553 void LaTeXify(gint32*, int, int);
554 void AppendToTextFile(char*,char*, ...);
555 void CopySector(char*);
556 void Byteset(char*);
557 void Erase(char*);
558 void MergeImages(char*, int);
559 void RandomError(char*);
560 void RandomImage(char*, char*, int);
561 void RawSector(char*);
562 void ReadSector(char*);
563 void SendCDB(char*);
564 void ShowHeader(char*);
565 void ShowSector(char*);
566 Bitmap* SimulateDefects(gint64);
567 void TruncateImageFile(char*);
568 void ZeroUnreadable(void);
569 
570 /***
571  *** ds-marker.c
572  ***/
573 
574 enum
575 {  SECTOR_PRESENT,
576    SECTOR_MISSING,
577    SECTOR_MISSING_DISPLACED,
578    SECTOR_MISSING_WRONG_FP,
579    SECTOR_WITH_SIMULATION_HINT
580 };
581 
582 enum
583 {  SOURCE_MEDIUM,
584    SOURCE_IMAGE,
585    SOURCE_ECCFILE
586 };
587 
588 void CreateMissingSector(unsigned char*, guint64, unsigned char*, guint64, char*);
589 void CreateDebuggingSector(unsigned char*, guint64, unsigned char*, guint64, char*, char*);
590 int CheckForMissingSector(unsigned char*, guint64, unsigned char*, guint64);
591 int CheckForMissingSectors(unsigned char*, guint64, unsigned char*, guint64, int, guint64*);
592 void ExplainMissingSector(unsigned char*, guint64, int, int, int*);
593 
594 void CreatePaddingSector(unsigned char*, guint64, unsigned char*, guint64);
595 
596 char *GetSimulationHint(unsigned char*);
597 
598 /***
599  *** endian.c
600  ***/
601 
602 guint32 SwapBytes32(guint32);
603 guint64 SwapBytes64(guint64);
604 void    SwapEccHeaderBytes(EccHeader*);
605 void    SwapDefectiveHeaderBytes(struct _DefectiveSectorHeader*);
606 void    SwapCrcBlockBytes(CrcBlock*);
607 void    PrintEccHeader(EccHeader*);
608 
609 /***
610  *** fix-window.c
611  ***/
612 
613 void CreateFixWindow(GtkWidget*);
614 
615 /***
616  *** galois.c
617  ***
618  * This is currently the hardcoded GF(2**8).
619  * gint32 gives abundant space for the GF.
620  * Squeezing it down to guint8 won't probably gain much,
621  * so we implement this defensively here.
622  *
623  * Note that some performance critical stuff needs to
624  * be #included from galois-inlines.h
625  */
626 
627 /* Galois field parameters for 8bit symbol Reed-Solomon code */
628 
629 #define GF_SYMBOLSIZE 8
630 #define GF_FIELDSIZE (1<<GF_SYMBOLSIZE)
631 #define GF_FIELDMAX (GF_FIELDSIZE-1)
632 #define GF_ALPHA0 GF_FIELDMAX
633 
634 /* RS polynomial parameters for RS01/RS02 codec */
635 
636 #define RS_GENERATOR_POLY 0x187    /* 1 + X + X**2 + X**7 + X**8 */
637 #define RS_FIRST_ROOT 112          /* same choices as in CCSDS */
638 #define RS_PRIM_ELEM 11
639 #define RS_PRIMTH_ROOT 116         /* prim-th root of 1 */
640 
641 /* Lookup tables for Galois field arithmetic */
642 
643 typedef struct _GaloisTables
644 {  gint32 gfGenerator;  /* GF generator polynomial */
645    gint32 *indexOf;     /* log */
646    gint32 *alphaTo;     /* inverse log */
647    gint32 *encAlphaTo; /* inverse log optimized for encoder */
648 } GaloisTables;
649 
650 /* Lookup and working tables for the ReedSolomon codecs */
651 
652 typedef struct _ReedSolomonTables
653 {  GaloisTables *gfTables;/* from above */
654    gint32 *gpoly;        /* RS code generator polynomial */
655    gint32 fcr;           /* first consecutive root of RS generator polynomial */
656    gint32 primElem;      /* primitive field element */
657    gint32 nroots;        /* degree of RS generator polynomial */
658    gint32 ndata;         /* data bytes per ecc block */
659    gint32 shiftInit;     /* starting value for iteratively processing parity */
660 
661    guint8 *bLut[GF_FIELDSIZE];   /* 8bit encoder lookup table */
662    guint8 *synLut;       /* Syndrome calculation speedup */
663 } ReedSolomonTables;
664 
665 GaloisTables* CreateGaloisTables(gint32);
666 void FreeGaloisTables(GaloisTables*);
667 
668 ReedSolomonTables *CreateReedSolomonTables(GaloisTables*, gint32, gint32, int);
669 void FreeReedSolomonTables(ReedSolomonTables*);
670 
671 /***
672  *** help-dialogs.c
673  ***/
674 
675 /* Creating labels with links to online help */
676 
677 typedef struct _LabelWithOnlineHelp
678 {  GtkWidget *helpWindow;
679    GtkWidget *normalLabel;
680    GtkWidget *linkBox;
681    GtkWidget *linkLabel;
682    GtkWidget *vbox;
683    GPtrArray *lastSizes;  /* for breaking expose loops between the help windows */
684 
685    char *windowTitle;
686    char *normalText;
687    char *highlitText;
688    int inside;
689    int outerPadding;   /* Padding between window and outer vbox */
690 } LabelWithOnlineHelp;
691 
692 LabelWithOnlineHelp* CreateLabelWithOnlineHelp(char*, char*);
693 LabelWithOnlineHelp* CloneLabelWithOnlineHelp(LabelWithOnlineHelp*, char*);
694 void FreeLabelWithOnlineHelp(LabelWithOnlineHelp*);
695 void SetOnlineHelpLinkText(LabelWithOnlineHelp*, char*);
696 void AddHelpListItem(LabelWithOnlineHelp*, char*, ...);
697 void AddHelpParagraph(LabelWithOnlineHelp*, char*, ...);
698 void AddHelpWidget(LabelWithOnlineHelp*, GtkWidget*);
699 
700 /* Specific online help dialogs */
701 
702 GtkWidget* ShowTextfile(char*, char*, char*, GtkScrolledWindow**, GtkTextBuffer**);
703 void ShowGPL();
704 void ShowLog();
705 void UpdateLog();
706 void AboutDialog();
707 
708 void AboutText(GtkWidget*, char*, ...);
709 void AboutLink(GtkWidget*, char*, char*);
710 void AboutTextWithLink(GtkWidget*, char*, char*);
711 
712 /***
713  *** heuristic-lec.c
714  ***/
715 
716 void UpdateByteCounts(struct _RawBuffer*);
717 void CalculatePQLoad(struct _RawBuffer*);
718 void UpdatePQParityList(struct _RawBuffer*, unsigned char*);
719 
720 int HeuristicLEC(unsigned char*, struct _RawBuffer*, unsigned char*);
721 int SearchPlausibleSector(struct _RawBuffer*, int);
722 int BruteForceSearchPlausibleSector(struct _RawBuffer*);
723 int AckHeuristic(struct _RawBuffer*);
724 
725 /***
726  *** icon-factory.c
727  ***/
728 
729 void CreateIconFactory();
730 
731 /***
732  *** image.c
733  ***/
734 
735 enum {IMAGE_NONE, IMAGE_FILE, IMAGE_MEDIUM};
736 enum {FP_UNKNOWN, FP_UNREADABLE, FP_PRESENT};
737 enum {ECCFILE_PRESENT, ECCFILE_MISSING, ECCFILE_INVALID, ECCFILE_DEFECTIVE_HEADER, ECCFILE_WRONG_CODEC};
738 
739 typedef struct _Image
740 {  int type;                   /* file or medium */
741 
742    /* physical storage handles */
743 
744    LargeFile *file;
745    struct _DeviceHandle *dh;
746 
747    /*
748     * info on file system(s) found on medium
749     */
750 
751    struct _IsoInfo *isoInfo;  /* Information gathered from ISO filesystem */
752    struct _Method *eccMethod; /* Method used for augmenting the image */
753    EccHeader *eccHeader;      /* copy of ecc header in augmented image */
754    guint64 expectedSectors;   /* Image size according to codec (including augmented parts) */
755 
756    guint64 sectorSize;        /* size in sectors if this is a file based image */
757    int inLast;                /* files may have incomplete last sector */
758    guint64 sectorsMissing;    /* number of missing sectors */
759    guint64 crcErrors;         /* number of sectors with crc errors */
760    guint8 mediumSum[16];      /* complete md5sum of whole medium */
761 
762    /*
763     * image fingerprint caching
764     */
765 
766    guint8 imageFP[16];        /* Image fingerprint */
767    guint64 fpSector;          /* Sector used for calculating the fingerprint */
768    int fpState;               /* 0=unknown; 1=unreadable; 2=present */
769 
770   /*
771    * layout caching
772    */
773 
774    void *cachedLayout;        /* Layout of different codecs */
775 
776    /*
777     * optionally attached ecc file
778     */
779 
780    LargeFile *eccFile;        /* ecc file */
781    int eccFileState;          /* see enum above */
782    struct _Method *eccFileMethod;     /* method associated with it */
783    EccHeader *eccFileHeader;  /* copy of ecc header in ecc file */
784 } Image;
785 
786 Image* OpenImageFromFile(char*, int, mode_t);
787 Image* OpenImageFromDevice(char*);   /* really in scsi-layer.h */
788 Image* OpenEccFileForImage(Image*, char*, int, mode_t);
789 int ReportImageEccInconsistencies(Image*);
790 int GetImageFingerprint(Image*, guint8*, guint64);
791 void ExamineECC(Image*);
792 int ImageReadSectors(Image*, void*, guint64, int);
793 int TruncateImage(Image*, guint64);
794 void CloseImage(Image*);
795 
796 /***
797  *** large-io.c
798  ***/
799 
800 LargeFile *LargeOpen(char*, int, mode_t);
801 int LargeSeek(LargeFile*, off_t);
802 int LargeEOF(LargeFile*);
803 ssize_t LargeRead(LargeFile*, void*, size_t);
804 ssize_t LargeWrite(LargeFile*, void*, size_t);
805 int LargeClose(LargeFile*);
806 int LargeTruncate(LargeFile*, off_t);
807 int LargeStat(char*, guint64*);
808 int LargeUnlink(char*);
809 
810 int DirStat(char*);
811 FILE *portable_fopen(char*, char*);
812 int portable_mkdir(char*);
813 char *ApplyAutoSuffix(char*, char*);
814 
815 /***
816  *** l-ec.c
817  ***/
818 
819 #define N_P_VECTORS   86      /* 43 16bit p vectors */
820 #define P_VECTOR_SIZE 26      /* using RS(26,24) ECC */
821 
822 #define N_Q_VECTORS   52      /* 26 16bit q vectors */
823 #define Q_VECTOR_SIZE 45      /* using RS(45,43) ECC */
824 
825 #define P_PADDING 229         /* padding values for */
826 #define Q_PADDING 210         /* shortened RS code  */
827 
828 int PToByteIndex(int, int);
829 int QToByteIndex(int, int);
830 void ByteIndexToP(int, int*, int*);
831 void ByteIndexToQ(int, int*, int*);
832 
833 void PrintVector(unsigned char*, int, int);
834 
835 void GetPVector(unsigned char*, unsigned char*, int);
836 void SetPVector(unsigned char*, unsigned char*, int);
837 void FillPVector(unsigned char*, unsigned char, int);
838 void AndPVector(unsigned char*, unsigned char, int);
839 void OrPVector(unsigned char*, unsigned char, int);
840 
841 void GetQVector(unsigned char*, unsigned char*, int);
842 void SetQVector(unsigned char*, unsigned char*, int);
843 void FillQVector(unsigned char*, unsigned char, int);
844 void AndQVector(unsigned char*, unsigned char, int);
845 void OrQVector(unsigned char*, unsigned char, int);
846 
847 int DecodePQ(ReedSolomonTables*, unsigned char*, int, int*, int);
848 
849 int CountC2Errors(unsigned char*);
850 
851 /***
852  *** logfile.c
853  ***/
854 
855 void DefaultLogFile();
856 void VPrintLogFile(char*, va_list);
857 void PrintLogFile(char*, ...);
858 
859 /***
860  *** maintenance.c
861  ***
862  *
863  * Provides a context for running testing functions
864  * within the usual program context.
865  * Only for debugging / development purposes.
866  */
867 
868 void Maintenance1(char*);
869 
870 /***
871  *** main-window.c
872  ***/
873 
874 #define FIRST_CREATE_WINDOW 3
875 
876 typedef enum
877 {  ACTION_WELCOME,   /* Tab 0; not really an action   */
878    ACTION_STOP,      /* ----   does not have a window */
879    ACTION_READ,      /* Tab 1 (linear); Tab 2 (adaptive)*/
880    ACTION_SCAN,      /* Tab 1 (linear); Tab 2 (adaptive)*/
881    ACTION_VERIFY,    /* VERIFY, CREATE and FIX have separate windows assigned */
882    ACTION_CREATE,    /* for each method. */
883    ACTION_CREATE_CONT,
884    ACTION_FIX
885 } MajorActions;
886 
887 void CreateMainWindow(int*, char***);
888 void ContinueWithAction(int);
889 
890 /***
891  *** medium-info.c
892  ***/
893 
894 void CreateMediumInfoWindow(void);
895 void PrintMediumInfo(void*);
896 
897 /***
898  *** memtrack.c
899  ***/
900 
901 /*
902  * Macro replacements for the glib functions.
903  */
904 
905 #ifdef WITH_MEMDEBUG_YES
906 #define g_malloc(size) malloc_ext(size,__FILE__,__LINE__)
907 #define g_malloc0(size) malloc_ext(size,__FILE__,__LINE__)
908 #define g_realloc(ptr,size) realloc_ext(ptr,size,__FILE__,__LINE__)
909 #define g_strdup(str) strdup_ext(str,__FILE__,__LINE__)
910 
911 #define g_try_malloc(size) try_malloc_ext(size,__FILE__,__LINE__)
912 
913 #define g_strdup_printf(format,args...) \
914         strdup_printf_ext(format,__FILE__,__LINE__, ## args)
915 #define g_strdup_vprintf(format,argp) \
916         strdup_vprintf_ext(format,argp,__FILE__,__LINE__)
917 #define g_locale_to_utf8(str,size,in,out,gerr) \
918         g_locale_to_utf8_ext(str,size,in,out,gerr,__FILE__,__LINE__)
919 #define g_free(size) free_ext(size,__FILE__,__LINE__)
920 
921 #define REMEMBER(ptr) remember(ptr, 0, __FILE__, __LINE__)
922 #define FORGET(ptr) forget(ptr)
923 #else
924 #define REMEMBER(ptr)
925 #define FORGET(ptr)
926 #endif
927 
928 /*
929  * Protos for the replacement functions.
930  */
931 
932 void*	malloc_ext(int,char*,int);
933 void*	realloc_ext(void*, int, char*, int);
934 void*	try_malloc_ext(int,char*,int);
935 char*	strdup_ext(const char*,char*,int);
936 char*	strdup_printf_ext(char*, char*, int, ...);
937 char*	strdup_vprintf_ext(char*, va_list, char*, int);
938 gchar*  g_locale_to_utf8_ext(const gchar*, gssize, gsize*, gsize*, GError**, char*, int);
939 void	free_ext(void*,char*,int);
940 
941 void    remember(void*, int, char*, int);
942 int     forget(void*);
943 
944 void    check_memleaks(void);
945 
946 /***
947  *** menubar.c
948  ***/
949 
950 void AttachTooltip(GtkWidget*, char*, char*);
951 GtkWidget* CreateMenuBar(GtkWidget*);
952 GtkWidget* CreateToolBar(GtkWidget*);
953 
954 /***
955  *** method.c / method-link.c
956  ***
957  * method-link.c is automatically created by the configure script.
958  */
959 
960 #define DATA_MD5_BAD (1<<0)          /* for result of finalizeCksums */
961 #define CRC_MD5_BAD (1<<1)
962 #define ECC_MD5_BAD (1<<2)
963 
964 typedef struct _Method
965 {  char name[4];                     /* Method name tag */
966    guint32 properties;               /* see definition above */
967    char *description;                /* Fulltext description */
968    char *menuEntry;                  /* Text for use in preferences menu */
969    void (*create)(void);             /* Creates an error correction file */
970    void (*fix)(Image*);              /* Fixes a damaged image */
971    void (*verify)(Image*);           /* Verifies image with ecc data */
972    int  (*recognizeEccFile)(LargeFile*, EccHeader**); /* checks whether we can handle this ecc file */
973    int  (*recognizeEccImage)(Image*); /* checks whether we can handle this augmented image */
974    guint64 (*expectedImageSize)(Image*);/* calculates expected image size (incl. augmented data) */
975    CrcBuf* (*getCrcBuf)(Image*);      /* read and cache CRC info from ecc data */
976    void (*resetCksums)(Image*);       /* Methods for building internal */
977    void (*updateCksums)(Image*, gint64, unsigned char*);/* checksum while reading an image */
978    int  (*finalizeCksums)(Image*);
979    void *ckSumClosure;                                   /* working closure for above */
980    void (*createVerifyWindow)(struct _Method*, GtkWidget*);
981    void (*createCreateWindow)(struct _Method*, GtkWidget*);
982    void (*createFixWindow)(struct _Method*, GtkWidget*);
983    void (*createPrefsPage)(struct _Method*, GtkWidget*);
984    void (*resetVerifyWindow)(struct _Method*);
985    void (*resetCreateWindow)(struct _Method*);
986    void (*resetFixWindow)(struct _Method*);
987    void (*resetPrefsPage)(struct _Method*);
988    void (*readPreferences)(struct _Method*);
989    void (*destroy)(struct _Method*);
990    int  tabWindowIndex;              /* our position in the (invisible) notebook */
991    void *widgetList;                 /* linkage to window system */
992 } Method;
993 
994 void BindMethods(void);        /* created by configure in method-link.c */
995 
996 void CollectMethods(void);
997 void RegisterMethod(Method*);
998 void ListMethods(void);
999 Method* FindMethod(char*);
1000 void CallMethodDestructors(void);
1001 
1002 /***
1003  *** misc.c
1004  ***/
1005 
1006 char* sgettext(char*);
1007 char* sgettext_utf8(char*);
1008 
1009 gint64 uchar_to_gint64(unsigned char*);
1010 void gint64_to_uchar(unsigned char*, gint64);
1011 
1012 void CalcSectors(guint64, guint64*, int*);
1013 
1014 void PrintCLI(char*, ...);
1015 void PrintLog(char*, ...);
1016 void PrintLogWithAsterisks(char*, ...);
1017 void Verbose(char*, ...);
1018 void PrintTimeToLog(GTimer*, char*, ...);
1019 void PrintProgress(char*, ...);
1020 void ClearProgress(void);
1021 void PrintCLIorLabel(GtkLabel*, char*, ...);
1022 int GetLongestTranslation(char*, ...);
1023 
1024 void LogWarning(char*, ...);
1025 void Stop(char*, ...);
1026 void RegisterCleanup(char*, void (*)(gpointer), gpointer);
1027 void UnregisterCleanup(void);
1028 
1029 GThread* CreateGThread(GThreadFunc, gpointer);
1030 
1031 void ShowWidget(GtkWidget*);
1032 void AllowActions(gboolean);
1033 
1034 void ShowMessage(GtkWindow*, char*, GtkMessageType);
1035 GtkWidget* CreateMessage(char*, GtkMessageType, ...);
1036 void SetLabelText(GtkLabel*, char*, ...);
1037 void SetProgress(GtkWidget*, int, int);
1038 
1039 int ModalDialog(GtkMessageType, GtkButtonsType, void (*)(GtkDialog*), char*, ...);
1040 int ModalWarning(GtkMessageType, GtkButtonsType, void (*)(GtkDialog*), char*, ...);
1041 
1042 void SetText(PangoLayout*, char*, int*, int*);
1043 void SwitchAndSetFootline(GtkWidget*, int, GtkWidget*, char*, ...);
1044 
1045 void ReverseCancelOK(GtkDialog*);
1046 void TimedInsensitive(GtkWidget*, int);
1047 
1048 int GetLabelWidth(GtkLabel*, char*, ...);
1049 void LockLabelSize(GtkLabel*, char*, ...);
1050 
1051 int ConfirmImageDeletion(char *);
1052 int ConfirmEccDeletion(char *);
1053 
1054 /***
1055  *** preferences.c
1056  ***/
1057 
1058 void CreatePreferencesWindow(void);
1059 void UpdateMethodPreferences(void);
1060 void HidePreferences(void);
1061 void FreePreferences(void*);
1062 
1063 void UpdatePrefsExhaustiveSearch(void);
1064 void UpdatePrefsConfirmDeletion(void);
1065 void RegisterPreferencesHelpWindow(LabelWithOnlineHelp*);
1066 
1067 /***
1068  *** print-sense.c
1069  ***/
1070 
1071 void RememberSense(int, int, int);
1072 char *GetSenseString(int, int, int, int);
1073 char* GetLastSenseString(int);
1074 void GetLastSense(int*, int*, int*);
1075 
1076 /***
1077  *** random.c
1078  ***/
1079 
1080 #define	MY_RAND_MAX	2147483647
1081 
1082 gint32  Random(void);
1083 void    SRandom(gint32);
1084 guint32 Random32(void);
1085 
1086 /***
1087  *** raw-editor.c
1088  ***/
1089 
1090 void CreateRawEditor(void);
1091 void FreeRawEditorContext(void*);
1092 
1093 
1094 /***
1095  *** raw-sector-cache.c
1096  ***/
1097 
1098 typedef struct _DefectiveSectorHeader
1099 {  unsigned char mediumFP[16];       /* Medium fingerprint */
1100    gint64 lba;                       /* LBA of this sector */
1101    gint32 sectorSize;                /* Sector size in bytes */
1102    gint32 properties;                /* Flags for future use */
1103    gint32 dshFormat;                 /* Format of this file */
1104    gint32 nSectors;                  /* Number of sectors in this file */
1105 } DefectiveSectorHeader;
1106 
1107 enum                                 /* for ->properties above */
1108 {  DSH_HAS_FINGERPRINT = (1<<0),
1109    DSH_XA_MODE         = (1<<1)
1110 };
1111 
1112 int SaveDefectiveSector(struct _RawBuffer*, int);
1113 int TryDefectiveSectorCache(struct _RawBuffer*, unsigned char*);
1114 void ReadDefectiveSectorFile(DefectiveSectorHeader *, struct _RawBuffer*, char*);
1115 
1116 /***
1117  *** read-linear.c
1118  ***/
1119 
1120 void ReadMediumLinear(gpointer);
1121 
1122 /***
1123  *** read-linear-window.c
1124  ***/
1125 
1126 void ResetLinearReadWindow();
1127 void CreateLinearReadWindow(GtkWidget*);
1128 
1129 void InitializeCurve(void*, int, int);
1130 void AddCurveValues(void*, int, int, int);
1131 void MarkExistingSectors(void);
1132 void RedrawReadLinearWindow(void);
1133 
1134 /***
1135  *** read-adaptive.c
1136  ***/
1137 
1138 void GetReadingRange(gint64, gint64*, gint64*);
1139 
1140 void ReadMediumAdaptive(gpointer);
1141 
1142 /***
1143  *** read-adaptive-window.c
1144  ***/
1145 
1146 #define ADAPTIVE_READ_SPIRAL_SIZE 4800
1147 
1148 void ResetAdaptiveReadWindow();
1149 void SetAdaptiveReadMinimumPercentage(int);
1150 void CreateAdaptiveReadWindow(GtkWidget*);
1151 
1152 void ClipReadAdaptiveSpiral(int);
1153 void SetAdaptiveReadSubtitle(char*);
1154 void SetAdaptiveReadFootline(char*, GdkColor*);
1155 void UpdateAdaptiveResults(gint64, gint64, gint64, int);
1156 void ChangeSegmentColor(GdkColor*, int);
1157 void RemoveFillMarkers();
1158 
1159 /***
1160  *** recover-raw.c
1161  ***/
1162 
1163 #define MAX_RAW_TRANSFER_SIZE (2352+296)  /* main channel plus C2 vector and mask */
1164 #define CD_RAW_DUMP_SIZE MAX_RAW_TRANSFER_SIZE
1165 #define CD_RAW_SECTOR_SIZE 2352
1166 #define CD_RAW_C2_SECTOR_SIZE (2352+294)  /* main channel plus C2 vector */
1167 
1168 typedef struct _RawBuffer
1169 {  GaloisTables *gt;          /* for L-EC Reed-Solomon */
1170    ReedSolomonTables *rt;
1171    struct _AlignedBuffer *workBuf; /* working buffer for READ CD */
1172    unsigned char *zeroSector; /* a raw sector containing just zeros. */
1173    unsigned char **rawBuf;    /* buffer for raw read attempts */
1174    int samplesRead;           /* number of samples read */
1175    int samplesMax;            /* maximum number of samples we can store */
1176    int sampleSize;            /* size of samples */
1177    int dataOffset;            /* offset to user data in frame */
1178    int xaMode;                /* frame is in XA21 mode */
1179    int recommendedAttempts;   /* number of retries recommended by reading heuristics */
1180 
1181    unsigned char *recovered;  /* working buffer for cd frame recovery */
1182    unsigned char *byteState;  /* state of error correction */
1183    unsigned char *reference;  /* NULL or the correct sector (for debugging purposes) */
1184    unsigned char *byteCount;  /* stores how many different bytes were read for each position in a sector */
1185    gint64 lba;                /* sector number were currently working on */
1186 
1187    guint8 mediumFP[16];       /* medium fingerprint for raw sector cache validation */
1188    int validFP;               /* indicates valid fingerprint */
1189 
1190    unsigned char *pParity1[N_P_VECTORS];
1191    unsigned char *pParity2[N_P_VECTORS];
1192    int pParityN[N_P_VECTORS][2];
1193 
1194    unsigned char *qParity1[N_Q_VECTORS];
1195    unsigned char *qParity2[N_Q_VECTORS];
1196    int qParityN[N_Q_VECTORS][2];
1197 
1198    int *pLoad,*qLoad;
1199 
1200    /* data structures for the smart_lec */
1201 
1202    unsigned char **pList[N_P_VECTORS];  /* List of accepting P vectors */
1203    int pn[N_P_VECTORS];
1204 
1205    unsigned char **qList[N_Q_VECTORS];  /* List of accepting Q vectors */
1206    int qn[N_Q_VECTORS];
1207 
1208    int bestFrame;                      /* Frame with lowest failures */
1209    int bestP1, bestP2, bestQ1, bestQ2;
1210 
1211 } RawBuffer;
1212 
1213 enum                          /* values for byteState */
1214 {  FRAME_BYTE_UNKNOWN,        /* state of byte is unknown */
1215    FRAME_BYTE_ERROR,          /* byte is wrong (= erasure for ecc) */
1216    FRAME_BYTE_GOOD            /* byte is correct */
1217 };
1218 
1219 RawBuffer* CreateRawBuffer(int);
1220 void ReallocRawBuffer(RawBuffer*, int);
1221 void ResetRawBuffer(RawBuffer*);
1222 void FreeRawBuffer(RawBuffer*);
1223 
1224 void DumpSector(RawBuffer*, char*);
1225 
1226 #define STRICT_MSF_CHECK FALSE
1227 #define SLOPPY_MSF_CHECK TRUE
1228 
1229 int MSFtoLBA(unsigned char, unsigned char, unsigned char);
1230 int CheckEDC(unsigned char*, int);
1231 int CheckMSF(unsigned char*, int, int);
1232 void InitializeCDFrame(unsigned char*, int, int, int);
1233 
1234 void UpdateFrameStats(RawBuffer*);
1235 int ValidateRawSector(RawBuffer*, unsigned char*, char*);
1236 int IterativeLEC(RawBuffer*);
1237 int TryCDFrameRecovery(RawBuffer*, unsigned char*);
1238 
1239 /***
1240  *** scsi-layer.c
1241  ***
1242  * Note that there is also a scsi-layer.h with more
1243  * scsi wrapper dependent declarations.
1244  */
1245 
1246 /* Maximum number of sectors per request */
1247 
1248 #define MAX_CLUSTER_SIZE (32*2048)
1249 #define MAX_CLUSTER_SECTORS 32
1250 
1251 typedef struct _AlignedBuffer
1252 {  unsigned char *base;
1253    unsigned char *buf;
1254 } AlignedBuffer;
1255 
1256 AlignedBuffer *CreateAlignedBuffer(int);
1257 void FreeAlignedBuffer(AlignedBuffer*);
1258 
1259 char* DefaultDevice(void);
1260 gint64 CurrentImageSize(void);
1261 gint64 CurrentImageCapacity(void);
1262 
1263 int SendReadCDB(char*, unsigned char*, unsigned char*, int, int);
1264 
1265 /***
1266  *** scsi-simulated.c
1267  ***/
1268 
1269 void InitSimulatedCD(void);
1270 
1271 /***
1272  *** rs-decoder.c
1273  ***/
1274 
1275 int TestErrorSyndromes(ReedSolomonTables*, unsigned char*);
1276 
1277 /***
1278  *** rs-encoder.c and friends
1279  ***/
1280 
1281 typedef enum
1282 {  ENCODING_ALG_DEFAULT,
1283    ENCODING_ALG_INVALID,
1284    ENCODING_ALG_32BIT,
1285    ENCODING_ALG_64BIT,
1286    ENCODING_ALG_SSE2,
1287    ENCODING_ALG_ALTIVEC
1288 } CODEC_TYPE;
1289 
1290 void EncodeNextLayer(ReedSolomonTables*, unsigned char*, unsigned char*, guint64, int);
1291 void DescribeRSEncoder(char**, char**);
1292 int ProbeSSE2(void);
1293 int ProbeAltiVec(void);
1294 
1295 /***
1296  *** show-manual.c
1297  ***/
1298 
1299 void ShowPDF(char*);
1300 
1301 /***
1302  *** smart-lec.c
1303  ***/
1304 
1305 #define SMART_LEC_MESSAGE_SIZE 256
1306 
1307 void CollectGoodVectors(RawBuffer*);
1308 void PrintPQStats(RawBuffer*);
1309 int SmartLEC(RawBuffer*);
1310 
1311 void *PrepareIterativeSmartLEC(RawBuffer*);
1312 void SmartLECIteration(void*, char*);
1313 void EndIterativeSmartLEC(void*);
1314 
1315 /***
1316  *** spiral.c
1317  ***/
1318 
1319 typedef struct _Spiral
1320 {  GdkDrawable *drawable;
1321    int mx, my;
1322    int startRadius;
1323    int segmentSize;
1324    int segmentCount;
1325    double *segmentPos;
1326    GdkColor **segmentColor;
1327    GdkColor *outline;
1328    int diameter;
1329    int segmentClipping;
1330    int cursorPos;
1331    GdkColor *colorUnderCursor;
1332 } Spiral;
1333 
1334 Spiral* CreateSpiral(GdkColor*, GdkColor*, int, int, int);
1335 void SetSpiralWidget(Spiral*, GtkWidget*);
1336 void FillSpiral(Spiral*, GdkColor*);
1337 void FreeSpiral(Spiral*);
1338 void DrawSpiral(Spiral*);
1339 void DrawSpiralSegment(Spiral*, GdkColor*, int);
1340 void DrawSpiralLabel(Spiral*, PangoLayout*, char*, GdkColor*, int, int);
1341 
1342 void ChangeSpiralCursor(Spiral*, int);
1343 void MoveSpiralCursor(Spiral*, int);
1344 
1345 /***
1346  *** welcome-window.c
1347  ***/
1348 
1349 void CreateWelcomePage(GtkNotebook*);
1350 
1351 #endif				/* DVDISASTER_H */
1352