15 years ago I've accidently deleted an XFS drive full of recordings. And even in those (*.vdr) days foremost wasn't the most successful tool in order to recover recordings.
What I've done:
1. I've made an (dd-) image
2. I used a modified version of genindex to scan the image
The result where thousands of small video files (the number depends on the degree of fragmentation of your drive).
This was working fairly well, but most of the recordings were not worth recovering because I had to solve the puzzle of concatinating dozens of files (out of the thousands) in the correct order.
But if it helps you here is my patch:
diff -ur genindex-0.1.3.orig/file.c genindex-0.1.3/file.c
--- genindex-0.1.3.orig/file.c 2006-06-01 22:09:10.000000000 +0200
+++ genindex-0.1.3/file.c 2008-11-19 14:59:52.000000000 +0100
@@ -181,16 +181,20 @@
cFileName::~cFileName()
{
+ printf("====>close %s<====\n", filename);
close(fd);
}
-int cFileName::Open(void)
+int cFileName::Open(off64_t xxx = 0)
{
close(fd); fd=-1;
cString filename;
if(input) filename=input;
else filename=cString::sprintf(FILENAME,fileno);
fd=open64(filename,O_RDONLY);
+ if (xxx > 0) {
+ lseek64(fd,xxx,SEEK_SET);
+ }
if(fd>=0) {
struct stat64 st;
if(fstat64(fd,&st)==0) {
diff -ur genindex-0.1.3.orig/file.h genindex-0.1.3/file.h
--- genindex-0.1.3.orig/file.h 2006-06-01 17:12:25.000000000 +0200
+++ genindex-0.1.3/file.h 2008-11-19 15:01:15.000000000 +0100
@@ -54,12 +54,13 @@
public:
cFileName(const char *Input, bool LargeOK);
~cFileName();
- int Open(void);
+ int Open(off64_t);
int NextFile(void);
int OpenWrite(void);
int NextWriteFile(void);
int Skip(int nr, int off);
int FileNumber(void) { return fileno; }
+ void SetFileNumber(int i) {fileno = i;}
long long FileSize(void) { return size; }
};
Only in genindex-0.1.3: file.o
Only in genindex-0.1.3: genindex
diff -ur genindex-0.1.3.orig/genindex.c genindex-0.1.3/genindex.c
--- genindex-0.1.3.orig/genindex.c 2006-06-02 15:44:31.000000000 +0200
+++ genindex-0.1.3/genindex.c 2008-11-19 15:00:58.000000000 +0100
@@ -41,6 +41,8 @@
char *destdir=0;
char *input=0;
int splitsize=2000;
+long long startat=0;
+int firstnum=1;
bool rewrite=false;
bool quiet=false;
@@ -61,6 +63,7 @@
//
unsigned int sSize;
int splitOffset;
+ long long startOffset;
bool pstart;
//
unsigned char buff[KILOBYTE(256)];
@@ -77,7 +80,7 @@
public:
cGenIndex(void);
~cGenIndex();
- void Work(void);
+ void Work(off64_t);
void Skip(int type);
};
@@ -86,6 +89,7 @@
index=new cIndex(destdir);
fileName=new cFileName(input,input && rewrite);
writeName=new cFileName(destdir,true);
+ writeName->SetFileNumber(firstnum);
if(rewrite) {
SetDefaultRule(prSkip);
@@ -124,7 +128,7 @@
return replayFile>=0;
}
-void cGenIndex::Work(void)
+void cGenIndex::Work(off64_t startat = 0)
{
eof=error=pstart=false;
memset(fileSize,0,sizeof(fileSize));
@@ -137,14 +141,16 @@
}
}
- replayFile=fileName->Open();
+ readOffset=startat;
+
+ replayFile=fileName->Open(readOffset);
readNo=fileName->FileNumber();
fileSize[readNo]=fileName->FileSize();
- readOffset=0;
fileNo=rewrite ? 1 : readNo;
fileOffset=0;
splitOffset=splitsize*MEGABYTE(1);
+ startOffset=startat*MEGABYTE(1);
sSize=0;
if(replayFile>=0) {
@@ -236,7 +242,7 @@
}
if(rewrite) {
- if(scan && fileOffset>=splitOffset && (pstart || sSize)) {
+ if(scan && (fileOffset>=splitOffset || nextFile) && (pstart || sSize)) {
if(sSize+len>sizeof(store)) {
printf("Oops! Packet buffer overflow\n");
error=true;
@@ -246,7 +252,7 @@
sSize+=len;
}
else {
- if(fileOffset>=splitOffset && sSize && ftype==I_FRAME) {
+ if((fileOffset>=splitOffset || nextFile) && sSize && ftype==I_FRAME) {
writeFile=writeName->NextWriteFile();
if(writeFile<0) {
printf("Failed to open output file(s)\n");
@@ -254,6 +260,7 @@
return -1;
}
packetNo=fileNo=writeName->FileNumber();
+ nextFile=false;
packetOffset=0;
fileOffset=sSize;
}
@@ -343,6 +350,8 @@
{
static struct option long_options[] = {
{ "rewrite", no_argument, NULL, 'r' },
+ { "startat", required_argument, NULL, 'a' },
+ { "firstnum", required_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
{ "dest", required_argument, NULL, 'd' },
{ "split", required_argument, NULL, 's' },
@@ -353,8 +362,14 @@
int s=0, str[MAX_STR];
int c;
- while((c=getopt_long(argc,argv,"rqd:s:i:",long_options,NULL))!=-1) {
+ while((c=getopt_long(argc,argv,"rqd:s:i:a:f:",long_options,NULL))!=-1) {
switch (c) {
+ case 'a':
+ startat=atoll(optarg);
+ break;
+ case 'f':
+ firstnum=atoi(optarg);
+ break;
case 'r':
rewrite=true;
break;
@@ -396,6 +411,8 @@
about();
printf("\nUsage: genindex [-r] [-d DIR] [-s SIZE]\n\n"
" -i FILE, --input FILE use a single input file\n"
+ " -a, --startat start reading input file at position\n"
+ " -f, --firstnum start numbering output file at num\n"
" -r, --rewrite rewrite video files\n"
" -d DIR, --dest=DIR set destination dir\n"
" -s SIZE, --split=SIZE split files at megabyte count\n"
@@ -421,6 +438,6 @@
}
if(!quiet) printf("\n\n");
}
- gi.Work();
+ gi.Work(startat);
return 0;
}
Only in genindex-0.1.3: genindex.o
diff -ur genindex-0.1.3.orig/pes.c genindex-0.1.3/pes.c
--- genindex-0.1.3.orig/pes.c 2003-07-26 23:55:21.000000000 +0200
+++ genindex-0.1.3/pes.c 2008-10-26 23:32:44.000000000 +0100
@@ -11,7 +11,7 @@
#include "pes.h"
#include "ringbuffer.h"
-#define DEBUG(x...) printf(x)
+#define DEBUG(x...) fprintf(stderr, x)
//#define DEBUG(x...)
//#define PD(x...) printf(x)
@@ -23,6 +23,7 @@
{
rb=new cRingBufferFrame(KILOBYTE(50));
defaultRule=ru;
+ nextFile=false;
Reset();
}
@@ -109,6 +110,7 @@
}
}
else if(skipped) {
+ nextFile=true;
totalSkipped+=skipped;
if(skipped==zeros) totalZeros+=zeros;
else DEBUG("PES: skipped %d bytes\n",skipped);
diff -ur genindex-0.1.3.orig/pes.h genindex-0.1.3/pes.h
--- genindex-0.1.3.orig/pes.h 2003-07-26 23:54:51.000000000 +0200
+++ genindex-0.1.3/pes.h 2008-10-26 18:59:26.000000000 +0100
@@ -25,6 +25,7 @@
class cPES : public cMutex {
protected:
enum eRule { prPass, prSkip, prAct1, prAct2, prAct3, prAct4, prAct5, prAct6, prAct7, prAct8 };
+ bool nextFile;
private:
eRule rules[NUM_RULESETS][NUM_RULES], *currRules, currRule, defaultRule;
int currNum;
Only in genindex-0.1.3: pes.o
Only in genindex-0.1.3: ringbuffer.o
Only in genindex-0.1.3: thread.o
Christian.
On 2023-07-03 14:34, Kartsa wrote:
Hi I’ve had VDR running for almost 20 years now. Not continuously of course and occasionally I have updated the system and added more disk and new MB and CPU and so. My problem is that I had an external disk for saving recordings which did not fit on the internal hard disk and now the external disk has failed. I had XFS on the disk and I have been able to create an image of the disk (probably with big chunks missing) but I have not been able to restore any of the recordings from the image. I have tried with foremost but the problem is the ts files. Foremost does not recognise them out of the box and I would need some header/footer information of the files. But to my understanding the ts files have no special footer which would indicate the ending of a file. Have tried to recognise from current recordings the header and tried with that. Foremost has been able to restore the info files but those are not a big help. Anyway I was wondering if there are any tools that I could try to restore the recordings. I have tried a lot of different tools (including testdisk and photorec) but have not had any real luck. So any instructions and/or pointers would be appreciated :) BR \\Kartsa _______________________________________________ vdr mailing list vdr@xxxxxxxxxxx https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
_______________________________________________ vdr mailing list vdr@xxxxxxxxxxx https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr