New upstream version 0.79.5
This commit is contained in:
319
scsi-layer.c
319
scsi-layer.c
@@ -1,22 +1,23 @@
|
||||
/* dvdisaster: Additional error correction for optical media.
|
||||
* Copyright (C) 2004-2012 Carsten Gnoerlich.
|
||||
* Project home page: http://www.dvdisaster.com
|
||||
* Email: carsten@dvdisaster.com -or- cgnoerlich@fsfe.org
|
||||
* Copyright (C) 2004-2015 Carsten Gnoerlich.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* Email: carsten@dvdisaster.org -or- cgnoerlich@fsfe.org
|
||||
* Project homepage: http://www.dvdisaster.org
|
||||
*
|
||||
* This file is part of dvdisaster.
|
||||
*
|
||||
* dvdisaster 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* dvdisaster 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.
|
||||
* along with dvdisaster. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dvdisaster.h"
|
||||
@@ -29,7 +30,7 @@
|
||||
***/
|
||||
|
||||
static int query_type(DeviceHandle*, int);
|
||||
static unsigned int query_size(DeviceHandle*);
|
||||
static gint64 query_size(Image*);
|
||||
static int query_copyright(DeviceHandle*);
|
||||
|
||||
static int read_dvd_sector(DeviceHandle*, unsigned char*, int, int);
|
||||
@@ -135,7 +136,7 @@ int InquireDevice(DeviceHandle *dh, int probe_only)
|
||||
|
||||
if(ab->buf[0] != 0x05 && !probe_only)
|
||||
{ PrintCLI("\n");
|
||||
if(ab->buf[0]) Stop(_("Device %s (%s) is not a CDROM drive."),dh->device,ibuf);
|
||||
if(ab->buf[0]) Stop(_("Device %s (%s) is not an optical drive."),dh->device,ibuf);
|
||||
else Stop(_("Device %s (%s) is a hard disk."),dh->device,ibuf);
|
||||
}
|
||||
}
|
||||
@@ -157,7 +158,7 @@ static int try_fallback_type_check(DeviceHandle *dh)
|
||||
{ AlignedBuffer *ab;
|
||||
Sense *sense = &dh->sense;
|
||||
unsigned char cmd[MAX_CDB_SIZE];
|
||||
unsigned int length;
|
||||
int length;
|
||||
|
||||
Verbose("# *** try_fallback_type_check(%s) ***\n", dh->devinfo);
|
||||
|
||||
@@ -190,8 +191,6 @@ static int try_fallback_type_check(DeviceHandle *dh)
|
||||
|
||||
length = ab->buf[0]<<8 | ab->buf[1];
|
||||
length += 2;
|
||||
length_align(&length);
|
||||
|
||||
if(length != 4100) /* not a BD */
|
||||
{ Verbose("# allocation length = %d != 4100 -> not a BD type medium.\n", length);
|
||||
goto try_dvd;
|
||||
@@ -422,7 +421,7 @@ static int query_incomplete(DeviceHandle *dh, int probe_only)
|
||||
|
||||
status = dh->read(dh, ab->buf, 16, 1);
|
||||
if(status)
|
||||
{ Verbose("# Readiing the ISO root sector failed\n");
|
||||
{ Verbose("# Reading the ISO root sector failed\n");
|
||||
FreeAlignedBuffer(ab);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -479,7 +478,6 @@ static int query_cd(DeviceHandle *dh, int probe_only)
|
||||
length = buf[0]<<8 | buf[1];
|
||||
length += 2 ; /* MMC3: "Disc information length excludes itself" */
|
||||
length_align(&length);
|
||||
|
||||
Verbose("#CD: size returned is %d\n", length);
|
||||
|
||||
if(length>1024) /* don't let the drive hack us using a buffer overflow ;-) */
|
||||
@@ -538,7 +536,6 @@ static int query_cd(DeviceHandle *dh, int probe_only)
|
||||
length = buf[0]<<8 | buf[1];
|
||||
length += 2; /* MMC3: "Disc information length excludes itself" */
|
||||
length_align(&length);
|
||||
|
||||
Verbose("#CD: size returned is %d\n", length);
|
||||
|
||||
if(length < 15)
|
||||
@@ -554,8 +551,6 @@ static int query_cd(DeviceHandle *dh, int probe_only)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
length = 16; /* Works around Windows (and possibly other OS) driver issues */
|
||||
|
||||
memset(cmd, 0, MAX_CDB_SIZE);
|
||||
cmd[0] = 0x43; /* READ TOC/PMA/ATIP */
|
||||
cmd[1] = 0x02; /* TIME bit required for this format */
|
||||
@@ -975,7 +970,6 @@ static int query_bd(DeviceHandle *dh, int probe_only)
|
||||
length = buf[0]<<8 | buf[1];
|
||||
length += 2;
|
||||
length_align(&length);
|
||||
|
||||
Verbose("#BD: disc structure query succeeded, length %d bytes\n", length);
|
||||
|
||||
/* Do the real query */
|
||||
@@ -1082,6 +1076,7 @@ static int query_type(DeviceHandle *dh, int probe_only)
|
||||
Verbose("# trying READ DISC INFORMATION for size\n");
|
||||
if(SendPacket(dh, cmd, 10, buf, MIN_TRANSFER_LEN, sense, DATA_READ) == 0)
|
||||
{ length = buf[0]<<8 | buf[1];
|
||||
length_align(&length);
|
||||
|
||||
Verbose("# size returned is %d\n", length);
|
||||
|
||||
@@ -1194,7 +1189,6 @@ static int query_blank(DeviceHandle *dh)
|
||||
length = buf[0]<<8 | buf[1];
|
||||
length += 2; /* MMC3: "Disc information length excludes itself" */
|
||||
length_align(&length);
|
||||
|
||||
Verbose("#CD: size returned is %d\n", length);
|
||||
|
||||
if(length < 15 || length > 1024) /* implausible */
|
||||
@@ -1250,7 +1244,6 @@ static int query_blank(DeviceHandle *dh)
|
||||
length = buf[0]<<8 | buf[1];
|
||||
length += 2; /* MMC3: "Disc information length excludes itself" */
|
||||
length_align(&length);
|
||||
|
||||
Verbose("#DVD: size returned is %d\n", length);
|
||||
|
||||
memset(cmd, 0, MAX_CDB_SIZE);
|
||||
@@ -1782,11 +1775,14 @@ static void evaluate_results(int res0, int res1, int *result, char **msg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the medium size.
|
||||
* Do a READ CAPACITY.
|
||||
* Needs to be separated as we need this value to invoke the RS02/RS03
|
||||
* size heuristics which in turn must be executed before calling query_size().
|
||||
*/
|
||||
|
||||
static unsigned int query_size(DeviceHandle *dh)
|
||||
{ Sense sense;
|
||||
static void read_capacity(Image *image)
|
||||
{ DeviceHandle *dh = image->dh;
|
||||
Sense sense;
|
||||
AlignedBuffer *ab = CreateAlignedBuffer(2048);
|
||||
unsigned char *buf = ab->buf;
|
||||
unsigned char cmd[MAX_CDB_SIZE];
|
||||
@@ -1794,7 +1790,8 @@ static unsigned int query_size(DeviceHandle *dh)
|
||||
|
||||
/*** Query size by doing READ CAPACITY */
|
||||
|
||||
Verbose("# *** query_size(%s) ***\n", dh->devinfo);
|
||||
Verbose("# *** read_capacity(%s) ***\n", dh->devinfo);
|
||||
|
||||
memset(cmd, 0, MAX_CDB_SIZE);
|
||||
cmd[0] = 0x25; /* READ CAPACITY */
|
||||
|
||||
@@ -1802,10 +1799,12 @@ static unsigned int query_size(DeviceHandle *dh)
|
||||
{ FreeAlignedBuffer(ab);
|
||||
Stop(_("%s\nCould not query medium size.\n"),
|
||||
GetSenseString(sense.sense_key, sense.asc, sense.ascq, TRUE));
|
||||
return 0;
|
||||
dh->readCapacity = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
dh->readCapacity = (gint64)(buf[0]<<24 | buf[1]<<16 | buf[2]<<8 | buf[3]);
|
||||
Verbose(" -> %lld\n", dh->readCapacity);
|
||||
FreeAlignedBuffer(ab);
|
||||
|
||||
/*** Validate capacity */
|
||||
@@ -1819,48 +1818,45 @@ static unsigned int query_size(DeviceHandle *dh)
|
||||
if(dh->mainType == DVD && dh->layers == 2 && dh->readCapacity > MAX_DVD_DL_SIZE)
|
||||
implausible = TRUE;
|
||||
|
||||
if(implausible)
|
||||
if(implausible && !dh->simImage)
|
||||
{ LogWarning(_("READ CAPACITY: implausible medium size, %lld sectors\n"),
|
||||
(gint64)dh->readCapacity);
|
||||
dh->readCapacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*** If RS02 header search is enabled and we can find an appropriate header,
|
||||
use it as an authoritative source for the medium size. */
|
||||
/*
|
||||
* Query the medium size.
|
||||
*/
|
||||
|
||||
if(Closure->querySize >= 2)
|
||||
{ if(dh->rs02Size <= 0)
|
||||
{ gint64 last_sector = MAX(dh->readCapacity, dh->userAreaSize);
|
||||
|
||||
if(last_sector > 0)
|
||||
dh->rs02Size = MediumLengthFromRS02(dh, last_sector);
|
||||
}
|
||||
else Verbose("Root header search succeeded!\n");
|
||||
if(dh->rs02Size > 0)
|
||||
{ Verbose("Medium size obtained from ECC header: %lld sectors\n", dh->rs02Size);
|
||||
return dh->rs02Size;
|
||||
}
|
||||
else Verbose("Medium size could NOT be determined from ECC header.\n");
|
||||
}
|
||||
else
|
||||
{ if(dh->rs02Size > 0)
|
||||
{ Verbose("Exhaustive ECC header search disabled, but root header search succeeded!\n");
|
||||
Verbose("Medium size obtained from ECC header: %lld sectors\n", dh->rs02Size);
|
||||
return dh->rs02Size;
|
||||
}
|
||||
Verbose("Skipping medium size determination from ECC header.\n");
|
||||
static gint64 query_size(Image *image)
|
||||
{ DeviceHandle *dh = image->dh;
|
||||
|
||||
Verbose("# *** query_size(%s) ***\n", dh->devinfo);
|
||||
|
||||
/*** If an EccHeader was already found and the codec specified
|
||||
the overall image size, use that as an authoritative source
|
||||
for the medium size. */
|
||||
|
||||
if(image->expectedSectors > 0)
|
||||
{ Verbose("Medium size obtained from ECC header: %lld sectors\n", image->expectedSectors);
|
||||
return image->expectedSectors;
|
||||
}
|
||||
else Verbose("Medium size could NOT be determined from ECC header.\n");
|
||||
|
||||
/*** If ISO/UDF filesystem parsing is enabled try this next. */
|
||||
/*** Try getting the size from the ISO/UDF filesystem. */
|
||||
|
||||
if(Closure->querySize >= 1)
|
||||
{ if(dh->isoInfo)
|
||||
{ Verbose("Medium size obtained from ISO/UDF file system: %d sectors\n",
|
||||
dh->isoInfo->volumeSize);
|
||||
return dh->isoInfo->volumeSize;
|
||||
if(image->isoInfo)
|
||||
{ if(Closure->ignoreIsoSize)
|
||||
{ Verbose("Note: NOT examining ISO/UDF filesystem as requested by user option!\n");
|
||||
}
|
||||
else Verbose("Medium size could NOT be determined from ISO/UDF filesystem.\n");
|
||||
} else Verbose("Skipping medium size determination from ISO/UDF filesystem.\n");
|
||||
else
|
||||
{ Verbose("Medium size obtained from ISO/UDF file system: %d sectors\n",
|
||||
image->isoInfo->volumeSize);
|
||||
return image->isoInfo->volumeSize;
|
||||
}
|
||||
}
|
||||
else Verbose("Medium size could NOT be determined from ISO/UDF filesystem.\n");
|
||||
|
||||
/*** If everything else fails, query the drive. */
|
||||
|
||||
@@ -2000,51 +1996,50 @@ static unsigned int query_size(DeviceHandle *dh)
|
||||
*/
|
||||
|
||||
gint64 CurrentMediumSize(int get_blank_size)
|
||||
{ DeviceHandle *dh = NULL;
|
||||
{ Image *image;
|
||||
gint64 size;
|
||||
|
||||
#ifdef SYS_UNKNOWN
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
dh = OpenDevice(Closure->device);
|
||||
if(!dh) return 0;
|
||||
if(InquireDevice(dh, 1) != 0x05)
|
||||
{ CloseDevice(dh);
|
||||
image = OpenImageFromDevice(Closure->device);
|
||||
if(!image) return 0;
|
||||
if(InquireDevice(image->dh, 1) != 0x05)
|
||||
{ CloseImage(image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Avoid size query on unknown media */
|
||||
|
||||
if(!query_type(dh, 1) && !get_blank_size)
|
||||
{ CloseDevice(dh);
|
||||
if(!query_type(image->dh, 1) && !get_blank_size)
|
||||
{ CloseImage(image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* A size query on unsupported media would derail */
|
||||
|
||||
if((dh->subType == UNSUPPORTED) && !get_blank_size)
|
||||
{ CloseDevice(dh);
|
||||
if((image->dh->subType == UNSUPPORTED) && !get_blank_size)
|
||||
{ CloseImage(image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We can return either the image size or the size of blank media. */
|
||||
|
||||
if(get_blank_size)
|
||||
{ if(!query_blank(dh))
|
||||
{ CloseDevice(dh);
|
||||
{ if(!query_blank(image->dh))
|
||||
{ CloseImage(image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = dh->blankCapacity;
|
||||
size = image->dh->blankCapacity;
|
||||
}
|
||||
else
|
||||
{ if(Closure->querySize >= 1) /* parseUDF or better requested */
|
||||
ExamineUDF(dh);
|
||||
size = query_size(dh);
|
||||
{ read_capacity(image);
|
||||
size = query_size(image);
|
||||
}
|
||||
|
||||
CloseDevice(dh);
|
||||
CloseImage(image);
|
||||
|
||||
return size;
|
||||
}
|
||||
@@ -2119,7 +2114,7 @@ void LoadMedium(DeviceHandle *dh, int load)
|
||||
if(load) return;
|
||||
|
||||
/* Some drives lock the tray when it was closed via START STOP.
|
||||
That sucks especially under newer Linux kernels as we need to
|
||||
That sucks especially under newer GNU/Linux kernels as we need to
|
||||
be root to unlock it. Try anyways; maybe this changes in
|
||||
future kernels. */
|
||||
|
||||
@@ -2270,9 +2265,19 @@ static int read_cd_sector(DeviceHandle *dh, unsigned char *buf, int lba, int nse
|
||||
ret = SendPacket(dh, cmd, 12, buf, 2048*nsectors, sense, DATA_READ);
|
||||
|
||||
#if 0
|
||||
if(lba==16000) /* fixme */
|
||||
{ buf[240]^=255;
|
||||
}
|
||||
#define BORK 34999
|
||||
if(lba<=BORK && BORK<lba+nsectors) /* fixme */
|
||||
{ int offset = 2048*(BORK-lba);
|
||||
buf[offset+240]^=255;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define BORK2 300
|
||||
if(lba<=BORK2 && BORK2<lba+nsectors) /* fixme */
|
||||
{ int offset = 2048*(BORK2-lba);
|
||||
buf[offset+240]^=255;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(ret<0) RememberSense(sense->sense_key, sense->asc, sense->ascq);
|
||||
@@ -2558,12 +2563,13 @@ int ReadSectorsFast(DeviceHandle *dh, unsigned char *buf, gint64 s, int nsectors
|
||||
*** Open the device and query some of its properties.
|
||||
***/
|
||||
|
||||
DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
{ DeviceHandle *dh = NULL;
|
||||
Image* OpenImageFromDevice(char *device)
|
||||
{ Image *image = NULL;
|
||||
DeviceHandle *dh = NULL;
|
||||
|
||||
/* Open the device. */
|
||||
|
||||
Verbose("# *** OpenAndQueryDevice(%s) ***\n", device);
|
||||
Verbose("# *** OpenImageFromDevice(%s) ***\n", device);
|
||||
dh = OpenDevice(device);
|
||||
if(!dh) return NULL;
|
||||
|
||||
@@ -2573,25 +2579,26 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
if(!TestUnitReady(dh))
|
||||
{ if( dh->sense.sense_key == 2 /* Not Ready */
|
||||
&& dh->sense.asc == 0x3a) /* Medium not present */
|
||||
Stop(_("Device %s: no medium present\n"), device);
|
||||
else Stop(_("Device %s does not become ready:\n%s\n\n"), device,
|
||||
GetSenseString(dh->sense.sense_key, dh->sense.asc, dh->sense.ascq, FALSE));
|
||||
{ CloseDevice(dh);
|
||||
Stop(_("Device %s: no medium present\n"), device);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{ CloseDevice(dh);
|
||||
Stop(_("Device %s does not become ready:\n%s\n\n"), device,
|
||||
GetSenseString(dh->sense.sense_key, dh->sense.asc, dh->sense.ascq, FALSE));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SYS_LINUX
|
||||
PrintLog(_("\nDevice: %s, %s\n"),device, dh->devinfo);
|
||||
#endif
|
||||
|
||||
#ifdef SYS_MINGW
|
||||
PrintLog(_("\nDevice: %s (%s), %s\n"),
|
||||
device, dh->aspiUsed ? "ASPI" : "SPTI", dh->devinfo);
|
||||
#endif
|
||||
|
||||
/* Query the type and fail immediately if incompatible medium is found
|
||||
so that the later tests are not derailed by the wrong medium type */
|
||||
|
||||
if(!query_type(dh, 0))
|
||||
{ Stop(_("Drive failed to report media type."));
|
||||
{ CloseDevice(dh);
|
||||
Stop(_("Drive failed to report media type."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2614,6 +2621,14 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the Image structure.
|
||||
From here we need it to store additional information about the image. */
|
||||
|
||||
image = g_malloc0(sizeof(Image));
|
||||
image->type = IMAGE_MEDIUM;
|
||||
image->fpSector = -1;
|
||||
image->dh = dh;
|
||||
|
||||
/* Activate raw reading features if possible,
|
||||
output selected reading mode */
|
||||
|
||||
@@ -2623,7 +2638,7 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
if(Closure->readRaw)
|
||||
{ dh->rawBuffer = CreateRawBuffer(MAX_RAW_TRANSFER_SIZE);
|
||||
|
||||
dh->rawBuffer->validFP = GetMediumFingerprint(dh, dh->rawBuffer->mediumFP, FINGERPRINT_SECTOR);
|
||||
dh->rawBuffer->validFP = GetImageFingerprint(image, dh->rawBuffer->mediumFP, FINGERPRINT_SECTOR);
|
||||
|
||||
if(dh->subType == XA21)
|
||||
{ dh->rawBuffer->dataOffset = 24;
|
||||
@@ -2653,11 +2668,14 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
|
||||
/* Examine medium type */
|
||||
|
||||
if(Closure->querySize >= 1) /* parseUDF or better requested */
|
||||
ExamineUDF(dh);
|
||||
GetImageFingerprint(image, NULL, FINGERPRINT_SECTOR);
|
||||
ExamineUDF(image);
|
||||
|
||||
read_capacity(image); /* Needed for ExamineECC() ! */
|
||||
ExamineECC(image);
|
||||
|
||||
Verbose("# Calling query_size()\n");
|
||||
dh->sectors = query_size(dh);
|
||||
dh->sectors = query_size(image);
|
||||
Verbose("# returned: %lld sectors\n", dh->sectors);
|
||||
|
||||
switch(dh->subType & MAIN_TYPE_MASK)
|
||||
@@ -2665,16 +2683,16 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
case DVD:
|
||||
case CD:
|
||||
{ char *tmp;
|
||||
if(!dh->isoInfo) // || dh->rs02Size > 0)
|
||||
if(!image->isoInfo) // || dh->rs02Size > 0)
|
||||
tmp = g_strdup_printf(_("Medium: %s, %lld sectors%s"),
|
||||
dh->typeDescr, dh->sectors,
|
||||
dh->rs02Size ? ", Ecc" : "");
|
||||
image->expectedSectors ? ", Ecc" : ""); //fixme: validate
|
||||
else
|
||||
tmp = g_strdup_printf(_("Medium \"%s\": %s, %lld sectors%s created %s"),
|
||||
dh->isoInfo->volumeLabel,
|
||||
image->isoInfo->volumeLabel,
|
||||
dh->typeDescr, dh->sectors,
|
||||
dh->rs02Size ? ", Ecc," : ",",
|
||||
dh->isoInfo->creationDate);
|
||||
image->expectedSectors ? ", Ecc," : ",", //fixme: validate
|
||||
image->isoInfo->creationDate);
|
||||
|
||||
if(dh->manuID[0] && dh->manuID[0] != '-')
|
||||
dh->mediumDescr = g_strdup_printf("%s, %s %s.", tmp, _("Manuf.-ID:"), dh->manuID);
|
||||
@@ -2688,15 +2706,16 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
{ char *td = alloca(strlen(dh->typeDescr)+1);
|
||||
|
||||
strcpy(td, dh->typeDescr);
|
||||
CloseDevice(dh);
|
||||
CloseImage(image);
|
||||
Stop(_("This software does not support \"%s\" type media."), td);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(dh->mainType == DVD && query_copyright(dh))
|
||||
{ CloseDevice(dh);
|
||||
{ CloseImage(image);
|
||||
Stop(_("This software does not support encrypted media.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the bitmap of simulated defects */
|
||||
@@ -2704,97 +2723,7 @@ DeviceHandle* OpenAndQueryDevice(char *device)
|
||||
if(Closure->simulateDefects)
|
||||
dh->defects = SimulateDefects(dh->sectors);
|
||||
|
||||
return dh;
|
||||
}
|
||||
|
||||
/***
|
||||
*** Open the device and query some of the medium properties.
|
||||
***
|
||||
* Does NOT gather enough information for actually reading from the device;
|
||||
* use OpenAndQueryDevice() for that.
|
||||
*/
|
||||
|
||||
DeviceHandle* QueryMediumInfo(char *device)
|
||||
{ DeviceHandle *dh = NULL;
|
||||
|
||||
/* Open the device. */
|
||||
|
||||
Verbose("# *** QueryMediumInfo(%s) ***\n", device);
|
||||
dh = OpenDevice(device);
|
||||
if(!dh) return NULL;
|
||||
|
||||
InquireDevice(dh, 0);
|
||||
|
||||
if(!TestUnitReady(dh))
|
||||
{ if( dh->sense.sense_key == 2 /* Not Ready */
|
||||
&& dh->sense.asc == 0x3a) /* Medium not present */
|
||||
Stop(_("Device %s: no medium present\n"), device);
|
||||
else Stop(_("Device %s does not become ready:\n%s\n\n"), device,
|
||||
GetSenseString(dh->sense.sense_key, dh->sense.asc, dh->sense.ascq, FALSE));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* General type detection */
|
||||
|
||||
query_type(dh, 1);
|
||||
query_blank(dh);
|
||||
|
||||
/* Examine medium size (only on known/handled formats) */
|
||||
|
||||
if(dh->subType != UNSUPPORTED)
|
||||
{ if(Closure->querySize >= 1) /* parseUDF or better requested */
|
||||
ExamineUDF(dh);
|
||||
|
||||
dh->sectors = query_size(dh);
|
||||
}
|
||||
|
||||
return dh;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the md5sum from the specified sector. Results are cached in the
|
||||
* DeviceHandle as multiple queries may occur.
|
||||
*/
|
||||
|
||||
int GetMediumFingerprint(DeviceHandle *dh, guint8 *fp_out, gint64 sector)
|
||||
{ AlignedBuffer *ab;
|
||||
int status;
|
||||
|
||||
/* Sector already cached? */
|
||||
|
||||
if(dh->fpSector == sector)
|
||||
switch(dh->fpState)
|
||||
{ case 0: /* not read */
|
||||
break;
|
||||
case 1: /* unreadable */
|
||||
memset(fp_out, 0, 16);
|
||||
return FALSE;
|
||||
case 2: /* already cached */
|
||||
memcpy(fp_out, dh->mediumFP, 16);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ab = CreateAlignedBuffer(2048);
|
||||
status = ReadSectorsFast(dh, ab->buf, sector, 1);
|
||||
|
||||
dh->fpSector = sector;
|
||||
if(status) /* read error */
|
||||
{ dh->fpState = 1;
|
||||
}
|
||||
else
|
||||
{ struct MD5Context md5ctxt;
|
||||
|
||||
dh->fpState = 2;
|
||||
|
||||
MD5Init(&md5ctxt);
|
||||
MD5Update(&md5ctxt, ab->buf, 2048);
|
||||
MD5Final(dh->mediumFP, &md5ctxt);
|
||||
memcpy(fp_out, dh->mediumFP, 16);
|
||||
}
|
||||
|
||||
FreeAlignedBuffer(ab);
|
||||
|
||||
return dh->fpState == 2;
|
||||
return image;
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
Reference in New Issue
Block a user