Imported Upstream version 0.72
This commit is contained in:
252
file.c
Normal file
252
file.c
Normal file
@@ -0,0 +1,252 @@
|
||||
/* 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"
|
||||
|
||||
/***
|
||||
*** Open the image file and fill in the respective Info struct.
|
||||
***/
|
||||
|
||||
ImageInfo* OpenImageFile(EccHeader *eh, int mode)
|
||||
{ ImageInfo *ii = NULL;
|
||||
gint64 img_size;
|
||||
int n,file_flags;
|
||||
gint64 fp_sector;
|
||||
unsigned char buf[2048];
|
||||
struct MD5Context md5ctxt;
|
||||
|
||||
ii = g_malloc0(sizeof(ImageInfo));
|
||||
|
||||
if(!(mode & PRINT_MODE))
|
||||
PrintLog(_("\nOpening %s"), Closure->imageName);
|
||||
|
||||
if(!LargeStat(Closure->imageName, &img_size))
|
||||
{ if(mode & PRINT_MODE) /* no error in print mode */
|
||||
{ FreeImageInfo(ii);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PrintLog(_(": not present.\n"));
|
||||
g_free(ii);
|
||||
Stop(_("Image file %s not present."),Closure->imageName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file_flags = mode & WRITEABLE_IMAGE ? O_RDWR : O_RDONLY;
|
||||
|
||||
if(!(ii->file = LargeOpen(Closure->imageName, file_flags, IMG_PERMS)))
|
||||
{ if(Closure->guiMode)
|
||||
{ g_free(ii);
|
||||
PrintLog(": %s", strerror(errno));
|
||||
Stop(_("Can't open %s:\n%s"),Closure->imageName,strerror(errno));
|
||||
}
|
||||
else Stop(": %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ii->size = img_size;
|
||||
CalcSectors(img_size, &ii->sectors, &ii->inLast);
|
||||
|
||||
if(!(mode & PRINT_MODE))
|
||||
{ if(ii->inLast == 2048)
|
||||
PrintLog(_(": %lld medium sectors.\n"), ii->sectors);
|
||||
else PrintLog(_(": %lld medium sectors and %d bytes.\n"),
|
||||
ii->sectors-1, ii->inLast);
|
||||
}
|
||||
|
||||
/*** Calculate md5sum of the fingerprint sector.
|
||||
Use sector specified by .ecc file if possible,
|
||||
else use built-in default */
|
||||
|
||||
if(!eh)
|
||||
fp_sector = FINGERPRINT_SECTOR;
|
||||
else fp_sector = eh->fpSector;
|
||||
|
||||
LargeSeek(ii->file, fp_sector*2048);
|
||||
|
||||
MD5Init(&md5ctxt);
|
||||
n = LargeRead(ii->file, buf, 2048);
|
||||
|
||||
if(n != 2048)
|
||||
Stop(_("could not read image sector %lld (only %d bytes):\n%s"),
|
||||
fp_sector,n,strerror(errno));
|
||||
MD5Update(&md5ctxt, buf, n);
|
||||
MD5Final(ii->mediumFP, &md5ctxt);
|
||||
if(CheckForMissingSector(buf, fp_sector, NULL, 0) != SECTOR_PRESENT) /* No sector, no md5sum */
|
||||
{ memset(ii->mediumFP, 0 ,16);
|
||||
ii->fpValid=FALSE;
|
||||
}
|
||||
else ii->fpValid=TRUE;
|
||||
LargeSeek(ii->file, 0); /* rewind */
|
||||
|
||||
return ii;
|
||||
}
|
||||
|
||||
void FreeImageInfo(ImageInfo *ii)
|
||||
{
|
||||
if(ii->file)
|
||||
if(!LargeClose(ii->file))
|
||||
Stop(_("Error closing image file:\n%s"), strerror(errno));
|
||||
|
||||
g_free(ii);
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
*** Open the ecc file and fill in the info stuff
|
||||
***/
|
||||
|
||||
EccInfo* OpenEccFile(int mode)
|
||||
{ EccInfo *ei = NULL;
|
||||
int file_flags;
|
||||
|
||||
/*** Sanity check for ecc file reads */
|
||||
|
||||
if(!(mode & WRITEABLE_ECC))
|
||||
{ gint64 ecc_size;
|
||||
|
||||
if(!LargeStat(Closure->eccName, &ecc_size))
|
||||
{ if(!(mode & PRINT_MODE))
|
||||
Stop(_("Can't open %s:\n%s"),Closure->eccName,strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ecc_size < 4096)
|
||||
Stop(_("Invalid or damaged ecc file"));
|
||||
}
|
||||
|
||||
/*** Open the ecc file */
|
||||
|
||||
ei = g_malloc0(sizeof(EccInfo));
|
||||
ei->eh = g_malloc0(sizeof(EccHeader));
|
||||
|
||||
file_flags = mode & WRITEABLE_ECC ? O_RDWR | O_CREAT : O_RDONLY;
|
||||
|
||||
if(!(ei->file = LargeOpen(Closure->eccName, file_flags, IMG_PERMS)))
|
||||
{ FreeEccInfo(ei);
|
||||
ei = NULL;
|
||||
|
||||
if(!(mode & PRINT_MODE)) /* missing ecc file no problem in print mode */
|
||||
Stop(_("Can't open %s:\n%s"),Closure->eccName,strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!(mode & WRITEABLE_ECC))
|
||||
{ int n = LargeRead(ei->file, ei->eh, sizeof(EccHeader));
|
||||
|
||||
if(n != sizeof(EccHeader))
|
||||
{ FreeEccInfo(ei);
|
||||
Stop(_("Can't read ecc header:\n%s"),strerror(errno));
|
||||
}
|
||||
|
||||
/*** Endian annoyance */
|
||||
|
||||
#ifdef HAVE_BIG_ENDIAN
|
||||
SwapEccHeaderBytes(ei->eh);
|
||||
#endif
|
||||
|
||||
/*** See if we can use the ecc file */
|
||||
|
||||
if(strncmp((char*)ei->eh->cookie, "*dvdisaster*", 12))
|
||||
{ FreeEccInfo(ei);
|
||||
Stop(_("Invalid or damaged ecc file"));
|
||||
}
|
||||
|
||||
VerifyVersion(ei->eh,1);
|
||||
|
||||
ei->sectors = uchar_to_gint64(ei->eh->sectors);
|
||||
LargeSeek(ei->file, 0);
|
||||
}
|
||||
|
||||
return ei;
|
||||
}
|
||||
|
||||
void FreeEccInfo(EccInfo *ei)
|
||||
{
|
||||
if(ei->file)
|
||||
if(!LargeClose(ei->file))
|
||||
Stop(_("Error closing error correction file:\n%s"), strerror(errno));
|
||||
|
||||
if(ei->eh) g_free(ei->eh);
|
||||
g_free(ei);
|
||||
}
|
||||
|
||||
/***
|
||||
*** Auxiliary functions
|
||||
***/
|
||||
|
||||
/*
|
||||
* Append the given file suffix if none is already present
|
||||
*/
|
||||
|
||||
char *ApplyAutoSuffix(char *filename, char *suffix)
|
||||
{ char *out;
|
||||
|
||||
if(!filename || !*filename || strrchr(filename, '.'))
|
||||
return filename;
|
||||
|
||||
out = g_strdup_printf("%s.%s",filename,suffix);
|
||||
g_free(filename);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*
|
||||
* See if we can handle the specified .ecc file
|
||||
*/
|
||||
|
||||
int VerifyVersion(EccHeader *eh, int fatal)
|
||||
{
|
||||
if(Closure->version < eh->neededVersion)
|
||||
{ if(fatal)
|
||||
Stop(_("This .ecc file requires dvdisaster V%d.%d.%d or higher.\n"
|
||||
"Please visit http://www.dvdisaster.com for an upgrade."),
|
||||
eh->neededVersion/10000,
|
||||
(eh->neededVersion%10000)/100,
|
||||
eh->neededVersion%100);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove the image file */
|
||||
|
||||
void UnlinkImage(GtkWidget *label)
|
||||
{
|
||||
if(LargeUnlink(Closure->imageName))
|
||||
{ PrintLog(_("\nImage file %s deleted.\n"),Closure->imageName);
|
||||
|
||||
if(Closure->guiMode)
|
||||
SetLabelText(GTK_LABEL(label),
|
||||
_("\nImage file %s deleted.\n"), Closure->imageName);
|
||||
}
|
||||
else
|
||||
{ if(!Closure->guiMode)
|
||||
PrintLog("\n");
|
||||
|
||||
ModalWarning(GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, NULL,
|
||||
_("Image file %s not deleted: %s\n"),
|
||||
Closure->imageName, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user