Imported Upstream version 0.72
This commit is contained in:
977
dvdisaster.c
Normal file
977
dvdisaster.c
Normal file
@@ -0,0 +1,977 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#include "dvdisaster.h"
|
||||
|
||||
#ifdef SYS_MINGW
|
||||
#include <windows.h>
|
||||
#include <winnls.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create the error correction file
|
||||
*/
|
||||
|
||||
void CreateEcc(void)
|
||||
{ Method *method = FindMethod(Closure->methodName);
|
||||
|
||||
/*** GUI mode does its own FindMethod() before calling us
|
||||
so the following Stop() will never execute in GUI mode */
|
||||
|
||||
if(!method) Stop(_("\nMethod %s not available.\n"
|
||||
"Use -m without parameters for a method list.\n"),
|
||||
Closure->methodName);
|
||||
|
||||
method->create(method);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix the medium with ecc information
|
||||
*/
|
||||
|
||||
void FixEcc(void)
|
||||
{ Method *method;
|
||||
|
||||
/* Error handling is done within EccFileMethod() */
|
||||
|
||||
method = EccFileMethod(TRUE);
|
||||
|
||||
/* Dispatch to the proper method */
|
||||
|
||||
method->fix(method);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verfiy the image against ecc data
|
||||
*/
|
||||
|
||||
void Verify(void)
|
||||
{ Method *method;
|
||||
|
||||
/* If something is wrong with the .iso or .ecc files
|
||||
we fall back to the RS01 method for comparing
|
||||
since it is robust against missing files. */
|
||||
|
||||
if(!(method = EccFileMethod(FALSE)))
|
||||
if(!(method = FindMethod("RS01")))
|
||||
Stop(_("RS01 method not available for comparing files."));
|
||||
|
||||
/* Dispatch to the proper method */
|
||||
|
||||
method->verify(method);
|
||||
}
|
||||
|
||||
/*
|
||||
* The all-famous main() loop
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{ MODE_NONE,
|
||||
|
||||
MODE_CREATE,
|
||||
MODE_HELP,
|
||||
MODE_FIX,
|
||||
MODE_VERIFY,
|
||||
MODE_READ,
|
||||
MODE_SCAN,
|
||||
MODE_SEQUENCE,
|
||||
|
||||
MODE_BYTESET,
|
||||
MODE_COPY_SECTOR,
|
||||
MODE_CMP_IMAGES,
|
||||
MODE_DEBUG_MAINT1,
|
||||
MODE_ERASE,
|
||||
MODE_LIST_ASPI,
|
||||
MODE_MARKED_IMAGE,
|
||||
MODE_MERGE_IMAGES,
|
||||
MODE_RANDOM_ERR,
|
||||
MODE_RANDOM_IMAGE,
|
||||
MODE_RAW_SECTOR,
|
||||
MODE_READ_SECTOR,
|
||||
MODE_SEND_CDB,
|
||||
MODE_SHOW_SECTOR,
|
||||
MODE_SIGN,
|
||||
MODE_TRUNCATE,
|
||||
MODE_ZERO_UNREADABLE,
|
||||
|
||||
MODIFIER_ADAPTIVE_READ,
|
||||
MODIFIER_AUTO_SUFFIX,
|
||||
MODIFIER_CACHE_SIZE,
|
||||
MODIFIER_CLV_SPEED, /* unused */
|
||||
MODIFIER_CAV_SPEED, /* unused */
|
||||
MODIFIER_CDUMP,
|
||||
MODIFIER_DAO,
|
||||
MODIFIER_DEBUG,
|
||||
MODIFIER_DEFECTIVE_DUMP,
|
||||
MODIFIER_DRIVER,
|
||||
MODIFIER_EJECT,
|
||||
MODIFIER_FILL_UNREADABLE,
|
||||
MODIFIER_IGNORE_FATAL_SENSE,
|
||||
MODIFIER_INTERNAL_REREADS,
|
||||
MODIFIER_QUERY_SIZE,
|
||||
MODIFIER_NEW_DS_MARKER,
|
||||
MODIFIER_RANDOM_SEED,
|
||||
MODIFIER_READ_ATTEMPTS,
|
||||
MODIFIER_READ_MEDIUM,
|
||||
MODIFIER_READ_RAW,
|
||||
MODIFIER_RAW_MODE,
|
||||
MODIFIER_SCREEN_SHOT,
|
||||
MODIFIER_SIMULATE_DEFECTS,
|
||||
MODIFIER_SPEED_WARNING,
|
||||
MODIFIER_SPINUP_DELAY,
|
||||
MODIFIER_SPLIT_FILES,
|
||||
MODIFIER_TRUNCATE,
|
||||
MODIFIER_VERSION,
|
||||
} run_mode;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{ int mode = MODE_NONE;
|
||||
int sequence = MODE_NONE;
|
||||
int devices_queried = FALSE;
|
||||
char *debug_arg = NULL;
|
||||
char *read_range = NULL;
|
||||
#ifdef WITH_NLS_YES
|
||||
char *locale_test;
|
||||
#ifdef WITH_EMBEDDED_SRC_PATH_YES
|
||||
#ifndef SYS_MINGW
|
||||
char src_locale_path[strlen(SRCDIR)+10];
|
||||
#endif
|
||||
#endif /* WITH_EMBEDDED_SRC_PATH_YES */
|
||||
#if defined(SYS_MINGW) || defined(SYS_DARWIN)
|
||||
char *bin_locale_path = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_MEMDEBUG_YES
|
||||
atexit(check_memleaks);
|
||||
#endif
|
||||
|
||||
/*** Do this early so that we can use mutexes */
|
||||
|
||||
g_thread_init(NULL);
|
||||
|
||||
#ifdef SYS_MINGW
|
||||
/*** Create a named mutex so that the installer can detect
|
||||
that we are running. A malicious user may cause this
|
||||
to fail by reserving the mutex for himself,
|
||||
so we do not care if the mutex can not be created. */
|
||||
|
||||
CreateMutex(NULL, FALSE, "dvdisaster");
|
||||
#endif
|
||||
|
||||
/*** Setup the global closure. */
|
||||
|
||||
InitClosure();
|
||||
|
||||
/*** Setup for multithreading */
|
||||
|
||||
Closure->mainThread = g_thread_self();
|
||||
|
||||
/*** Setup the locale.
|
||||
Try the local source directory first (it may be more recent),
|
||||
then fall back to the global installation directory.
|
||||
The test phrase is supposed to be translated with "yes",
|
||||
_independent_ of the actual locale! */
|
||||
|
||||
#ifdef WITH_NLS_YES
|
||||
#ifdef SYS_MINGW
|
||||
if(!g_getenv("LANG")) /* Unix style setting has precedence */
|
||||
{ LANGID lang_id;
|
||||
|
||||
/* Try to get locale from Windows
|
||||
and set the respective environment variables. */
|
||||
|
||||
lang_id = GetUserDefaultLangID();
|
||||
switch(PRIMARYLANGID(lang_id))
|
||||
{ case LANG_CZECH:
|
||||
g_setenv("LANG", "cs_CZ", 1);
|
||||
#ifdef WIN_CONSOLE
|
||||
g_setenv("OUTPUT_CHARSET", "CP852", 1);
|
||||
#else
|
||||
g_setenv("OUTPUT_CHARSET", "CP1250", 1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LANG_GERMAN:
|
||||
g_setenv("LANG", "de_DE", 1);
|
||||
#ifdef WIN_CONSOLE
|
||||
g_setenv("OUTPUT_CHARSET", "CP850", 1);
|
||||
#else
|
||||
g_setenv("OUTPUT_CHARSET", "CP1252", 1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LANG_ITALIAN:
|
||||
g_setenv("LANG", "it_IT", 1);
|
||||
#ifdef WIN_CONSOLE
|
||||
g_setenv("OUTPUT_CHARSET", "CP850", 1);
|
||||
#else
|
||||
g_setenv("OUTPUT_CHARSET", "CP1252", 1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LANG_RUSSIAN:
|
||||
g_setenv("LANG", "ru_RU", 1);
|
||||
#ifdef WIN_CONSOLE
|
||||
g_setenv("OUTPUT_CHARSET", "CP855", 1);
|
||||
#else
|
||||
g_setenv("OUTPUT_CHARSET", "CP1251", 1);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case LANG_SWEDISH:
|
||||
g_setenv("LANG", "sv_SV", 1);
|
||||
#ifdef WIN_CONSOLE
|
||||
g_setenv("OUTPUT_CHARSET", "CP850", 1);
|
||||
#else
|
||||
g_setenv("OUTPUT_CHARSET", "CP1252", 1);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* SYS_MINGW */
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
setlocale(LC_MESSAGES, "");
|
||||
textdomain("dvdisaster");
|
||||
|
||||
#ifndef SYS_MINGW
|
||||
/* Try local source directory first */
|
||||
|
||||
#ifdef WITH_EMBEDDED_SRC_PATH_YES
|
||||
g_sprintf(src_locale_path,"%s/locale",SRCDIR);
|
||||
bindtextdomain("dvdisaster", src_locale_path);
|
||||
#endif /* WITH_EMBEDDED_SRC_PATH_YES */
|
||||
|
||||
/* TRANSLATORS:
|
||||
This is a dummy entry which is supposed to translate into "ok".
|
||||
Please do not return anything else here. */
|
||||
locale_test = gettext("test phrase for verifying the locale installation");
|
||||
|
||||
/* Try current directory. Might work if we are starting
|
||||
from the root dir of a binary distribution. */
|
||||
|
||||
if(strcmp(locale_test, "ok"))
|
||||
{ char buf[256];
|
||||
|
||||
if(getcwd(buf, 256))
|
||||
{ char locale_path[strlen(buf)+20];
|
||||
g_sprintf(locale_path,"%s/locale", buf);
|
||||
bindtextdomain("dvdisaster", locale_path);
|
||||
locale_test = gettext("test phrase for verifying the locale installation");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYS_MINGW) || defined(SYS_DARWIN)
|
||||
/* Try the directory where our executable comes from.
|
||||
This is only possible under Windows and Mac OS,
|
||||
and should cover all cases. */
|
||||
|
||||
#ifdef SYS_MINGW
|
||||
bin_locale_path = g_strdup_printf("%s\\locale", Closure->binDir);
|
||||
#else
|
||||
bin_locale_path = g_strdup_printf("%s/locale", Closure->binDir);
|
||||
#endif
|
||||
bindtextdomain("dvdisaster", bin_locale_path);
|
||||
locale_test = gettext("test phrase for verifying the locale installation");
|
||||
g_free(bin_locale_path);
|
||||
#endif
|
||||
|
||||
/* Last resort: fall back to global locale */
|
||||
|
||||
if(strcmp(locale_test, "ok"))
|
||||
bindtextdomain("dvdisaster", LOCALEDIR);
|
||||
#endif /* WITH_NLS_YES */
|
||||
|
||||
/*** Create some localized file name presets */
|
||||
|
||||
LocalizedFileDefaults();
|
||||
|
||||
/*** Collect the Method list */
|
||||
|
||||
CollectMethods();
|
||||
|
||||
/*** The following test may go wrong if the compiler chooses the
|
||||
wrong packing. */
|
||||
|
||||
if(sizeof(EccHeader) != 4096)
|
||||
Stop("sizeof(EccHeader) is %d, but must be 4096.\n", sizeof(EccHeader));
|
||||
|
||||
/*** Parse the options */
|
||||
|
||||
for(;;)
|
||||
{ int option_index,c;
|
||||
static struct option long_options[] =
|
||||
{ {"adaptive-read", 0, 0, MODIFIER_ADAPTIVE_READ},
|
||||
{"auto-suffix", 0, 0, MODIFIER_AUTO_SUFFIX},
|
||||
{"byteset", 1, 0, MODE_BYTESET },
|
||||
{"copy-sector", 1, 0, MODE_COPY_SECTOR },
|
||||
{"compare-images", 1, 0, MODE_CMP_IMAGES },
|
||||
{"cache-size", 1, 0, MODIFIER_CACHE_SIZE },
|
||||
{"cav", 1, 0, MODIFIER_CAV_SPEED },
|
||||
{"cdump", 0, 0, MODIFIER_CDUMP },
|
||||
{"clv", 1, 0, MODIFIER_CLV_SPEED },
|
||||
{"create", 0, 0, 'c'},
|
||||
{"dao", 0, 0, MODIFIER_DAO },
|
||||
{"debug", 0, 0, MODIFIER_DEBUG },
|
||||
{"debug1", 1, 0, MODE_DEBUG_MAINT1 },
|
||||
{"defective-dump", 1, 0, MODIFIER_DEFECTIVE_DUMP },
|
||||
{"device", 0, 0, 'd'},
|
||||
{"driver", 1, 0, MODIFIER_DRIVER },
|
||||
{"ecc", 1, 0, 'e'},
|
||||
{"eject", 0, 0, MODIFIER_EJECT },
|
||||
{"erase", 1, 0, MODE_ERASE },
|
||||
{"fill-unreadable", 1, 0, MODIFIER_FILL_UNREADABLE },
|
||||
{"fix", 0, 0, 'f'},
|
||||
{"help", 0, 0, 'h'},
|
||||
{"ignore-fatal-sense", 0, 0, MODIFIER_IGNORE_FATAL_SENSE },
|
||||
{"internal-rereads", 1, 0, MODIFIER_INTERNAL_REREADS },
|
||||
{"image", 1, 0, 'i'},
|
||||
{"jump", 1, 0, 'j'},
|
||||
#ifdef SYS_MINGW
|
||||
{"list", 0, 0, 'l' },
|
||||
#endif
|
||||
{"marked-image", 1, 0, MODE_MARKED_IMAGE },
|
||||
{"merge-images", 1, 0, MODE_MERGE_IMAGES },
|
||||
{"method", 2, 0, 'm' },
|
||||
{"new-ds-marker", 0, 0, MODIFIER_NEW_DS_MARKER },
|
||||
{"prefix", 1, 0, 'p'},
|
||||
{"query-size", 1, 0, MODIFIER_QUERY_SIZE },
|
||||
{"random-errors", 1, 0, MODE_RANDOM_ERR },
|
||||
{"random-image", 1, 0, MODE_RANDOM_IMAGE },
|
||||
{"random-seed", 1, 0, MODIFIER_RANDOM_SEED },
|
||||
{"raw-mode", 1, 0, MODIFIER_RAW_MODE },
|
||||
{"raw-sector", 1, 0, MODE_RAW_SECTOR},
|
||||
{"read", 2, 0,'r'},
|
||||
{"read-attempts", 1, 0, MODIFIER_READ_ATTEMPTS },
|
||||
{"read-medium", 1, 0, MODIFIER_READ_MEDIUM },
|
||||
{"read-sector", 1, 0, MODE_READ_SECTOR},
|
||||
{"read-raw", 0, 0, MODIFIER_READ_RAW},
|
||||
{"redundancy", 1, 0, 'n'},
|
||||
{"scan", 2, 0,'s'},
|
||||
{"screen-shot", 0, 0, MODIFIER_SCREEN_SHOT },
|
||||
{"send-cdb", 1, 0, MODE_SEND_CDB},
|
||||
{"show-sector", 1, 0, MODE_SHOW_SECTOR},
|
||||
{"sign", 0, 0, MODE_SIGN},
|
||||
{"sim-defects", 1, 0, MODIFIER_SIMULATE_DEFECTS},
|
||||
{"speed-warning", 2, 0, MODIFIER_SPEED_WARNING},
|
||||
{"spinup-delay", 1, 0, MODIFIER_SPINUP_DELAY},
|
||||
{"split-files", 0, 0, MODIFIER_SPLIT_FILES},
|
||||
{"test", 0, 0, 't'},
|
||||
{"threads", 1, 0, 'x'},
|
||||
{"truncate", 2, 0, MODIFIER_TRUNCATE},
|
||||
{"unlink", 0, 0, 'u'},
|
||||
{"verbose", 0, 0, 'v'},
|
||||
{"version", 0, 0, MODIFIER_VERSION},
|
||||
{"zero-unreadable", 0, 0, MODE_ZERO_UNREADABLE},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv,
|
||||
"cd:e:fhi:j:lm::n:p:r::s::tuvx:",
|
||||
long_options, &option_index);
|
||||
|
||||
if(c == -1) break;
|
||||
|
||||
switch(c)
|
||||
{ case 'r': mode = MODE_SEQUENCE; sequence |= 1<<MODE_READ;
|
||||
if(optarg) read_range = g_strdup(optarg);
|
||||
break;
|
||||
|
||||
case 's': mode = MODE_SEQUENCE; sequence |= 1<<MODE_SCAN;
|
||||
if(optarg) read_range = g_strdup(optarg);
|
||||
break;
|
||||
case 'c': mode = MODE_SEQUENCE; sequence |= 1<<MODE_CREATE; break;
|
||||
case 'f': mode = MODE_SEQUENCE; sequence |= 1<<MODE_FIX; break;
|
||||
case 't': mode = MODE_SEQUENCE; sequence |= 1<<MODE_VERIFY; break;
|
||||
case 'u': Closure->unlinkImage = TRUE; break;
|
||||
case 'h': mode = MODE_HELP; break;
|
||||
case 'i': if(optarg)
|
||||
{ g_free(Closure->imageName);
|
||||
Closure->imageName = g_strdup(optarg);
|
||||
}
|
||||
break;
|
||||
case 'j': if(optarg) Closure->sectorSkip = atoi(optarg) & ~0xf;
|
||||
if(Closure->sectorSkip<0) Closure->sectorSkip = 0;
|
||||
break;
|
||||
case 'l': mode = MODE_LIST_ASPI; break;
|
||||
case 'm': if(optarg && strlen(optarg) == 4)
|
||||
{ g_free(Closure->methodName);
|
||||
Closure->methodName = g_strdup(optarg);
|
||||
}
|
||||
else { ListMethods(); FreeClosure(); exit(EXIT_SUCCESS); }
|
||||
break;
|
||||
case 'n': if(optarg)
|
||||
{ Closure->redundancy = g_strdup(optarg);
|
||||
if(!strcmp(optarg, "CD") || !strcmp(optarg, "cd"))
|
||||
Closure->mediumSize = CDR_SIZE;
|
||||
else if(!strcmp(optarg, "DVD") || !strcmp(optarg, "dvd"))
|
||||
Closure->mediumSize = DVD_SL_SIZE;
|
||||
else if(!strcmp(optarg, "DVD9") || !strcmp(optarg, "dvd9"))
|
||||
Closure->mediumSize = DVD_DL_SIZE;
|
||||
else Closure->mediumSize = (gint64)atoll(optarg);
|
||||
break;
|
||||
}
|
||||
case 'e': if(optarg)
|
||||
{ g_free(Closure->eccName);
|
||||
Closure->eccName = g_strdup(optarg);
|
||||
}
|
||||
break;
|
||||
case 'p': if(optarg)
|
||||
{ g_free(Closure->imageName);
|
||||
g_free(Closure->eccName);
|
||||
Closure->eccName = g_malloc(strlen(optarg)+5);
|
||||
Closure->imageName = g_malloc(strlen(optarg)+5);
|
||||
g_sprintf(Closure->eccName,"%s.ecc",optarg);
|
||||
g_sprintf(Closure->imageName,"%s.iso",optarg);
|
||||
}
|
||||
break;
|
||||
case 'd': if(optarg)
|
||||
{ g_free(Closure->device);
|
||||
Closure->device = g_strdup(optarg);
|
||||
break;
|
||||
}
|
||||
case 'v': Closure->verbose = TRUE;
|
||||
break;
|
||||
|
||||
case 'x': Closure->codecThreads = atoi(optarg);
|
||||
if(Closure->codecThreads < 1 || Closure->codecThreads > MAX_CODEC_THREADS)
|
||||
Stop(_("--threads must be 1..%d\n"), MAX_CODEC_THREADS);
|
||||
break;
|
||||
|
||||
case 0 : break; /* flag argument */
|
||||
|
||||
case MODIFIER_ADAPTIVE_READ:
|
||||
Closure->adaptiveRead = TRUE;
|
||||
break;
|
||||
case MODIFIER_AUTO_SUFFIX:
|
||||
Closure->autoSuffix = TRUE;
|
||||
break;
|
||||
case MODIFIER_CACHE_SIZE:
|
||||
Closure->cacheMB = atoi(optarg);
|
||||
if(Closure->cacheMB < 8)
|
||||
Stop(_("--cache-size must at least be 8MB; 16MB or higher is recommended."));
|
||||
if(Closure->cacheMB > 8192)
|
||||
Stop(_("--cache-size maximum is 8192MB."));
|
||||
break;
|
||||
case MODIFIER_CDUMP:
|
||||
Closure->debugCDump = TRUE;
|
||||
break;
|
||||
case MODIFIER_DAO:
|
||||
Closure->noTruncate = 1;
|
||||
break;
|
||||
case MODIFIER_EJECT:
|
||||
Closure->eject = 1;
|
||||
break;
|
||||
case MODIFIER_DRIVER: /* currently undocumented feature */
|
||||
#if defined(SYS_LINUX)
|
||||
if(optarg && !strcmp(optarg,"sg"))
|
||||
Closure->useSGioctl = TRUE;
|
||||
else
|
||||
Stop(_("Valid args for --driver: sg"));
|
||||
#else
|
||||
Stop(_("--driver is only supported on GNU/Linux"));
|
||||
#endif
|
||||
break;
|
||||
case MODIFIER_FILL_UNREADABLE:
|
||||
if(optarg) Closure->fillUnreadable = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case MODIFIER_IGNORE_FATAL_SENSE:
|
||||
Closure->ignoreFatalSense = TRUE;
|
||||
break;
|
||||
case MODIFIER_INTERNAL_REREADS:
|
||||
if(optarg)
|
||||
Closure->internalAttempts = atoi(optarg);
|
||||
if(Closure->internalAttempts < 0)
|
||||
Closure->internalAttempts = -1;
|
||||
if(Closure->internalAttempts > 10)
|
||||
Closure->internalAttempts = 10;
|
||||
break;
|
||||
case MODIFIER_TRUNCATE:
|
||||
if(optarg) /* debugging truncate mode */
|
||||
{ mode = MODE_TRUNCATE;
|
||||
debug_arg = g_strdup(optarg);
|
||||
}
|
||||
else Closure->truncate = 1; /* truncate confirmation for fix mode */
|
||||
break;
|
||||
case MODIFIER_DEBUG:
|
||||
Closure->debugMode = TRUE;
|
||||
break;
|
||||
case MODIFIER_DEFECTIVE_DUMP:
|
||||
{ char *c;
|
||||
Closure->defectiveDump = TRUE;
|
||||
g_free(Closure->dDumpDir);
|
||||
Closure->dDumpDir = g_strdup(optarg);
|
||||
c = strrchr(Closure->dDumpDir, '/');
|
||||
if(c)
|
||||
{ *c = 0;
|
||||
g_free(Closure->dDumpPrefix);
|
||||
Closure->dDumpPrefix = g_strdup(c+1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MODIFIER_NEW_DS_MARKER:
|
||||
Closure->dsmVersion = 1;
|
||||
break;
|
||||
case MODIFIER_QUERY_SIZE:
|
||||
if(!strcmp(optarg, "drive")) Closure->querySize = 0;
|
||||
else if(!strcmp(optarg, "udf")) Closure->querySize = 1;
|
||||
else if(!strcmp(optarg, "ecc")) Closure->querySize = 2;
|
||||
else Stop("--query-size requires one of these arguments: drive udf ecc\n");
|
||||
break;
|
||||
case MODIFIER_RANDOM_SEED:
|
||||
if(optarg) Closure->randomSeed = atoi(optarg);
|
||||
break;
|
||||
case MODIFIER_RAW_MODE:
|
||||
if(optarg) Closure->rawMode = strtol(optarg,NULL,16);
|
||||
break;
|
||||
case MODIFIER_READ_ATTEMPTS:
|
||||
if(optarg)
|
||||
{ char copy[strlen(optarg)+1];
|
||||
char *cpos;
|
||||
|
||||
strcpy(copy, optarg);
|
||||
cpos = strchr(copy,'-');
|
||||
|
||||
if(!cpos)
|
||||
{ Closure->minReadAttempts = Closure->maxReadAttempts = atoi(optarg);
|
||||
}
|
||||
else
|
||||
{ *cpos = 0;
|
||||
Closure->minReadAttempts = atoi(copy);
|
||||
Closure->maxReadAttempts = atoi(cpos+1);
|
||||
}
|
||||
|
||||
if(Closure->minReadAttempts < 1)
|
||||
Closure->minReadAttempts = 1;
|
||||
if(Closure->maxReadAttempts < Closure->minReadAttempts)
|
||||
Closure->maxReadAttempts = Closure->minReadAttempts;
|
||||
}
|
||||
break;
|
||||
case MODIFIER_READ_MEDIUM:
|
||||
Closure->readingPasses = atoi(optarg);
|
||||
break;
|
||||
case MODIFIER_READ_RAW:
|
||||
Closure->readRaw = TRUE;
|
||||
break;
|
||||
case MODIFIER_SCREEN_SHOT:
|
||||
Closure->screenShotMode = TRUE;
|
||||
break;
|
||||
case MODIFIER_SIMULATE_DEFECTS:
|
||||
if(optarg) Closure->simulateDefects = atoi(optarg);
|
||||
else Closure->simulateDefects = 10;
|
||||
break;
|
||||
case MODIFIER_SPINUP_DELAY:
|
||||
if(optarg) Closure->spinupDelay = atoi(optarg);
|
||||
break;
|
||||
case MODIFIER_SPEED_WARNING:
|
||||
if(optarg) Closure->speedWarning = atoi(optarg);
|
||||
else Closure->speedWarning=10;
|
||||
break;
|
||||
case MODIFIER_SPLIT_FILES:
|
||||
Closure->splitFiles = 1;
|
||||
break;
|
||||
case MODIFIER_CLV_SPEED:
|
||||
Closure->driveSpeed = atoi(optarg);
|
||||
break;
|
||||
case MODIFIER_CAV_SPEED:
|
||||
Closure->driveSpeed = -atoi(optarg);
|
||||
break;
|
||||
case MODIFIER_VERSION:
|
||||
PrintCLI(_("\ndvdisaster version %s build %d\n\n"),
|
||||
Closure->cookedVersion, buildCount);
|
||||
FreeClosure();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case MODE_BYTESET:
|
||||
mode = MODE_BYTESET;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_CMP_IMAGES:
|
||||
mode = MODE_CMP_IMAGES;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_COPY_SECTOR:
|
||||
mode = MODE_COPY_SECTOR;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_DEBUG_MAINT1:
|
||||
mode = MODE_DEBUG_MAINT1;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_ERASE:
|
||||
mode = MODE_ERASE;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_MARKED_IMAGE:
|
||||
mode = MODE_MARKED_IMAGE;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_MERGE_IMAGES:
|
||||
mode = MODE_MERGE_IMAGES;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_RANDOM_ERR:
|
||||
mode = MODE_RANDOM_ERR;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_RANDOM_IMAGE:
|
||||
mode = MODE_RANDOM_IMAGE;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_RAW_SECTOR:
|
||||
mode = MODE_RAW_SECTOR;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_READ_SECTOR:
|
||||
mode = MODE_READ_SECTOR;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_SEND_CDB:
|
||||
mode = MODE_SEND_CDB;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_SIGN:
|
||||
mode = MODE_SIGN;
|
||||
break;
|
||||
case MODE_SHOW_SECTOR:
|
||||
mode = MODE_SHOW_SECTOR;
|
||||
debug_arg = g_strdup(optarg);
|
||||
break;
|
||||
case MODE_ZERO_UNREADABLE:
|
||||
mode = MODE_ZERO_UNREADABLE;
|
||||
break;
|
||||
case '?': mode = MODE_HELP; break;
|
||||
default: PrintCLI(_("?? illegal getopt return value %d\n"),c); break;
|
||||
}
|
||||
}
|
||||
|
||||
/*** Don't allow debugging option if --debug wasn't given */
|
||||
|
||||
if(!Closure->debugMode)
|
||||
switch(mode)
|
||||
{ case MODE_BYTESET:
|
||||
case MODE_COPY_SECTOR:
|
||||
case MODE_CMP_IMAGES:
|
||||
case MODE_ERASE:
|
||||
case MODE_RANDOM_ERR:
|
||||
case MODE_RANDOM_IMAGE:
|
||||
case MODE_READ_SECTOR:
|
||||
case MODE_RAW_SECTOR:
|
||||
case MODE_SEND_CDB:
|
||||
case MODE_SHOW_SECTOR:
|
||||
case MODE_MARKED_IMAGE:
|
||||
case MODE_MERGE_IMAGES:
|
||||
case MODE_SIGN:
|
||||
case MODE_TRUNCATE:
|
||||
case MODE_ZERO_UNREADABLE:
|
||||
mode = MODE_HELP;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WIN_CONSOLE
|
||||
if(mode != MODE_SIGN && !VerifySignature())
|
||||
{ char version[80];
|
||||
|
||||
if(Closure->version % 100)
|
||||
sprintf(version, "dvdisaster-%s.%d-setup.exe", VERSION, Closure->version%100);
|
||||
else sprintf(version, "dvdisaster-%s-setup.exe", VERSION);
|
||||
Stop(_("dvdisaster is not properly installed.\n"
|
||||
"Please execute the installer program (%s) again.\n"), version);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** CPU type detection. */
|
||||
|
||||
Closure->useSSE2 = ProbeSSE2();
|
||||
|
||||
/*** Parse the sector ranges for --read and --scan */
|
||||
|
||||
if(read_range)
|
||||
{ char *dashpos = strchr(read_range,'-');
|
||||
|
||||
if(dashpos)
|
||||
{ *dashpos = 0;
|
||||
|
||||
Closure->readStart = atoi(read_range);
|
||||
if(strlen(dashpos+1) == 3 && !strncmp(dashpos+1, "end", 3))
|
||||
Closure->readEnd = -1;
|
||||
else Closure->readEnd = atoi(dashpos+1);
|
||||
}
|
||||
else Closure->readStart = Closure->readEnd = atoi(read_range);
|
||||
g_free(read_range);
|
||||
}
|
||||
|
||||
/*** Apply auto suffixes
|
||||
(--read etc. may be processed before --auto-suffix,
|
||||
so we must defer autosuffixing until all args have been read) */
|
||||
|
||||
if(Closure->autoSuffix)
|
||||
{ Closure->eccName = ApplyAutoSuffix(Closure->eccName, "ecc");
|
||||
Closure->imageName = ApplyAutoSuffix(Closure->imageName, "iso");
|
||||
}
|
||||
|
||||
/*** Determine the default device (OS dependent!) if none
|
||||
has been specified on the command line. */
|
||||
|
||||
if(!Closure->device)
|
||||
{ Closure->device = DefaultDevice();
|
||||
devices_queried = TRUE;
|
||||
}
|
||||
|
||||
/*** Dispatch action depending on mode.
|
||||
The major modes can be executed in sequence,
|
||||
but not all combinations may be really useful.
|
||||
|
||||
The GUI version for Windows does not have an open console,
|
||||
so no command line actions can be carried out.
|
||||
Force opening the GUI by clearing the mode variable. */
|
||||
|
||||
#if defined(SYS_MINGW) && !defined(WIN_CONSOLE)
|
||||
mode = MODE_NONE;
|
||||
#endif
|
||||
|
||||
switch(mode)
|
||||
{ case MODE_SEQUENCE:
|
||||
if(sequence & 1<<MODE_SCAN)
|
||||
ReadMediumLinear((gpointer)1);
|
||||
|
||||
if(sequence & 1<<MODE_READ)
|
||||
{ if(sequence & 1<<MODE_CREATE)
|
||||
Closure->readAndCreate = TRUE;
|
||||
if(Closure->adaptiveRead)
|
||||
ReadMediumAdaptive((gpointer)0);
|
||||
else ReadMediumLinear((gpointer)0);
|
||||
}
|
||||
|
||||
if(sequence & 1<<MODE_CREATE)
|
||||
CreateEcc();
|
||||
|
||||
if(sequence & 1<<MODE_FIX)
|
||||
FixEcc();
|
||||
|
||||
if(sequence & 1<<MODE_VERIFY)
|
||||
Verify();
|
||||
break;
|
||||
|
||||
case MODE_BYTESET:
|
||||
Byteset(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_CMP_IMAGES:
|
||||
MergeImages(debug_arg, FALSE);
|
||||
break;
|
||||
|
||||
case MODE_COPY_SECTOR:
|
||||
CopySector(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_DEBUG_MAINT1:
|
||||
Maintenance1(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_ERASE:
|
||||
Erase(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_SEND_CDB:
|
||||
SendCDB(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_RAW_SECTOR:
|
||||
RawSector(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_READ_SECTOR:
|
||||
ReadSector(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_SHOW_SECTOR:
|
||||
ShowSector(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_RANDOM_ERR:
|
||||
RandomError(Closure->imageName, debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_MARKED_IMAGE:
|
||||
RandomImage(Closure->imageName, debug_arg, 1);
|
||||
break;
|
||||
|
||||
case MODE_MERGE_IMAGES:
|
||||
MergeImages(debug_arg, TRUE);
|
||||
break;
|
||||
|
||||
case MODE_RANDOM_IMAGE:
|
||||
RandomImage(Closure->imageName, debug_arg, 0);
|
||||
break;
|
||||
|
||||
case MODE_TRUNCATE:
|
||||
TruncateImage(debug_arg);
|
||||
break;
|
||||
|
||||
case MODE_ZERO_UNREADABLE:
|
||||
ZeroUnreadable();
|
||||
break;
|
||||
|
||||
#ifdef SYS_MINGW
|
||||
case MODE_LIST_ASPI:
|
||||
ListAspiDrives();
|
||||
break;
|
||||
|
||||
case MODE_SIGN:
|
||||
WriteSignature();
|
||||
exit(0);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(debug_arg) g_free(debug_arg);
|
||||
|
||||
/*** If no mode was selected, print the help screen. */
|
||||
|
||||
#ifdef WIN_CONSOLE
|
||||
if(mode == MODE_HELP || mode == MODE_NONE)
|
||||
#else
|
||||
if(mode == MODE_HELP)
|
||||
#endif
|
||||
{
|
||||
/* TRANSLATORS: Program options like -r and --read are not to be translated
|
||||
to avoid confusion when discussing the program in international forums. */
|
||||
PrintCLI(_("\nCommon usage examples:\n"
|
||||
" dvdisaster -r,--read # Read the medium image to hard disc.\n"
|
||||
" # Use -rn-m to read a certain sector range, e.g. -r100-200\n"
|
||||
" dvdisaster -c,--create # Create .ecc information for the medium image.\n"
|
||||
" dvdisaster -f,--fix # Try to fix medium image using .ecc information.\n"
|
||||
" dvdisaster -s,--scan # Scan the medium for read errors.\n"
|
||||
" dvdisaster -t,--test # Test integrity of the .iso and .ecc files.\n"
|
||||
" dvdisaster -u,--unlink # Delete .iso files (when other actions complete)\n\n"));
|
||||
|
||||
PrintCLI(_("Drive and file specification:\n"
|
||||
" -d,--device device - read from given device (default: %s)\n"
|
||||
" -p,--prefix prefix - prefix of .iso/.ecc file (default: medium.* )\n"
|
||||
" -i,--image imagefile - name of image file (default: medium.iso)\n"
|
||||
" -e,--ecc eccfile - name of parity file (default: medium.ecc)\n"),
|
||||
Closure->device);
|
||||
|
||||
#ifdef SYS_MINGW
|
||||
PrintCLI(_(" -l,--list - list drives available under ASPI manager\n\n"));
|
||||
#else
|
||||
PrintCLI("\n");
|
||||
#endif
|
||||
|
||||
PrintCLI(_("Tweaking options (see manual before using!)\n"
|
||||
" -j,--jump n - jump n sectors forward after a read error (default: 16)\n"
|
||||
" -m n - list/select error correction methods (default: RS01)\n"
|
||||
" -n,--redundancy n%% - error correction file redundancy (in percent), or\n"
|
||||
" maximum error correction image size (in sectors)\n"
|
||||
" -v,--verbose - more diagnostic messages\n"
|
||||
// " -x, --threads n - use n threads for en-/decoding (if supported by codec)\n"
|
||||
" --adaptive-read - use optimized strategy for reading damaged media\n"
|
||||
" --auto-suffix - automatically add .iso and .ecc file suffixes\n"
|
||||
" --cache-size n - image cache size in MB during -c mode (default: 32MB)\n"
|
||||
" --dao - assume DAO disc; do not trim image end\n"
|
||||
" --defective-dump d - directory for saving incomplete raw sectors\n"
|
||||
" --eject - eject medium after successful read\n"
|
||||
" --fill-unreadable n - fill unreadable sectors with byte n\n"
|
||||
" --ignore-fatal-sense - continue reading after potentially fatal error conditon\n"
|
||||
" --internal-rereads n - drive may attempt n rereads before reporting an error\n"
|
||||
" --query-size n - query drive/udf/ecc for image size (default: ecc)\n"
|
||||
" --raw-mode n - mode for raw reading CD media (20 or 21)\n"
|
||||
" --read-attempts n-m - attempts n upto m reads of a defective sector\n"
|
||||
" --read-medium n - read the whole medium up to n times\n"
|
||||
" --read-raw - performs read in raw mode if possible\n"
|
||||
" --speed-warning n - print warning if speed changes by more than n percent\n"
|
||||
" --spinup-delay n - wait n seconds for drive to spin up\n"
|
||||
" --split-files - split image into files <= 2GB\n\n"));
|
||||
|
||||
if(Closure->debugMode)
|
||||
{ PrintCLI(_("Debugging options (purposefully undocumented and possibly harmful)\n"
|
||||
" --debug - enables the following options\n"
|
||||
" --byteset s,i,b - set byte i in sector s to b\n"
|
||||
" --cdump - creates C #include file dumps instead of hexdumps\n"
|
||||
" --compare-images a,b - compare sectors in images a and b\n"
|
||||
" --copy-sector a,n,b,m - copy sector n from image a to sector m in image b\n"
|
||||
" --erase sector - erase the given sector\n"
|
||||
" --erase n-m - erase sectors n - m, inclusively\n"
|
||||
" --marked-image n - create image with n marked random sectors\n"
|
||||
" --merge-images a,b merge image a with b (a receives sectors from b)\n"
|
||||
" --random-errors r,e seed image with (correctable) random errors\n"
|
||||
" --random-image n - create image with n sectors of random numbers\n"
|
||||
" --random-seed n - random seed for built-in random number generator\n"
|
||||
" --raw-sector n - shows hexdump of the given raw sector from medium in drive\n"
|
||||
" --read-sector n - shows hexdump of the given sector from medium in drive\n"
|
||||
" --screen-shot - useful for generating screen shots\n"
|
||||
" --send-cdb arg - executes given cdb at drive; kills system if used wrong\n"
|
||||
" --show-sector n - shows hexdump of the given sector in an image file\n"
|
||||
" --sim-defects n - simulate n%% defective sectors on medium\n"
|
||||
" --truncate n - truncates image to n sectors\n"
|
||||
" --zero-unreadable - replace the \"unreadable sector\" markers with zeros\n\n"));
|
||||
}
|
||||
|
||||
#ifdef WIN_CONSOLE
|
||||
PrintCLI(_("NOTE: This is the Windows console version of dvdisaster.\n"
|
||||
"The version providing a graphical user interface is called\n"
|
||||
"dvdisaster-win.exe (also contained in this installation).\n\n"));
|
||||
#endif
|
||||
FreeClosure();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* If no mode was selected at the command line,
|
||||
start the graphical user interface.
|
||||
Unless we are in Windows console mode where starting the GUI
|
||||
won't work. */
|
||||
|
||||
if(mode == MODE_NONE)
|
||||
{
|
||||
if(Closure->screenShotMode)
|
||||
{ GPtrArray *a=Closure->deviceNames;
|
||||
int i;
|
||||
for(i=0; i<a->len; i++)
|
||||
{ char *p = g_ptr_array_index(a,i);
|
||||
g_free(p);
|
||||
a->pdata[i] = g_strdup(_("Optical drive 52X FW 1.02"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* We need to query devices in order to build
|
||||
the drop-down menu.*/
|
||||
|
||||
if(!devices_queried)
|
||||
{ if(Closure->device)
|
||||
g_free(Closure->device);
|
||||
Closure->device = DefaultDevice();
|
||||
}
|
||||
|
||||
Closure->guiMode = TRUE;
|
||||
ReadDotfile();
|
||||
CreateMainWindow(&argc, &argv);
|
||||
}
|
||||
|
||||
FreeClosure();
|
||||
|
||||
exit(exitCode);
|
||||
}
|
||||
Reference in New Issue
Block a user