/* 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 #include #include #include /* safety margin in case we're getting UTF path names */ #define WIN_MAX_PATH (4*MAX_PATH) #endif #if 0 #define Verbose g_printf #else #define Verbose(format, ...) #endif /*** *** Locate the binary and documentation directory ***/ /* * Find location of special windows directories. * Copied from glib sources since they have declared it static. * Windows only. * CHECKME: Is it okay to return UTF8? */ #ifdef SYS_MINGW static gchar *get_special_folder(int csidl) { union { char c[WIN_MAX_PATH+1]; wchar_t wc[WIN_MAX_PATH+1]; } path; HRESULT hr; LPITEMIDLIST pidl = NULL; BOOL b; gchar *retval = NULL; hr = SHGetSpecialFolderLocation(NULL, csidl, &pidl); if(hr == S_OK) { if (G_WIN32_HAVE_WIDECHAR_API()) { b = SHGetPathFromIDListW(pidl, path.wc); if(b) retval = g_utf16_to_utf8(path.wc, -1, NULL, NULL, NULL); } else { b = SHGetPathFromIDListA(pidl, path.c); if(b) retval = g_locale_to_utf8(path.c, -1, NULL, NULL, NULL); } CoTaskMemFree(pidl); } return retval; } #endif /* * Find the place of our executable * (Windows only) */ #ifdef SYS_MINGW static char* get_exe_path() { char path[WIN_MAX_PATH]; int n = GetModuleFileNameA(NULL, path, WIN_MAX_PATH); if(n>0 && ncookedVersion); MD5Init(&md5ctxt); MD5Update(&md5ctxt, buf, strlen(buf)); MD5Final(digest+2, &md5ctxt); digest[ 0] = digest[ 7]+19; digest[ 1] = digest[ 9]+58; digest[18] = digest[12]+31; digest[19] = digest[15]+5; return digest; } void WriteSignature() { char loc[strlen(Closure->binDir) + strlen("\\signature")+ 10]; unsigned char *sig = create_signature(); FILE *file; /* processing of error conditions not necessary */ sprintf(loc, "%s\\signature", Closure->binDir); if(!(file = portable_fopen(loc, "wb"))) return; fwrite(sig, 20, 1, file); fclose(file); g_free(sig); } int VerifySignature() { char loc[strlen(Closure->binDir) + strlen("\\signature")+ 10]; unsigned char *sig = create_signature(); char buf[20]; FILE *file; int result; sprintf(loc, "%s\\signature", Closure->binDir); if(!(file = portable_fopen(loc, "rb"))) return FALSE; fread(buf, 20, 1, file); fclose(file); result = !memcmp(sig, buf, 20); return result; } #endif static void get_base_dirs() { #ifdef SYS_MINGW char *appdata; char *homedir; #endif #ifdef SYS_DARWIN char *resdir; #endif /*** Unless completely disabled through a configure option, the source directory is supposed to hold the most recent files, so try this first. Not necessary under Windows as it will always use the directory the binary has been called from. */ #ifdef WITH_EMBEDDED_SRC_PATH_YES #ifndef SYS_MINGW if(DirStat(SRCDIR)) { Closure->binDir = g_strdup(SRCDIR); Closure->docDir = g_strdup_printf("%s/documentation",SRCDIR); Verbose("Using paths from SRCDIR = %s\n", SRCDIR); goto find_dotfile; } #endif #endif /* WITH_EMBEDDED_SRC_PATH_YES */ /*** Otherwise try the installation directory. On Unices this is a hardcoded directory. Windows has binary distributions with no prior known installation place, but luckily it provides a way for figuring out that location. Darwin is like Unix when installed via make install; but tricky when app bundles are used. In that case we use GTK_PATH to find out our location. */ #if defined(SYS_LINUX) || defined(SYS_FREEBSD) || defined(SYS_NETBSD) || defined(SYS_UNKNOWN) || defined(SYS_SOLARIS) if(DirStat(BINDIR)) Closure->binDir = g_strdup(BINDIR); if(DirStat(DOCDIR)) Closure->docDir = g_strdup(DOCDIR); Verbose("Using hardcoded BINDIR = %s, DOCDIR = %s\n", BINDIR, DOCDIR); #endif #ifdef SYS_DARWIN resdir = (char*)g_getenv("GTK_PATH"); if(resdir) /* looks like we are inside an app bundle */ { if(DirStat(resdir)) Closure->binDir = g_strdup(resdir); Closure->docDir = g_strdup_printf("%s/doc", resdir); if(!DirStat(Closure->docDir)) { g_free(Closure->docDir); Closure->docDir = NULL; } } else /* maybe a normal install */ { if(DirStat(BINDIR)) Closure->binDir = g_strdup(BINDIR); if(DirStat(DOCDIR)) Closure->docDir = g_strdup(DOCDIR); } Verbose("Using BINDIR = %s, DOCDIR = %s\n", BINDIR, DOCDIR); #endif #ifdef SYS_MINGW Closure->binDir = get_exe_path(); if(Closure->binDir) Closure->docDir = g_strdup_printf("%s\\documentation", Closure->binDir); Verbose("Using path from get_exe_path() = %s\n", Closure->binDir); #endif /*** The location of the dotfile depends on the operating system. Under Unix the users home directory is used. */ #ifndef SYS_MINGW #ifdef WITH_EMBEDDED_SRC_PATH_YES find_dotfile: #endif /* WITH_EMBEDDED_SRC_PATH_YES */ Closure->homeDir = g_strdup(g_getenv("HOME")); Closure->dotFile = g_strdup_printf("%s/.dvdisaster", Closure->homeDir); #endif #ifdef SYS_MINGW /* For Windows the user's application directory in the roaming profile is preferred for the dotfile; if it does not exist we use the installation directory. */ appdata = get_special_folder(CSIDL_APPDATA); homedir = get_special_folder(CSIDL_PERSONAL); Verbose("Windows specific paths:\n" "- CSIDL_APPDATA: %s\n" "- CSIDL_PERSONAL: %s\n", appdata ? appdata : "NULL", homedir ? homedir : "NULL"); if(homedir && DirStat(homedir)) { Closure->homeDir = g_strdup(homedir); Verbose("- homedir path : %s\n", Closure->homeDir); g_free(homedir); } if(appdata) { Closure->appData = g_strdup_printf("%s\\dvdisaster", appdata); if(DirStat(appdata)) /* CSIDL_APPDATA present? */ { Verbose("- dotfile path : %s\n", Closure->appData); if(DirStat(Closure->appData)) { Closure->dotFile = g_strdup_printf("%s\\.dvdisaster", Closure->appData); Verbose("- dotfile path : present\n"); } else if(!portable_mkdir(Closure->appData)) /* Note: Windows! */ { Closure->dotFile = g_strdup_printf("%s\\.dvdisaster", Closure->appData); Verbose("- dotfile path : - created -\n"); } else { g_free(Closure->appData); Closure->appData = NULL; } } else { Verbose("- dotfile path : *can not be used*\n"); g_free(Closure->appData); Closure->appData = NULL; } g_free(appdata); } /* Fallbacks: Expect .dvdisaster file in binDir; propose C:\Windows\Temp as working dir */ if(!Closure->dotFile) Closure->dotFile = g_strdup_printf("%s\\.dvdisaster", Closure->binDir); if(!Closure->homeDir) Closure->homeDir = g_strdup("C:\\Windows\\Temp"); #endif Verbose("\nUsing file locations:\n" "- Homedir: %s\n" "- Bin dir: %s\n" "- Doc dir: %s\n" "- AppData: %s\n" "- dotfile: %s\n\n", Closure->homeDir, Closure->binDir, Closure->docDir, Closure->appData ? Closure->appData : "Null", Closure->dotFile); } /*** *** Set/get color values ***/ /* * Update color string for the ... string */ void UpdateMarkup(char **string, GdkColor *color) { int hexval; hexval = (color->red << 8) & 0xff0000; hexval |= color->green & 0xff00; hexval |= (color->blue >> 8) & 0xff; if(*string) g_free(*string); *string = g_strdup_printf("color=\"#%06x\"", hexval); } /* * Default color values */ void DefaultColors() { Closure->redText->red = 0xffff; Closure->redText->green = 0; Closure->redText->blue = 0; Closure->greenText->red = 0; Closure->greenText->green = 0x8000; Closure->greenText->blue = 0; Closure->barColor->red = 0xffff; Closure->barColor->green = 0; Closure->barColor->blue = 0; Closure->logColor->red = 0xffff; Closure->logColor->green = 0; Closure->logColor->blue = 0xffff; Closure->curveColor->red = 0; Closure->curveColor->green = 0; Closure->curveColor->blue = 0xffff; Closure->redSector->red = 0xffff; Closure->redSector->green = 0; Closure->redSector->blue = 0; Closure->yellowSector->red = 0xffff; Closure->yellowSector->green = 0xc000; Closure->yellowSector->blue = 0; Closure->greenSector->red = 0; Closure->greenSector->green = 0xdb00; Closure->greenSector->blue = 0; Closure->darkSector->red = 0; Closure->darkSector->green = 0x8000; Closure->darkSector->blue = 0; Closure->blueSector->red = 0; Closure->blueSector->green = 0; Closure->blueSector->blue = 0xffff; Closure->whiteSector->red = 0xffff; Closure->whiteSector->green = 0xffff; Closure->whiteSector->blue = 0xffff; UpdateMarkup(&Closure->redMarkup, Closure->redText); UpdateMarkup(&Closure->greenMarkup, Closure->greenText); } static void save_colors(FILE *dotfile, char *symbol, GdkColor *color) { char *blanks=" "; char *pad; int len=strlen(symbol); if(len>19) pad=blanks+19; else pad=blanks+len; fprintf(dotfile, "%s:%s%02x%02x%02x\n", symbol, pad, color->red>>8, color->green>>8, color->blue>>8); } static void get_color(GdkColor *color, char *value) { unsigned int hex = strtol(value, NULL, 16); color->red = (hex>>8)&0xff00; color->green = hex&0xff00; color->blue = (hex<<8)&0xff00; } /*** *** Save and restore user settings to/from the .dvdisaster file ***/ #define MAX_LINE_LEN 512 void ReadDotfile() { FILE *dotfile; char line[MAX_LINE_LEN]; dotfile = portable_fopen(Closure->dotFile, "rb"); if(!dotfile) return; while(TRUE) { int n; char symbol[41]; char *value; /* Get first MAX_LINE_LEN bytes of line, discard the rest */ line[MAX_LINE_LEN-1] = 1; fgets(line, MAX_LINE_LEN, dotfile); if(!line[MAX_LINE_LEN-1]) /* line longer than buffer */ while(!feof(dotfile) && fgetc(dotfile) != '\n') ; /* Trivially reject the line */ if(feof(dotfile)) break; if(*line == '#') continue; if(!sscanf(line, "%40[0-9a-zA-Z-]%n", symbol, &n)) continue; if(line[n] != ':') continue; /* Separate line contents into symbol: value pair */ value = line+n+1; while(*value && *value == ' ') value++; if(!*value) continue; n = strlen(value); if(value[n-1] == '\n') value[n-1] = 0; /* Parse the symbols which are recognized in this version */ if(!strcmp(symbol, "last-device")) { if(Closure->device) g_free(Closure->device); Closure->device = g_strdup(value); continue; } if(!strcmp(symbol, "last-image")) { g_free(Closure->imageName); if(!strcmp(value, "none")) Closure->imageName = g_strdup(""); else Closure->imageName = g_strdup(value); continue; } if(!strcmp(symbol, "last-ecc")) { g_free(Closure->eccName); if(!strcmp(value, "none")) Closure->eccName = g_strdup(""); else Closure->eccName = g_strdup(value); continue; } if(!strcmp(symbol, "browser")) { g_free(Closure->browser); Closure->browser = g_strdup(value); continue; } if(!strcmp(symbol, "adaptive-read")) { Closure->adaptiveRead = atoi(value); continue; } if(!strcmp(symbol, "auto-suffix")) { Closure->autoSuffix = atoi(value); continue; } if(!strcmp(symbol, "bd-size1")) { Closure->bdSize1 = Closure->savedBDSize1 = atoll(value); continue; } if(!strcmp(symbol, "bd-size2")) { Closure->bdSize2 = Closure->savedBDSize2 = atoll(value); continue; } if(!strcmp(symbol, "cache-size")) { Closure->cacheMB = atoi(value); continue; } if(!strcmp(symbol, "cd-size")) { Closure->cdSize = Closure->savedCDSize = atoll(value); continue; } if(!strcmp(symbol, "codec-threads")) { Closure->codecThreads = atoi(value); continue; } if(!strcmp(symbol, "dao")) { Closure->noTruncate = atoi(value); continue; } if(!strcmp(symbol, "defective-dump")) { Closure->defectiveDump = atoi(value); continue; } if(!strcmp(symbol, "defective-dir")) { if(Closure->dDumpDir) g_free(Closure->dDumpDir); Closure->dDumpDir = g_strdup(value); continue; } if(!strcmp(symbol, "defective-prefix")){ if(Closure->dDumpPrefix) g_free(Closure->dDumpPrefix); Closure->dDumpPrefix = g_strdup(value); continue; } if(!strcmp(symbol, "dotfile-version")) { Closure->dotFileVersion = atoi(value); continue; } if(!strcmp(symbol, "dvd-size1")) { Closure->dvdSize1 = Closure->savedDVDSize1 = atoll(value); continue; } if(!strcmp(symbol, "dvd-size2")) { Closure->dvdSize2 = Closure->savedDVDSize2 = atoll(value); continue; } if(!strcmp(symbol, "eject")) { Closure->eject = atoi(value); continue; } if(!strcmp(symbol, "fill-unreadable")) { Closure->fillUnreadable = atoi(value); continue; } if(!strcmp(symbol, "ignore-fatal-sense")) { Closure->ignoreFatalSense = atoi(value); continue; } if(!strcmp(symbol, "internal-attempts")) { Closure->internalAttempts = atoi(value); continue; } if(!strcmp(symbol, "jump")) { Closure->sectorSkip = atoi(value); continue; } if(!strcmp(symbol, "log-file-enabled")){ Closure->logFileEnabled = atoi(value); continue; } if(!strcmp(symbol, "log-file")) { if(Closure->logFile) g_free(Closure->logFile); Closure->logFile = g_strdup(value); continue; } if(!strcmp(symbol, "medium-size")) { Closure->mediumSize = atoll(value); continue; } if(!strcmp(symbol, "method-name")) { if(Closure->methodName) g_free(Closure->methodName); Closure->methodName = g_strdup(value); continue; } if(!strcmp(symbol, "max-read-attempts")) { Closure->maxReadAttempts = atoi(value); continue; } if(!strcmp(symbol, "min-read-attempts")) { Closure->minReadAttempts = atoi(value); continue; } if(!strcmp(symbol, "missing-sector-marker")) { Closure->dsmVersion = atoi(value); continue; } if(!strcmp(symbol, "query-size")) { Closure->querySize = atoi(value); continue; } if(!strcmp(symbol, "raw-mode")) { Closure->rawMode = atoi(value); continue; } if(!strcmp(symbol, "read-and-create")) { Closure->readAndCreate = atoi(value); continue; } if(!strcmp(symbol, "read-medium")) { Closure->readingPasses = atoi(value); continue; } if(!strcmp(symbol, "read-raw")) { Closure->readRaw = atoi(value); continue; } if(!strcmp(symbol, "redundancy")) { if(Closure->redundancy) g_free(Closure->redundancy); Closure->redundancy = g_strdup(value); continue; } if(!strcmp(symbol, "reverse-cancel-ok")) { Closure->reverseCancelOK = atoi(value); continue; } if(!strcmp(symbol, "spinup-delay")) { Closure->spinupDelay = atoi(value); continue; } if(!strcmp(symbol, "split-files")) { Closure->splitFiles = atoi(value); continue; } if(!strcmp(symbol, "unlink")) { Closure->unlinkImage = atoi(value); continue; } if(!strcmp(symbol, "verbose")) { Closure->verbose = atoi(value); continue; } if(!strcmp(symbol, "welcome-msg")) { Closure->welcomeMessage = atoi(value); continue; } if(!strcmp(symbol, "positive-text")) { get_color(Closure->greenText, value); UpdateMarkup(&Closure->greenMarkup, Closure->greenText); continue; } if(!strcmp(symbol, "negative-text")) { get_color(Closure->redText, value); UpdateMarkup(&Closure->redMarkup, Closure->redText); continue; } if(!strcmp(symbol, "bar-color")) { get_color(Closure->barColor, value); continue; } if(!strcmp(symbol, "log-color")) { get_color(Closure->logColor, value); continue; } if(!strcmp(symbol, "curve-color")) { get_color(Closure->curveColor, value); continue; } if(!strcmp(symbol, "defective-sector")){ get_color(Closure->redSector, value); continue; } if(!strcmp(symbol, "bad-checksum-sector")){ get_color(Closure->yellowSector, value); continue; } if(!strcmp(symbol, "good-sector")) { get_color(Closure->greenSector, value); continue; } if(!strcmp(symbol, "ignored-sector")) { get_color(Closure->blueSector, value); continue; } if(!strcmp(symbol, "highlit-sector")) { get_color(Closure->whiteSector, value); continue; } if(!strcmp(symbol, "present-sector")) { get_color(Closure->darkSector, value); continue; } } if(fclose(dotfile)) g_fprintf(stderr, "Error closing configuration file %s: %s\n", Closure->dotFile, strerror(errno)); } static void update_dotfile() { const char *no_dot_files; FILE *dotfile; /*** If the environment $NO_DOT_FILES is set, do not alter the dotfile. */ no_dot_files = g_getenv("NO_DOT_FILES"); if(no_dot_files && atoi(no_dot_files)) return; /*** Otherwise, save our session */ dotfile = portable_fopen(Closure->dotFile, "wb"); if(!dotfile) { g_fprintf(stderr, "Could not open configuration file %s: %s\n", Closure->dotFile, strerror(errno)); return; } g_fprintf(dotfile, _("# dvdisaster-%s configuration file\n" "# This is an automatically generated file\n" "# which will be overwritten each time dvdisaster is run.\n\n"), VERSION); g_fprintf(dotfile, "last-device: %s\n", Closure->device); g_fprintf(dotfile, "last-image: %s\n", Closure->imageName); g_fprintf(dotfile, "last-ecc: %s\n", Closure->eccName); g_fprintf(dotfile, "browser: %s\n\n", Closure->browser); g_fprintf(dotfile, "adaptive-read: %d\n", Closure->adaptiveRead); g_fprintf(dotfile, "auto-suffix: %d\n", Closure->autoSuffix); g_fprintf(dotfile, "bd-size1: %lld\n", (long long int)Closure->bdSize1); g_fprintf(dotfile, "bd-size2: %lld\n", (long long int)Closure->bdSize2); g_fprintf(dotfile, "cache-size: %d\n", Closure->cacheMB); g_fprintf(dotfile, "cd-size: %lld\n", (long long int)Closure->cdSize); g_fprintf(dotfile, "codec-threads: %d\n", Closure->codecThreads); g_fprintf(dotfile, "dao: %d\n", Closure->noTruncate); g_fprintf(dotfile, "defective-dump: %d\n", Closure->defectiveDump); g_fprintf(dotfile, "defective-dir: %s\n", Closure->dDumpDir); g_fprintf(dotfile, "defective-prefix: %s\n", Closure->dDumpPrefix); g_fprintf(dotfile, "dotfile-version: %d\n", Closure->dotFileVersion); g_fprintf(dotfile, "dvd-size1: %lld\n", (long long int)Closure->dvdSize1); g_fprintf(dotfile, "dvd-size2: %lld\n", (long long int)Closure->dvdSize2); g_fprintf(dotfile, "eject: %d\n", Closure->eject); g_fprintf(dotfile, "fill-unreadable: %d\n", Closure->fillUnreadable); g_fprintf(dotfile, "ignore-fatal-sense: %d\n", Closure->ignoreFatalSense); g_fprintf(dotfile, "internal-attempts: %d\n", Closure->internalAttempts); g_fprintf(dotfile, "jump: %d\n", Closure->sectorSkip); g_fprintf(dotfile, "log-file-enabled: %d\n", Closure->logFileEnabled); g_fprintf(dotfile, "log-file: %s\n", Closure->logFile); g_fprintf(dotfile, "medium-size: %lld\n", (long long int)Closure->mediumSize); g_fprintf(dotfile, "method-name: %s\n", Closure->methodName); g_fprintf(dotfile, "max-read-attempts: %d\n", Closure->maxReadAttempts); g_fprintf(dotfile, "min-read-attempts: %d\n", Closure->minReadAttempts); g_fprintf(dotfile, "missing-sector-marker: %d\n", Closure->dsmVersion); g_fprintf(dotfile, "query-size: %d\n", Closure->querySize); g_fprintf(dotfile, "raw-mode: %d\n", Closure->rawMode); g_fprintf(dotfile, "read-and-create: %d\n", Closure->readAndCreate); g_fprintf(dotfile, "read-medium: %d\n", Closure->readingPasses); g_fprintf(dotfile, "read-raw: %d\n", Closure->readRaw); if(Closure->redundancy) g_fprintf(dotfile, "redundancy: %s\n", Closure->redundancy); g_fprintf(dotfile, "reverse-cancel-ok: %d\n", Closure->reverseCancelOK); g_fprintf(dotfile, "spinup-delay: %d\n", Closure->spinupDelay); g_fprintf(dotfile, "split-files: %d\n", Closure->splitFiles); g_fprintf(dotfile, "unlink: %d\n", Closure->unlinkImage); g_fprintf(dotfile, "verbose: %d\n", Closure->verbose); g_fprintf(dotfile, "welcome-msg: %d\n\n", Closure->welcomeMessage); save_colors(dotfile, "positive-text", Closure->greenText); save_colors(dotfile, "negative-text", Closure->redText); save_colors(dotfile, "bar-color", Closure->barColor); save_colors(dotfile, "log-color", Closure->logColor); save_colors(dotfile, "curve-color", Closure->curveColor); save_colors(dotfile, "defective-sector", Closure->redSector); save_colors(dotfile, "bad-checksum-sector",Closure->yellowSector); save_colors(dotfile, "good-sector", Closure->greenSector); save_colors(dotfile, "ignored-sector", Closure->blueSector); save_colors(dotfile, "highlit-sector", Closure->whiteSector); save_colors(dotfile, "present-sector", Closure->darkSector); if(fclose(dotfile)) g_fprintf(stderr, "Error closing configuration file %s: %s\n", Closure->dotFile, strerror(errno)); } /*** *** Allocate and initialize our global variables ***/ GlobalClosure *Closure; int exitCode = EXIT_SUCCESS; void InitClosure() { int v1,v2,v3,dots=0; char *v,version[strlen(VERSION)+1]; Closure = g_malloc0(sizeof(GlobalClosure)); /* Give versions with patch levels a nicer formatting */ if(!strcmp(RELEASE_STATUS, "patch")) Closure->cookedVersion = g_strdup_printf("%s (pl%s)",VERSION,RELEASE_MICRO); else if(!strcmp(RELEASE_STATUS, "devel")) { Closure->releaseFlags = MFLAG_DEVEL; Closure->cookedVersion = g_strdup_printf("%s (devel-%s)",VERSION,RELEASE_MICRO); } else if(!strcmp(RELEASE_STATUS, "rc")) { Closure->releaseFlags = MFLAG_RC; Closure->cookedVersion = g_strdup_printf("%s (rc-%s)",VERSION,RELEASE_MICRO); } else Closure->cookedVersion = g_strdup(VERSION); /* Replace the dot with a locale-resistant separator */ strcpy(version,VERSION); for(v=version; *v; v++) if(*v=='.') { *v='x'; dots++; } if(dots == 1) { v1 = v2 = v3 = 0; sscanf(version,"%dx%d",&v1,&v2); } else { g_printf("Error: malformed version number %s\n",VERSION); exit(EXIT_FAILURE); } v3 = atoi(RELEASE_MICRO); Closure->version = 10000*v1 + 100*v2 + v3; #if 0 printf("Version %s; %d; Flags %d\n", Closure->cookedVersion, Closure->version, Closure->releaseFlags); #endif /* Get home and system directories */ get_base_dirs(); /* Fill in other closure defaults */ Closure->deviceNames = g_ptr_array_new(); Closure->deviceNodes = g_ptr_array_new(); Closure->browser = g_strdup("xdg-open"); Closure->methodList = g_ptr_array_new(); Closure->methodName = g_strdup("RS01"); Closure->dDumpDir = g_strdup(Closure->homeDir); Closure->cacheMB = 32; Closure->codecThreads = 1; Closure->minReadAttempts = 1; Closure->maxReadAttempts = 1; Closure->rawMode = 0x20; Closure->internalAttempts = -1; Closure->sectorSkip = 16; Closure->spinupDelay = 5; Closure->querySize = 2; Closure->fillUnreadable = -1; Closure->welcomeMessage = 1; /* default sizes for typical CD and DVD media */ Closure->cdSize = Closure->savedCDSize = CDR_SIZE; Closure->dvdSize1 = Closure->savedDVDSize1 = DVD_SL_SIZE; Closure->dvdSize2 = Closure->savedDVDSize2 = DVD_DL_SIZE; Closure->bdSize1 = Closure->savedBDSize1 = BD_SL_SIZE; Closure->bdSize2 = Closure->savedBDSize2 = BD_DL_SIZE; Closure->logString = g_string_sized_new(1024); Closure->logLock = g_mutex_new(); Closure->background = g_malloc0(sizeof(GdkColor)); Closure->foreground = g_malloc0(sizeof(GdkColor)); Closure->grid = g_malloc0(sizeof(GdkColor)); Closure->redText = g_malloc0(sizeof(GdkColor)); Closure->greenText = g_malloc0(sizeof(GdkColor)); Closure->barColor = g_malloc0(sizeof(GdkColor)); Closure->logColor = g_malloc0(sizeof(GdkColor)); Closure->curveColor = g_malloc0(sizeof(GdkColor)); Closure->redSector = g_malloc0(sizeof(GdkColor)); Closure->yellowSector= g_malloc0(sizeof(GdkColor)); Closure->greenSector = g_malloc0(sizeof(GdkColor)); Closure->blueSector = g_malloc0(sizeof(GdkColor)); Closure->whiteSector = g_malloc0(sizeof(GdkColor)); Closure->darkSector = g_malloc0(sizeof(GdkColor)); DefaultColors(); memset(Closure->bs, '\b', 255); DefaultLogFile(); #ifdef SYS_MINGW OpenAspi(); #endif } /* * Add some localized file name defaults. * Can't do this in InitClosure() as the locale has not been * initialized when it is being called. */ void LocalizedFileDefaults() { #ifdef SYS_DARWIN /* Darwin uses / as the current working directory when invoked from an app bundle. Not good. */ char *buf = getcwd(NULL,0); Closure->imageName = NULL; if(buf && !strcmp(buf,"/")) { free(buf); buf = getenv("HOME"); if(buf) { Closure->imageName = g_strdup_printf("%s/%s",buf,_("medium.iso")); Closure->eccName = g_strdup_printf("%s/%s",buf,_("medium.ecc")); Closure->dDumpPrefix = g_strdup_printf("%s/%s",buf,_("sector-")); } } if(!Closure->imageName) { Closure->imageName = g_strdup(_("medium.iso")); Closure->eccName = g_strdup(_("medium.ecc")); Closure->dDumpPrefix = g_strdup(_("sector-")); } #else /* On all other OS, storing the files in the cwd is a sane default. */ Closure->imageName = g_strdup(_("medium.iso")); Closure->eccName = g_strdup(_("medium.ecc")); Closure->dDumpPrefix = g_strdup(_("sector-")); #endif } /* * Clear the CRC cache */ void ClearCrcCache(void) { if(Closure->crcCache) g_free(Closure->crcCache); if(Closure->crcImageName) g_free(Closure->crcImageName); Closure->crcCache = NULL; Closure->crcImageName = NULL; memset(Closure->md5Cache, 0, 16); } /* * Clean up properly */ #define cond_free(x) if(x) g_free(x) /* Doing a simple g_ptr_array_free(a, TRUE) would confuse our memory leak checker */ void cond_free_ptr_array(GPtrArray *a) { unsigned int i; if(!a) return; for(i=0; ilen; i++) g_free(g_ptr_array_index(a,i)); g_ptr_array_free(a, FALSE); } void FreeClosure() { if(Closure->guiMode) update_dotfile(); ClearCrcCache(); cond_free(Closure->cookedVersion); cond_free(Closure->device); cond_free_ptr_array(Closure->deviceNames); cond_free_ptr_array(Closure->deviceNodes); cond_free(Closure->imageName); cond_free(Closure->eccName); cond_free(Closure->redundancy); CallMethodDestructors(); cond_free_ptr_array(Closure->methodList); cond_free(Closure->methodName); cond_free(Closure->homeDir); cond_free(Closure->dotFile); cond_free(Closure->logFile); cond_free(Closure->binDir); cond_free(Closure->docDir); cond_free(Closure->appData); cond_free(Closure->browser); cond_free(Closure->errorTitle); cond_free(Closure->dDumpDir); cond_free(Closure->dDumpPrefix); if(Closure->prefsContext) FreePreferences(Closure->prefsContext); if(Closure->rawEditorContext) FreeRawEditorContext(Closure->rawEditorContext); if(Closure->logString) g_string_free(Closure->logString, TRUE); if(Closure->logLock) g_mutex_free(Closure->logLock); if(Closure->drawGC) g_object_unref(Closure->drawGC); cond_free(Closure->background); cond_free(Closure->foreground); cond_free(Closure->grid); cond_free(Closure->redText); cond_free(Closure->greenText); cond_free(Closure->barColor); cond_free(Closure->logColor); cond_free(Closure->curveColor); cond_free(Closure->redSector); cond_free(Closure->yellowSector); cond_free(Closure->greenSector); cond_free(Closure->blueSector); cond_free(Closure->whiteSector); cond_free(Closure->darkSector); cond_free(Closure->redMarkup); cond_free(Closure->greenMarkup); cond_free(Closure->invisibleDash); if(Closure->readLinearCurve) FreeCurve(Closure->readLinearCurve); if(Closure->readLinearSpiral) FreeSpiral(Closure->readLinearSpiral); if(Closure->readAdaptiveSpiral) FreeSpiral(Closure->readAdaptiveSpiral); if(Closure->readAdaptiveSubtitle) g_free(Closure->readAdaptiveSubtitle); if(Closure->readAdaptiveErrorMsg) g_free(Closure->readAdaptiveErrorMsg); g_free(Closure); #ifdef SYS_MINGW CloseAspi(); #endif }