Files
dvdisaster/dvdisaster.h
2009-11-21 16:29:02 +09:00

1227 lines
37 KiB
C

/* dvdisaster: Additional error correction for optical media.
* Copyright (C) 2004-2009 Carsten Gnoerlich.
* Project home page: http://www.dvdisaster.com
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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.
*/
#ifndef DVDISASTER_H
#define DVDISASTER_H
/* "Dare to be gorgeous and unique.
* But don't ever be cryptic or otherwise unfathomable.
* Make it unforgettably great."
*
* From "A Final Note on Style",
* Amiga Intuition Reference Manual, 1986, p. 231
*/
/***
*** I'm too lazy to mess with #include dependencies.
*** Everything #includeable is rolled up herein...
*/
#define _GNU_SOURCE
//#include <glib.h>
#include <gtk/gtk.h>
#include <glib/gprintf.h>
#include <glib/gstrfuncs.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#ifdef WITH_NLS_YES
#include <libintl.h>
#include <locale.h>
#endif
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef SYS_MINGW
#include <io.h>
#endif
#include "md5.h"
#ifndef G_THREADS_ENABLED
#error "need multithreading glib2"
#endif
/* Phrase extraction for gettext()
Note that these functions are even required when
WITH_NLS_NO is set! */
#define _(string) sgettext(string)
#define _utf(string) sgettext_utf8(string)
/* File permissions for images */
#ifdef SYS_MINGW
#define IMG_PERMS (S_IRUSR | S_IWUSR)
#else
#define IMG_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
#endif
/* Using round() is preferred over rint() on systems which have it */
#ifndef HAVE_ROUND
#define round(x) rint(x)
#endif
/* Some standard media sizes */
#define CDR_SIZE (351*1024)
#define DVD_SL_SIZE 2295104 /* DVD+R/RW size used at least common denominator */
#define DVD_DL_SIZE 4171712 /* also seen: 4148992 4173824 */
#define BD_SL_SIZE 11826176
#define BD_DL_SIZE 23652352
/* Maximum accepted media sizes (in 2K sectors) */
#define MAX_CDR_SIZE (100*60*75) /* CDs can't have >100min w/o severe hacks */
#define MAX_DVD_SL_SIZE 2500000 /* I have to guess here */
#define MAX_DVD_DL_SIZE 4600000 /* I have to guess here */
/* Maximum number of parallel encoder/decoder threads */
#define MAX_CODEC_THREADS 32 /* not including IO and GUI */
/***
*** Our global closure (encapsulation of global variables)
***/
typedef struct _GlobalClosure
{ int version; /* Integer number representing current program version */
char *cookedVersion; /* version string formatted for GUI use */
gint8 releaseFlags; /* flags marking release status */
char *device; /* currently selected device to read from */
GPtrArray *deviceNames; /* List of drive names */
GPtrArray *deviceNodes; /* List of device nodes (C: or /dev/foo) */
char *imageName; /* complete path of current image file */
char *eccName; /* complete path of current ecc file */
GPtrArray *methodList; /* List of available methods */
char *methodName; /* Name of currently selected codec */
gint64 readStart; /* Range to read */
gint64 readEnd;
gint64 cdSize; /* Maximum cd size (for RS02 type images) */
gint64 dvdSize1; /* Maximum 1-layer dvd size (for augmented images) */
gint64 dvdSize2; /* Maximum 2-layer dvd size (for augmented images) */
gint64 bdSize1; /* Maximum 1-layer dvd size (for augmented images) */
gint64 bdSize2; /* Maximum 2-layer dvd size (for augmented images) */
gint64 savedCDSize; /* Undo values for above */
gint64 savedDVDSize1;
gint64 savedDVDSize2;
gint64 savedBDSize1;
gint64 savedBDSize2;
gint64 mediumSize; /* Maximum medium size (for augmented images) */
int cacheMB; /* Cache setting for the parity codec, in megabytes */
int codecThreads; /* Number of threads to use for RS encoders */
int sectorSkip; /* Number of sectors to skip after read error occurs */
char *redundancy; /* Error correction code redundancy */
int readRaw; /* Read CD sectors raw + verify them */
int rawMode; /* mode for mode page */
int minReadAttempts; /* minimum reading attempts */
int maxReadAttempts; /* maximal reading attempts */
int internalAttempts;/* read attempts by the drive itself */
int adaptiveRead; /* Use optimized strategy for reading defective images */
int speedWarning; /* Print warning if speed changes by more than given percentage */
int fillUnreadable; /* Byte value for filling unreadable sectors or -1 */
int spinupDelay; /* Seconds to wait for drive to spin up */
int truncate; /* confirms truncation of large images */
int noTruncate; /* do not truncate image at the end */
int dsmVersion; /* 1 means new style dead sector marker */
int unlinkImage; /* delete image after ecc file creation */
int driveSpeed; /* currently unused */
int debugMode; /* may activate additional features */
int debugCDump; /* dump as #include file instead of hexdump */
int verbose; /* may activate additional messages */
int screenShotMode; /* screen shot mode */
int splitFiles; /* limit image files to 2GB */
int autoSuffix; /* automatically extend files with suffices .iso/.ecc */
int querySize; /* what sources are used for image size queries */
int readAndCreate; /* automatically create .ecc file after reading an image */
int enableCurveSwitch; /* TRUE in readAndCreateMode after reading is complete */
int welcomeMessage; /* just print dvdisaster logo if FALSE */
int dotFileVersion; /* version of dotfile */
int simulateDefects; /* if >0, this is the percentage of simulated media defects */
int defectiveDump; /* dump non-recoverable sectors into given path */
char *dDumpDir; /* directory for above */
char *dDumpPrefix; /* file name prefix for above */
int reverseCancelOK; /* if TRUE the button order is reversed */
int eject; /* eject medium on success */
int readingPasses; /* try to read medium n times */
int pauseAfter; /* pause after given amount of minutes */
int pauseDuration; /* duration of pause in minutes */
int pauseEject; /* Eject medium during pause */
int ignoreFatalSense;/* Continue reading after potential fatal sense errors */
int useSSE2; /* TRUE means to use SSE2 version of the codec. */
int useSGioctl; /* Use the generic SCSI ioctl instead of CDROM one on Liux */
char *homeDir; /* path to users home dir */
char *dotFile; /* path to .dvdisaster file */
char *logFile; /* path to logfile */
int logFileEnabled; /* logfile enabled */
int logFileStamped; /* time stamp written to log file */
char *binDir; /* place where the binary resides */
char *docDir; /* place where our documentation resides */
char *appData; /* Windows specific */
char *browser; /* Name of preferred WEB browser */
char bs[256]; /* A string of 255 backspace characters */
GThread *mainThread; /* Thread of the main() routine */
void (*cleanupProc)(gpointer); /* Procedure to cleanup running threads after an error condition */
gpointer cleanupData;
char *errorTitle; /* Title to show in error dialogs */
gint32 randomSeed; /* for the random number generator */
#ifdef SYS_MINGW
/*** Hooks into the ASPI library */
void *aspiLib;
unsigned long (*GetASPI32SupportInfo)(void);
unsigned long (*SendASPI32Command)(void*);
#endif
guint32 *crcCache; /* sectorwise CRC32 for last image read */
char *crcImageName; /* file name of cached image */
unsigned char md5Cache[16]; /* md5sum of last image read */
/*** GUI-related things */
int guiMode; /* TRUE if GUI is active */
int stopActions; /* crude method to stop ongoing action(s) */
int noMissingWarnings; /* suppress warnings about inconsistent missing sectors */
GtkWidget *logWidget; /* Dialog for the log display */
GtkScrolledWindow *logScroll; /* and its scrolled window */
GtkTextBuffer *logBuffer; /* Text buffer for the log output */
GString *logString; /* holds logging output for current action */
GMutex *logLock; /* protects the logString */
/*** Widgets of the main window */
GtkWindow *window; /* main window */
GtkTooltips *tooltips; /* our global tooltips structure */
GdkPixbuf *windowIcon; /* main window icon */
GtkWidget *driveCombo; /* combo box for drive selection */
GtkWidget *imageFileSel; /* image file selector */
GtkWidget *imageEntry; /* image name entry field */
GtkWidget *eccFileSel; /* ecc file selector */
GtkWidget *eccEntry; /* ecc name entry field */
GtkWidget *notebook; /* The notebook behind our central output area */
GtkLabel *status; /* The status label */
GtkWidget *prefsButton;
GtkWidget *helpButton;
GtkWidget *readButton;
GtkWidget *createButton;
GtkWidget *scanButton;
GtkWidget *fixButton;
GtkWidget *testButton;
/*** The preferences window */
GtkWindow *prefsWindow;
void *prefsContext; /* local data for the preferences window */
/*** The raw editor window */
void *rawEditorContext;
/*** The medium info window */
GtkWidget *mediumWindow; /* Dialog for the medium info window */
GtkWidget *mediumDrive;
void *mediumInfoContext; /* private data */
/*** Common stuff for drawing curves and spirals */
GdkGC *drawGC;
GdkColor *background,*foreground,*grid;
GdkColor *redText;
char *redMarkup;
GdkColor *greenText;
char *greenMarkup;
GdkColor *barColor;
GdkColor *logColor;
GdkColor *curveColor;
GdkColor *redSector;
GdkColor *yellowSector;
GdkColor *greenSector;
GdkColor *blueSector;
GdkColor *whiteSector;
GdkColor *darkSector;
char *invisibleDash;
/*** Widgets for the linear reading/scanning action */
GtkWidget *readLinearHeadline;
GtkWidget *readLinearDrawingArea;
struct _Curve *readLinearCurve;
struct _Spiral *readLinearSpiral;
GtkWidget *readLinearNotebook;
GtkWidget *readLinearSpeed;
GtkWidget *readLinearErrors;
GtkWidget *readLinearFootline;
GtkWidget *readLinearFootlineBox;
gint64 crcErrors, readErrors; /* these are passed between threads and must therefore be global */
int eccType; /* type of ecc data provided while reading/scanning */
/*** Widgets for the adaptive reading action */
GtkWidget *readAdaptiveHeadline;
GtkWidget *readAdaptiveDrawingArea;
struct _Spiral *readAdaptiveSpiral;
char *readAdaptiveSubtitle;
char *readAdaptiveErrorMsg;
int additionalSpiralColor;
} GlobalClosure;
extern GlobalClosure *Closure; /* these should be the only global variables! */
extern int exitCode; /* value to use on exit() */
/***
***
***/
#define MAX_FILE_SEGMENTS 100
typedef struct _LargeFile
{ int fileSegment[MAX_FILE_SEGMENTS];
int flags;
mode_t mode;
int segment;
gint64 offset;
char *basename;
char *suffix;
int namelen;
gint64 size;
} LargeFile;
/***
*** An info package about a medium image
*** (NOT part or a header of the image file!)
*/
typedef struct _ImageInfo
{ LargeFile *file; /* file handle for image */
gint64 size; /* number of medium bytes */
gint64 sectors; /* number of medium sectors */
gint64 sectorsMissing; /* number of missing medium sectors */
gint64 crcErrors; /* sectors with CRC32 errors */
int inLast; /* bytes in last sector */
unsigned char mediumFP[16]; /* md5sum of first sector */
int fpValid; /* TRUE if above is a valid md5sum */
unsigned char mediumSum[16]; /* complete md5sum of whole medium */
} ImageInfo;
/***
*** An info package about a error correction file
*** (NOT part or a header of the ecc file!)
*/
typedef struct _EccInfo
{ LargeFile *file; /* file handle for ecc file */
struct _EccHeader *eh; /* the header struct below */
gint64 sectors; /* gint64 version of eh->sectors */
struct MD5Context md5Ctxt; /* md5 context of crc portion of file */
} EccInfo;
/***
*** The .ecc file header
***/
#define FINGERPRINT_SECTOR 16 /* Sector currently used to calculate the fingerprint. */
/* This is the ISO filesystem root sector which contains */
/* the volume label and creation time stamps. */
/* Versions upto 0.64 used sector 257, */
/* but that was not a wise choice for CD media.*/
#define MFLAG_DEVEL (1<<0) /* for methodFlags[3] */
#define MFLAG_RC (1<<1)
#define MFLAG_DATA_MD5 (1<<0) /* specific to RS03 */
typedef struct _EccHeader
{ gint8 cookie[12]; /* "*dvdisaster*" */
gint8 method[4]; /* e.g. "RS01" */
gint8 methodFlags[4]; /* 0-2 for free use by the respective methods; 3 see above */
guint8 mediumFP[16]; /* fingerprint of FINGERPRINT SECTOR */
guint8 mediumSum[16]; /* complete md5sum of whole medium */
guint8 eccSum[16]; /* md5sum of ecc code section of .ecc file */
guint8 sectors[8]; /* number of sectors medium is supposed to have */
gint32 dataBytes; /* data bytes per ecc block */
gint32 eccBytes; /* ecc bytes per ecc block */
gint32 creatorVersion; /* which dvdisaster version created this */
gint32 neededVersion; /* oldest version which can decode this file */
gint32 fpSector; /* sector used to calculate mediumFP */
guint32 selfCRC; /* CRC32 of EccHeader (currently RS02 only) -- since V0.66 --*/
guint8 crcSum[16]; /* md5sum of crc code section of RS02 .iso file */
gint32 inLast; /* bytes contained in last sector */
gint8 padding[3976]; /* pad to 4096 bytes: room for future expansion */
/* Note: Bytes 2048 and up are currently used by the RS02/RS03 codec
for a copy of the first ecc blocks CRC sums. */
} EccHeader;
/***
*** forward declarations
***/
struct _RawBuffer *rawbuffer_forward;
struct _DefectiveSectorHeader *dsh_forward;
/***
*** dvdisaster.c
***/
void CreateEcc(void);
void FixEcc(void);
void Verify(void);
/***
*** bitmap.c
***/
typedef struct _Bitmap
{ guint32 *bitmap;
gint32 size;
gint32 words;
} Bitmap;
Bitmap* CreateBitmap0(int);
#define GetBit(bm,bit) (bm->bitmap[(bit)>>5] & (1<<((bit)&31)))
#define SetBit(bm,bit) bm->bitmap[(bit)>>5] |= (1<<((bit)&31))
#define ClearBit(bm,bit) bm->bitmap[(bit)>>5] &= ~(1<<((bit)&31))
int CountBits(Bitmap*);
void FreeBitmap(Bitmap*);
/***
*** build.h
***/
int buildCount;
/***
*** closure.c
***/
void InitClosure(void);
void LocalizedFileDefaults(void);
void UpdateMarkup(char**, GdkColor*);
void DefaultColors(void);
void ClearCrcCache(void);
void FreeClosure(void);
void ReadDotfile(void);
void WriteSignature(void);
int VerifySignature(void);
/***
*** crc32.c
***/
guint32 Crc32(unsigned char*, int);
guint32 EDCCrc32(unsigned char*, int);
/***
*** crcbuf.c
***/
typedef struct _CrcBuf
{ guint32 *crcbuf;
gint64 size;
Bitmap *valid;
} CrcBuf;
enum
{ CRC_UNKNOWN,
CRC_BAD,
CRC_GOOD
};
CrcBuf *GetCRCFromRS01(EccInfo*);
CrcBuf *GetCRCFromRS02(void*, void*, LargeFile*);
void FreeCrcBuf(CrcBuf*);
int CheckAgainstCrcBuffer(CrcBuf*, gint64, unsigned char*);
/***
*** curve.c
***/
enum
{ CURVE_PERCENT,
CURVE_MEGABYTES
};
typedef struct _Curve
{ GtkWidget *widget; /* drawing area which is hosting us */
PangoLayout *layout;
gdouble *fvalue; /* floating point curve values */
gint *ivalue; /* integer bar curve values */
gint *lvalue; /* logarithmic integer curve */
gint enable; /* which of the above should be drawn */
gint lastValueIdx; /* end of value array */
gint leftX,rightX; /* Position of left and right y axis */
gint topY,bottomY; /* Top and bottom end of i/f y axes */
gint topLY,bottomLY; /* Top and bottom end of l y axes */
char *leftLabel; /* Label of left coordinate axis */
char *leftLogLabel; /* Label of left log coordinate axis */
char *leftFormat; /* Format of left coordinate axis numbering */
int bottomFormat; /* what kind of data are we displaying? */
int margin;
int maxX,maxY,logMaxY; /* current max value at y axis */
} Curve;
#define DRAW_ICURVE (1<<0)
#define DRAW_FCURVE (1<<1)
#define DRAW_LCURVE (1<<2)
Curve* CreateCurve(GtkWidget*, char*, char*, int, int);
void ZeroCurve(Curve*);
void FreeCurve(Curve*);
void UpdateCurveGeometry(Curve*, char*, int);
int CurveX(Curve*, gdouble);
int CurveY(Curve*, gdouble);
int CurveLogY(Curve*, gdouble);
void RedrawAxes(Curve*);
void RedrawCurve(Curve*, int);
/***
*** debug.c
***/
void HexDump(unsigned char*, int, int);
void CopySector(char*);
void Byteset(char*);
void Erase(char*);
void MergeImages(char*, int);
void RandomError(char*, char*);
void RandomImage(char*, char*, int);
void RawSector(char*);
void ReadSector(char*);
void SendCDB(char*);
void ShowSector(char*);
Bitmap* SimulateDefects(gint64);
void TruncateImage(char*);
void ZeroUnreadable(void);
/***
*** ds-marker.c
***/
enum
{ SECTOR_PRESENT,
SECTOR_MISSING,
SECTOR_MISSING_DISPLACED,
SECTOR_MISSING_WRONG_FP
};
void CreateMissingSector(unsigned char*, gint64, unsigned char*, gint64, char*);
int CheckForMissingSector(unsigned char*, gint64, unsigned char*, gint64);
void ExplainMissingSector(unsigned char*, gint64, int, int);
/***
*** endian.c
***/
guint32 SwapBytes32(guint32);
guint64 SwapBytes64(guint64);
void SwapEccHeaderBytes(EccHeader*);
void SwapDefectiveHeaderBytes(struct _DefectiveSectorHeader*);
/***
*** file.c
***/
#define READABLE_IMAGE 0
#define READABLE_ECC 0
#define WRITEABLE_IMAGE (1<<0)
#define WRITEABLE_ECC (1<<1)
#define PRINT_MODE (1<<4)
#define CREATE_CRC ((1<<1) | (1<<5))
ImageInfo* OpenImageFile(EccHeader*, int);
EccInfo* OpenEccFile(int);
EccInfo* OpenEccFileOld(int);
void FreeImageInfo(ImageInfo*);
void FreeEccInfo(EccInfo*);
char *ApplyAutoSuffix(char*, char*);
int VerifyVersion(EccHeader*, int fatal);
void UnlinkImage(GtkWidget*);
/***
*** fix-window.c
***/
void CreateFixWindow(GtkWidget*);
/***
*** galois.c
***
* This is currently the hardcoded GF(2**8).
* gint32 gives abundant space for the GF.
* Squeezing it down to guint8 won't probably gain much,
* so we implement this defensively here.
*
* Note that some performance critical stuff needs to
* be #included from galois-inlines.h
*/
/* Galois field parameters for 8bit symbol Reed-Solomon code */
#define GF_SYMBOLSIZE 8
#define GF_FIELDSIZE (1<<GF_SYMBOLSIZE)
#define GF_FIELDMAX (GF_FIELDSIZE-1)
#define GF_ALPHA0 GF_FIELDMAX
/* RS polynomial parameters for RS01/RS02 codec */
#define RS_GENERATOR_POLY 0x187 /* 1 + X + X**2 + X**7 + X**8 */
#define RS_FIRST_ROOT 112 /* same choices as in CCSDS */
#define RS_PRIM_ELEM 11
#define RS_PRIMTH_ROOT 116 /* prim-th root of 1 */
/* Lookup tables for Galois field arithmetic */
typedef struct _GaloisTables
{ gint32 gfGenerator; /* GF generator polynomial */
gint32 *indexOf; /* log */
gint32 *alphaTo; /* inverse log */
gint32 *encAlphaTo; /* inverse log optimized for encoder */
} GaloisTables;
/* Lookup and working tables for the ReedSolomon codecs */
typedef struct _ReedSolomonTables
{ GaloisTables *gfTables;/* from above */
gint32 *gpoly; /* RS code generator polynomial */
gint32 fcr; /* first consecutive root of RS generator polynomial */
gint32 primElem; /* primitive field element */
gint32 nroots; /* degree of RS generator polynomial */
gint32 ndata; /* data bytes per ecc block */
gint32 shiftInit; /* starting value for iteratively processing parity */
guint8 *bLut[GF_FIELDSIZE]; /* experimental 8bit lookup table */
} ReedSolomonTables;
GaloisTables* CreateGaloisTables(gint32);
void FreeGaloisTables(GaloisTables*);
ReedSolomonTables *CreateReedSolomonTables(GaloisTables*, gint32, gint32, int);
void FreeReedSolomonTables(ReedSolomonTables*);
/***
*** help-dialogs.c
***/
/* Creating labels with links to online help */
typedef struct _LabelWithOnlineHelp
{ GtkWidget *helpWindow;
GtkWidget *normalLabel;
GtkWidget *linkBox;
GtkWidget *linkLabel;
GtkWidget *vbox;
GPtrArray *lastSizes; /* for breaking expose loops between the help windows */
char *windowTitle;
char *normalText;
char *highlitText;
int inside;
int outerPadding; /* Padding between window and outer vbox */
} LabelWithOnlineHelp;
LabelWithOnlineHelp* CreateLabelWithOnlineHelp(char*, char*);
LabelWithOnlineHelp* CloneLabelWithOnlineHelp(LabelWithOnlineHelp*, char*);
void FreeLabelWithOnlineHelp(LabelWithOnlineHelp*);
void SetOnlineHelpLinkText(LabelWithOnlineHelp*, char*);
void AddHelpListItem(LabelWithOnlineHelp*, char*, ...);
void AddHelpParagraph(LabelWithOnlineHelp*, char*, ...);
void AddHelpWidget(LabelWithOnlineHelp*, GtkWidget*);
/* Specific online help dialogs */
GtkWidget* ShowTextfile(char*, char*, char*, GtkScrolledWindow**, GtkTextBuffer**);
void ShowGPL();
void ShowLog();
void UpdateLog();
void AboutDialog();
void AboutText(GtkWidget*, char*, ...);
void AboutLink(GtkWidget*, char*, char*);
void AboutTextWithLink(GtkWidget*, char*, char*);
/***
*** heuristic-lec.c
***/
void UpdateByteCounts(struct _RawBuffer*);
void CalculatePQLoad(struct _RawBuffer*);
void UpdatePQParityList(struct _RawBuffer*, unsigned char*);
int HeuristicLEC(unsigned char*, struct _RawBuffer*, unsigned char*);
int SearchPlausibleSector(struct _RawBuffer*, int);
int BruteForceSearchPlausibleSector(struct _RawBuffer*);
int AckHeuristic(struct _RawBuffer*);
/***
*** icon-factory.c
***/
void CreateIconFactory();
/***
*** large-io.c
***/
LargeFile *LargeOpen(char*, int, mode_t);
int LargeSeek(LargeFile*, gint64);
int LargeEOF(LargeFile*);
ssize_t LargeRead(LargeFile*, void*, size_t);
ssize_t LargeWrite(LargeFile*, void*, size_t);
int LargeClose(LargeFile*);
int LargeTruncate(LargeFile*, gint64);
int LargeStat(char*, gint64*);
int LargeUnlink(char*);
int DirStat(char*);
FILE *portable_fopen(char*, char*);
int portable_mkdir(char*);
/***
*** l-ec.c
***/
#define N_P_VECTORS 86 /* 43 16bit p vectors */
#define P_VECTOR_SIZE 26 /* using RS(26,24) ECC */
#define N_Q_VECTORS 52 /* 26 16bit q vectors */
#define Q_VECTOR_SIZE 45 /* using RS(45,43) ECC */
#define P_PADDING 229 /* padding values for */
#define Q_PADDING 210 /* shortened RS code */
int PToByteIndex(int, int);
int QToByteIndex(int, int);
void ByteIndexToP(int, int*, int*);
void ByteIndexToQ(int, int*, int*);
void PrintVector(unsigned char*, int, int);
void GetPVector(unsigned char*, unsigned char*, int);
void SetPVector(unsigned char*, unsigned char*, int);
void FillPVector(unsigned char*, unsigned char, int);
void AndPVector(unsigned char*, unsigned char, int);
void OrPVector(unsigned char*, unsigned char, int);
void GetQVector(unsigned char*, unsigned char*, int);
void SetQVector(unsigned char*, unsigned char*, int);
void FillQVector(unsigned char*, unsigned char, int);
void AndQVector(unsigned char*, unsigned char, int);
void OrQVector(unsigned char*, unsigned char, int);
int DecodePQ(ReedSolomonTables*, unsigned char*, int, int*, int);
int CountC2Errors(unsigned char*);
/***
*** logfile.c
***/
void DefaultLogFile();
void VPrintLogFile(char*, va_list);
void PrintLogFile(char*, ...);
/***
*** maintenance.c
***
*
* Provides a context for running testing functions
* within the usual program context.
* Only for debugging / development purposes.
*/
void Maintenance1(char*);
/***
*** main-window.c
***/
#define FIRST_CREATE_WINDOW 3
typedef enum
{ ACTION_WELCOME, /* Tab 0; not really an action */
ACTION_STOP, /* ---- does not have a window */
ACTION_READ, /* Tab 1 (linear); Tab 2 (adaptive)*/
ACTION_SCAN, /* Tab 1 (linear); Tab 2 (adaptive)*/
ACTION_VERIFY, /* VERIFY, CREATE and FIX have separate windows assigned */
ACTION_CREATE, /* for each method. */
ACTION_CREATE_CONT,
ACTION_FIX
} MajorActions;
void CreateMainWindow(int*, char***);
void ContinueWithAction(int);
/***
*** medium-info.c
***/
void CreateMediumInfoWindow(void);
/***
*** memtrack.c
***/
/*
* Macro replacements for the glib functions.
*/
#ifdef WITH_MEMDEBUG_YES
#define g_malloc(size) malloc_ext(size,__FILE__,__LINE__)
#define g_malloc0(size) malloc_ext(size,__FILE__,__LINE__)
#define g_realloc(ptr,size) realloc_ext(ptr,size,__FILE__,__LINE__)
#define g_strdup(str) strdup_ext(str,__FILE__,__LINE__)
#define g_try_malloc(size) try_malloc_ext(size,__FILE__,__LINE__)
#define g_strdup_printf(format,args...) \
strdup_printf_ext(format,__FILE__,__LINE__, ## args)
#define g_strdup_vprintf(format,argp) \
strdup_vprintf_ext(format,argp,__FILE__,__LINE__)
#define g_locale_to_utf8(str,size,in,out,gerr) \
g_locale_to_utf8_ext(str,size,in,out,gerr,__FILE__,__LINE__)
#define g_free(size) free_ext(size,__FILE__,__LINE__)
#define REMEMBER(ptr) remember(ptr, 0, __FILE__, __LINE__)
#define FORGET(ptr) forget(ptr)
#else
#define REMEMBER(ptr)
#define FORGET(ptr)
#endif
/*
* Protos for the replacement functions.
*/
void* malloc_ext(int,char*,int);
void* realloc_ext(void*, int, char*, int);
void* try_malloc_ext(int,char*,int);
char* strdup_ext(const char*,char*,int);
char* strdup_printf_ext(char*, char*, int, ...);
char* strdup_vprintf_ext(char*, va_list, char*, int);
gchar* g_locale_to_utf8_ext(const gchar*, gssize, gsize*, gsize*, GError**, char*, int);
void free_ext(void*,char*,int);
void remember(void*, int, char*, int);
int forget(void*);
void check_memleaks(void);
/***
*** menubar.c
***/
void AttachTooltip(GtkWidget*, char*, char*);
GtkWidget* CreateMenuBar(GtkWidget*);
GtkWidget* CreateToolBar(GtkWidget*);
/***
*** method.c / method-link.c
***
* method-link.c is automatically created by the configure script.
*/
typedef struct _Method
{ char name[4]; /* Method name tag */
char *description; /* Fulltext description */
char *menuEntry; /* Text for use in preferences menu */
void (*create)(struct _Method*); /* Creates an error correction file */
void (*fix)(struct _Method*); /* Fixes a damaged image */
void (*verify)(struct _Method*); /* Verifies image with ecc data */
void (*createVerifyWindow)(struct _Method*, GtkWidget*);
void (*createCreateWindow)(struct _Method*, GtkWidget*);
void (*createFixWindow)(struct _Method*, GtkWidget*);
void (*createPrefsPage)(struct _Method*, GtkWidget*);
void (*resetVerifyWindow)(struct _Method*);
void (*resetCreateWindow)(struct _Method*);
void (*resetFixWindow)(struct _Method*);
void (*resetPrefsPage)(struct _Method*);
void (*readPreferences)(struct _Method*);
void (*destroy)(struct _Method*);
int tabWindowIndex; /* our position in the (invisible) notebook */
void *widgetList; /* linkage to window system */
EccHeader *lastEh; /* copy of EccHeader from last EccFileMethod() call */
} Method;
void BindMethods(void); /* created by configure in method-link.c */
void CollectMethods(void);
void RegisterMethod(Method*);
void ListMethods(void);
Method* FindMethod(char*);
EccHeader* FindHeaderInImage(char*);
Method *EccFileMethod(int);
void CallMethodDestructors(void);
/***
*** misc.c
***/
char* sgettext(char*);
char* sgettext_utf8(char*);
gint64 uchar_to_gint64(unsigned char*);
void gint64_to_uchar(unsigned char*, gint64);
void CalcSectors(gint64, gint64*, int*);
void PrintCLI(char*, ...);
void PrintLog(char*, ...);
void Verbose(char*, ...);
void PrintTimeToLog(GTimer*, char*, ...);
void PrintProgress(char*, ...);
void PrintCLIorLabel(GtkLabel*, char*, ...);
void LogWarning(char*, ...);
void Stop(char*, ...);
void RegisterCleanup(char*, void (*)(gpointer), gpointer);
GThread* CreateGThread(GThreadFunc, gpointer);
void ShowWidget(GtkWidget*);
void AllowActions(gboolean);
void ShowMessage(GtkWindow*, char*, GtkMessageType);
GtkWidget* CreateMessage(char*, GtkMessageType, ...);
void SetLabelText(GtkLabel*, char*, ...);
void SetProgress(GtkWidget*, int, int);
int ModalDialog(GtkMessageType, GtkButtonsType, void (*)(GtkDialog*), char*, ...);
int ModalWarning(GtkMessageType, GtkButtonsType, void (*)(GtkDialog*), char*, ...);
void SetText(PangoLayout*, char*, int*, int*);
void SwitchAndSetFootline(GtkWidget*, int, GtkWidget*, char*, ...);
void ReverseCancelOK(GtkDialog*);
void TimedInsensitive(GtkWidget*, int);
int GetLabelWidth(GtkLabel*, char*, ...);
void LockLabelSize(GtkLabel*, char*, ...);
/***
*** preferences.c
***/
void CreatePreferencesWindow(void);
void UpdateMethodPreferences(void);
void HidePreferences(void);
void FreePreferences(void*);
void UpdatePrefsQuerySize(void);
void RegisterPreferencesHelpWindow(LabelWithOnlineHelp*);
/***
*** print-sense.c
***/
void RememberSense(int, int, int);
char *GetSenseString(int, int, int, int);
char* GetLastSenseString(int);
void GetLastSense(int*, int*, int*);
/***
*** random.c
***/
#define MY_RAND_MAX 2147483647
gint32 Random(void);
void SRandom(gint32);
guint32 Random32(void);
/***
*** raw-editor.c
***/
void CreateRawEditor(void);
void FreeRawEditorContext(void*);
/***
*** raw-sector-cache.c
***/
typedef struct _DefectiveSectorHeader
{ unsigned char mediumFP[16]; /* Medium fingerprint */
gint64 lba; /* LBA of this sector */
gint32 sectorSize; /* Sector size in bytes */
gint32 properties; /* Flags for future use */
gint32 dshFormat; /* Format of this file */
gint32 nSectors; /* Number of sectors in this file */
} DefectiveSectorHeader;
enum /* for ->properties above */
{ DSH_HAS_FINGERPRINT = (1<<0),
DSH_XA_MODE = (1<<1)
};
int SaveDefectiveSector(struct _RawBuffer*, int);
int TryDefectiveSectorCache(struct _RawBuffer*, unsigned char*);
void ReadDefectiveSectorFile(DefectiveSectorHeader *, struct _RawBuffer*, char*);
/***
*** read-linear.c
***/
enum
{ ECC_NONE, ECC_RS01, ECC_RS02
};
void ReadMediumLinear(gpointer);
/***
*** read-linear-window.c
***/
void ResetLinearReadWindow();
void CreateLinearReadWindow(GtkWidget*);
void InitializeCurve(void*, int, int);
void AddCurveValues(void*, int, int, int);
void MarkExistingSectors(void);
/***
*** read-adaptive.c
***/
void GetReadingRange(gint64, gint64*, gint64*);
void ReadMediumAdaptive(gpointer);
/***
*** read-adaptive-window.c
***/
#define ADAPTIVE_READ_SPIRAL_SIZE 4800
void ResetAdaptiveReadWindow();
void SetAdaptiveReadMinimumPercentage(int);
void CreateAdaptiveReadWindow(GtkWidget*);
void ClipReadAdaptiveSpiral(int);
void SetAdaptiveReadSubtitle(char*);
void SetAdaptiveReadFootline(char*, GdkColor*);
void UpdateAdaptiveResults(gint64, gint64, gint64, int);
void ChangeSegmentColor(GdkColor*, int);
void RemoveFillMarkers();
/***
*** recover-raw.c
***/
#define MAX_RAW_TRANSFER_SIZE (2352+296) /* main channel plus C2 vector and mask */
#define CD_RAW_DUMP_SIZE MAX_RAW_TRANSFER_SIZE
#define CD_RAW_SECTOR_SIZE 2352
#define CD_RAW_C2_SECTOR_SIZE (2352+294) /* main channel plus C2 vector */
typedef struct _RawBuffer
{ GaloisTables *gt; /* for L-EC Reed-Solomon */
ReedSolomonTables *rt;
struct _AlignedBuffer *workBuf; /* working buffer for READ CD */
unsigned char *zeroSector; /* a raw sector containing just zeros. */
unsigned char **rawBuf; /* buffer for raw read attempts */
int samplesRead; /* number of samples read */
int samplesMax; /* maximum number of samples we can store */
int sampleSize; /* size of samples */
int dataOffset; /* offset to user data in frame */
int xaMode; /* frame is in XA21 mode */
int recommendedAttempts; /* number of retries recommended by reading heuristics */
unsigned char *recovered; /* working buffer for cd frame recovery */
unsigned char *byteState; /* state of error correction */
unsigned char *reference; /* NULL or the correct sector (for debugging purposes) */
unsigned char *byteCount; /* stores how many different bytes were read for each position in a sector */
gint64 lba; /* sector number were currently working on */
guint8 mediumFP[16]; /* medium fingerprint for raw sector cache validation */
int validFP; /* indicates valid fingerprint */
unsigned char *pParity1[N_P_VECTORS];
unsigned char *pParity2[N_P_VECTORS];
int pParityN[N_P_VECTORS][2];
unsigned char *qParity1[N_Q_VECTORS];
unsigned char *qParity2[N_Q_VECTORS];
int qParityN[N_Q_VECTORS][2];
int *pLoad,*qLoad;
/* data structures for the smart_lec */
unsigned char **pList[N_P_VECTORS]; /* List of accepting P vectors */
int pn[N_P_VECTORS];
unsigned char **qList[N_Q_VECTORS]; /* List of accepting Q vectors */
int qn[N_Q_VECTORS];
int bestFrame; /* Frame with lowest failures */
int bestP1, bestP2, bestQ1, bestQ2;
} RawBuffer;
enum /* values for byteState */
{ FRAME_BYTE_UNKNOWN, /* state of byte is unknown */
FRAME_BYTE_ERROR, /* byte is wrong (= erasure for ecc) */
FRAME_BYTE_GOOD /* byte is correct */
};
RawBuffer* CreateRawBuffer(int);
void ReallocRawBuffer(RawBuffer*, int);
void ResetRawBuffer(RawBuffer*);
void FreeRawBuffer(RawBuffer*);
void DumpSector(RawBuffer*, char*);
#define STRICT_MSF_CHECK FALSE
#define SLOPPY_MSF_CHECK TRUE
int MSFtoLBA(unsigned char, unsigned char, unsigned char);
int CheckEDC(unsigned char*, int);
int CheckMSF(unsigned char*, int, int);
void InitializeCDFrame(unsigned char*, int, int, int);
void UpdateFrameStats(RawBuffer*);
int ValidateRawSector(RawBuffer*, unsigned char*, char*);
int IterativeLEC(RawBuffer*);
int TryCDFrameRecovery(RawBuffer*, unsigned char*);
/***
*** scsi-layer.c
***
* Note that there is also a scsi-layer.h with more
* scsi wrapper dependent declarations.
*/
/* Maximum number of sectors per request */
#define MAX_CLUSTER_SIZE (32*2048)
#define MAX_CLUSTER_SECTORS 32
typedef struct _AlignedBuffer
{ unsigned char *base;
unsigned char *buf;
} AlignedBuffer;
AlignedBuffer *CreateAlignedBuffer(int);
void FreeAlignedBuffer(AlignedBuffer*);
void OpenAspi(void);
void CloseAspi(void);
void ListAspiDrives(void);
char* DefaultDevice(void);
gint64 CurrentImageSize(void);
gint64 CurrentImageCapacity(void);
int SendReadCDB(char*, unsigned char*, unsigned char*, int, int);
/***
*** rs-encoder.c and friends
***/
void EncodeNextLayer(ReedSolomonTables*, unsigned char*, unsigned char*, guint64, int);
int ProbeSSE2(void);
/***
*** show-manual.c
***/
void ShowHTML(char*);
/***
*** smart-lec.c
***/
#define SMART_LEC_MESSAGE_SIZE 256
void CollectGoodVectors(RawBuffer*);
void PrintPQStats(RawBuffer*);
int SmartLEC(RawBuffer*);
void *PrepareIterativeSmartLEC(RawBuffer*);
void SmartLECIteration(void*, char*);
void EndIterativeSmartLEC(void*);
/***
*** spiral.c
***/
typedef struct _Spiral
{ GdkDrawable *drawable;
int mx, my;
int startRadius;
int segmentSize;
int segmentCount;
double *segmentPos;
GdkColor **segmentColor;
GdkColor *outline;
int diameter;
int segmentClipping;
int cursorPos;
GdkColor *colorUnderCursor;
} Spiral;
Spiral* CreateSpiral(GdkColor*, GdkColor*, int, int, int);
void SetSpiralWidget(Spiral*, GtkWidget*);
void FillSpiral(Spiral*, GdkColor*);
void FreeSpiral(Spiral*);
void DrawSpiral(Spiral*);
void DrawSpiralSegment(Spiral*, GdkColor*, int);
void DrawSpiralLabel(Spiral*, PangoLayout*, char*, GdkColor*, int, int);
void ChangeSpiralCursor(Spiral*, int);
void MoveSpiralCursor(Spiral*, int);
/***
*** welcome-window.c
***/
void CreateWelcomePage(GtkNotebook*);
#endif /* DVDISASTER_H */