First attempt at a second-pass option, although it does not seem successful for the time being
This commit is contained in:
parent
3a53962ed2
commit
f0bc221382
3 changed files with 145 additions and 12 deletions
112
src/dvdcopy.cc
112
src/dvdcopy.cc
|
|
@ -32,6 +32,9 @@
|
|||
|
||||
#include <sys/time.h>
|
||||
|
||||
// use of regular expressions !
|
||||
#include <regex.h>
|
||||
|
||||
|
||||
|
||||
#define BUF_BLOCK_SIZE 128
|
||||
|
|
@ -134,11 +137,15 @@ void DVDCopy::copyFile(const DVDFileData * dat, int firstBlock,
|
|||
|
||||
outfile.seek(current_size);
|
||||
size -= current_size;
|
||||
printf("File already partially read: using %d sectors\n",
|
||||
current_size);
|
||||
const char * fmt =
|
||||
(firstBlock > 0 ?
|
||||
"Partial read starting at sector %d\n":
|
||||
"File already partially read: using %d sectors\n");
|
||||
|
||||
printf(fmt, current_size);
|
||||
}
|
||||
if(blockNumber > 0)
|
||||
size = current_size + blockNumber; // we read only the relevant portion
|
||||
size = blockNumber; // we read only the relevant portion
|
||||
switch(dat->domain) {
|
||||
case DVD_READ_INFO_FILE:
|
||||
case DVD_READ_INFO_BACKUP_FILE:
|
||||
|
|
@ -263,7 +270,17 @@ void DVDCopy::copy(const char *device, const char * target)
|
|||
|
||||
void DVDCopy::secondPass(const char *device, const char * target)
|
||||
{
|
||||
|
||||
setup(device, target);
|
||||
readBadSectors();
|
||||
|
||||
for(int i = 0; i < badSectorsList.size(); i++) {
|
||||
BadSectors & bs = badSectorsList[i];
|
||||
printf("Trying to read %d bad sectors from file %s at %d:\n",
|
||||
bs.number,
|
||||
bs.file->fileName().c_str(),
|
||||
bs.start);
|
||||
copyFile(bs.file, bs.start, bs.number);
|
||||
}
|
||||
}
|
||||
|
||||
DVDCopy::~DVDCopy()
|
||||
|
|
@ -278,15 +295,18 @@ DVDCopy::~DVDCopy()
|
|||
delete *i; // Keep it clean;
|
||||
}
|
||||
|
||||
void DVDCopy::openBadSectorsFile(const char * mode)
|
||||
{
|
||||
if(! badSectors) {
|
||||
std::string bsf = targetDirectory + ".bad";
|
||||
badSectors = fopen(bsf.c_str(), mode);
|
||||
}
|
||||
}
|
||||
|
||||
void DVDCopy::registerBadSectors(const DVDFileData * dat,
|
||||
int beg, int size)
|
||||
{
|
||||
if(! badSectors) {
|
||||
std::string bsf = targetDirectory + ".bad";
|
||||
badSectors = fopen(bsf.c_str(), "a");
|
||||
}
|
||||
|
||||
openBadSectorsFile("a");
|
||||
fprintf(badSectors, "%s: %d,%d,%d %d (%d)\n",
|
||||
dat->fileName().c_str(),
|
||||
dat->title,
|
||||
|
|
@ -294,4 +314,78 @@ void DVDCopy::registerBadSectors(const DVDFileData * dat,
|
|||
dat->number,
|
||||
beg, size);
|
||||
fflush(badSectors);
|
||||
|
||||
badSectorsList.push_back(BadSectors(dat, beg, size));
|
||||
}
|
||||
|
||||
int DVDCopy::findFile(int title, dvd_read_domain_t domain, int number)
|
||||
{
|
||||
for(int i = 0; i < files.size(); i++) {
|
||||
const DVDFileData * dat = files[i];
|
||||
if(
|
||||
(dat->title == title) &&
|
||||
(dat->domain == domain) &&
|
||||
(dat->number == number)
|
||||
)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DVDCopy::readBadSectors()
|
||||
{
|
||||
openBadSectorsFile("r");
|
||||
if(! badSectors) {
|
||||
fprintf(stderr, "%s", "No bad sectors file found, "
|
||||
"which is probably good news !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[1024];
|
||||
regex_t re;
|
||||
regmatch_t matches[6];
|
||||
{
|
||||
int er = regcomp(&re, "[^:]+: *([0-9]+),([0-9]+),([0-9]+) *"
|
||||
"([0-9]+) *\\(([0-9]+)\\)",
|
||||
REG_EXTENDED);
|
||||
if(er) {
|
||||
regerror(er, &re, buffer, sizeof(buffer));
|
||||
fprintf(stderr, "Error building the line regexp: %s", buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while(! feof(badSectors)) {
|
||||
fgets(buffer, sizeof(buffer), badSectors);
|
||||
int status = regexec(&re, buffer, sizeof(matches)/sizeof(regmatch_t),
|
||||
matches, 0);
|
||||
if(status) {
|
||||
fprintf(stderr, "error parsing line: %s", buffer);
|
||||
}
|
||||
else {
|
||||
// Make all substrings NULL-terminated:
|
||||
for(int i = 1; i < sizeof(matches)/sizeof(regmatch_t); i++) {
|
||||
if(matches[i].rm_so >= 0)
|
||||
buffer[matches[i].rm_eo] = 0;
|
||||
}
|
||||
|
||||
// No validation whatsoever, but all groups should be here anyway !
|
||||
int title = atoi(buffer + matches[1].rm_so);
|
||||
dvd_read_domain_t domain =
|
||||
(dvd_read_domain_t) atoi(buffer + matches[2].rm_so);
|
||||
int number = atoi(buffer + matches[3].rm_so);
|
||||
|
||||
int beg = atoi(buffer + matches[4].rm_so);
|
||||
int size = atoi(buffer + matches[5].rm_so);
|
||||
|
||||
int idx = findFile(title, domain, number);
|
||||
if(idx < 0) {
|
||||
fprintf(stderr, "Found no match for file %d,%d,%d\n",
|
||||
title, domain, number);
|
||||
}
|
||||
else
|
||||
badSectorsList.push_back(BadSectors(files[idx], beg, size));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ class DVDCopy {
|
|||
/// In the hope to be read again...
|
||||
FILE * badSectors;
|
||||
|
||||
/// Writes a bad sector list to the file
|
||||
/// Writes a bad sector list to the file, and add them to the
|
||||
/// badSectors list.
|
||||
void registerBadSectors(const DVDFileData * dat,
|
||||
int beg, int size);
|
||||
|
||||
|
|
@ -55,10 +56,40 @@ class DVDCopy {
|
|||
/// The underlying files of the source
|
||||
std::vector<DVDFileData *> files;
|
||||
|
||||
/// Subclass representing a single line in a bad sectors file.
|
||||
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;
|
||||
|
||||
/// reads the bad sectors from the bad sectors file
|
||||
void readBadSectors();
|
||||
|
||||
/// Opens the bad sectors file with the given mode, if not open already.
|
||||
///
|
||||
/// @todo There should be a way to track the mode last used in order
|
||||
/// not to try to read from a descriptor open for writing.
|
||||
void openBadSectorsFile(const char * mode);
|
||||
|
||||
/// Finds the index of the file referred to by the title, domain,
|
||||
/// number triplet. Returns -1 if not found.
|
||||
int findFile(int title, dvd_read_domain_t domain, int number);
|
||||
|
||||
public:
|
||||
|
||||
DVDCopy();
|
||||
|
|
|
|||
12
src/main.cc
12
src/main.cc
|
|
@ -43,6 +43,7 @@ static struct option long_options[] = {
|
|||
{ "help", 0, NULL, 'h'},
|
||||
{ "eject", 0, NULL, 'e' },
|
||||
{ "list", 1, NULL, 'l' },
|
||||
{ "second-pass", 0, NULL, 's' },
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
|
@ -51,9 +52,10 @@ int main(int argc, char ** argv)
|
|||
DVDCopy dvd;
|
||||
|
||||
int option;
|
||||
int secondPass = 0;
|
||||
|
||||
do {
|
||||
option = getopt_long(argc, argv, "hel:",
|
||||
option = getopt_long(argc, argv, "hel:s",
|
||||
long_options, NULL);
|
||||
|
||||
switch(option) {
|
||||
|
|
@ -70,6 +72,9 @@ int main(int argc, char ** argv)
|
|||
dvd.displayFiles();
|
||||
}
|
||||
return 0;
|
||||
case 's':
|
||||
secondPass = 1;
|
||||
break;
|
||||
}
|
||||
} while(option != -1);
|
||||
if(argc != optind + 2) {
|
||||
|
|
@ -77,6 +82,9 @@ int main(int argc, char ** argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
dvd.copy(argv[optind], argv[optind+1]);
|
||||
if(secondPass)
|
||||
dvd.secondPass(argv[optind], argv[optind+1]);
|
||||
else
|
||||
dvd.copy(argv[optind], argv[optind+1]);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue