Hi,
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@linuxtv.org
https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
_______________________________________________
vdr mailing list
vdr@linuxtv.org
https://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

Reply via email to