Make --scan output a much smaller list of bad sectors

This commit is contained in:
Vincent Fourmond 2013-01-09 22:26:54 +01:00
parent 9a72df5d87
commit 6a2f279ea6
2 changed files with 85 additions and 38 deletions

View file

@ -44,6 +44,33 @@
int debug = 1;
std::string BadSectors::toString() const
{
char buffer[1024];
snprintf(buffer, sizeof(buffer),
"%s: %d,%d,%d %d (%d)",
file->fileName().c_str(),
file->title,
file->domain,
file->number,
start, number);
return std::string(buffer);
}
bool BadSectors::tryMerge(const BadSectors & follower)
{
if(follower.file != file)
return false;
if(start + number != follower.start)
return false;
number += follower.number;
return true;
}
//////////////////////////////////////////////////////////////////////
DVDCopy::DVDCopy() : badSectors(NULL)
{
reader = NULL;
@ -219,8 +246,6 @@ void DVDCopy::scanForBadSectors(const char *device,
{
setup(device, NULL);
badSectors = fopen(badSectorsFile, "w");
for(std::vector<DVDFileData *>::iterator i = files.begin();
i != files.end(); i++) {
DVDFileData * dat = *i;
@ -241,20 +266,35 @@ void DVDCopy::scanForBadSectors(const char *device,
if(buffer[2] == 1 && buffer[first_pes_offset + 3] == 1)
continue;
else
registerBadSectors(dat, blk + i, 1);
registerBadSectors(dat, blk + i, 1, true);
}
};
auto failure = [this](int blk, int nb,
const DVDFileData * dat) {
registerBadSectors(dat, blk, nb);
registerBadSectors(dat, blk, nb, true);
};
file->walkFile(0, sz, 128,
success, failure);
/// @todo Compact the bad sectors file (this should be done at the
/// very end, rewriting the whole file)
}
// OK, now, we have a list of bad sectors. We simplify it
std::vector<BadSectors> simplifiedBad;
for(int i = 0; i < badSectorsList.size(); i++) {
const BadSectors & bs = badSectorsList[i];
if(!i)
simplifiedBad.push_back(bs);
else {
if(! simplifiedBad.back().tryMerge(bs))
simplifiedBad.push_back(bs);
}
}
FILE * bad = fopen(badSectorsFile, "w");
for(int i = 0; i < simplifiedBad.size(); i++)
fprintf(bad, "%s\n",
simplifiedBad[i].toString().c_str());
}
DVDCopy::~DVDCopy()
@ -277,18 +317,15 @@ void DVDCopy::openBadSectorsFile(const char * mode)
}
void DVDCopy::registerBadSectors(const DVDFileData * dat,
int beg, int size)
int beg, int size, bool dontWrite)
{
openBadSectorsFile("a");
fprintf(badSectors, "%s: %d,%d,%d %d (%d)\n",
dat->fileName().c_str(),
dat->title,
dat->domain,
dat->number,
beg, size);
fflush(badSectors);
badSectorsList.push_back(BadSectors(dat, beg, size));
if(! dontWrite) {
openBadSectorsFile("a");
fprintf(badSectors, "%s\n",
badSectorsList.back().toString().c_str());
fflush(badSectors);
}
}
int DVDCopy::findFile(int title, dvd_read_domain_t domain, int number)

View file

@ -22,6 +22,33 @@
#include "dvdreader.hh"
/// Class representing a series of consecutive bad sectors.
///
/// @todo Write to- and from- string methods.
class BadSectors {
public:
/// The underlying DVD file (ie something in the files list)
const DVDFileData * file;
/// The starting sector
int start;
/// The number of bad sectors;
int number;
BadSectors(const DVDFileData * f, int s, int n) :
file(f), start(s), number(n) {;}
/// Transform into a string
std::string toString() const;
/// If the given bad sector is next to this one, appends it and
/// return true, else return false
bool tryMerge(const BadSectors & follower);
};
/// Handles the actual copying job, from a source to a target.
class DVDCopy {
/// Copies one file.
@ -47,10 +74,12 @@ class DVDCopy {
/// In the hope to be read again...
FILE * badSectors;
/// Writes a bad sector list to the file, and add them to the
/// badSectors list.
/// Writes a bad sector list to the bad sectors file (unless
/// dontWrite is true), and add them to the badSectors list (in any
/// case).
void registerBadSectors(const DVDFileData * dat,
int beg, int size);
int beg, int size,
bool dontWrite = false);
/// sets up the reader and gets the list of files, and sets up the
@ -60,25 +89,6 @@ class DVDCopy {
/// The underlying files of the source
std::vector<DVDFileData *> files;
/// Subclass representing a single line in a bad sectors file.
///
/// @todo Write to- and from- string methods.
class BadSectors {
public:
/// The underlying DVD file (ie something in the files list)
const DVDFileData * file;
/// The starting sector
int start;
/// The number of bad sectors;
int number;
BadSectors(const DVDFileData * f, int s, int n) :
file(f), start(s), number(n) {;}
};
/// The list of bad sectors, either read from the bad sectors file
/// or directly populated registerBadSectors
std::vector<BadSectors> badSectorsList;