]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/patches/testing/faketape.c
ebl add new hash lib test code
[bacula/bacula] / bacula / patches / testing / faketape.c
index 65792a985d0fedd1c448801cb90c2db087c5bb6d..9284680b6635f8e531595253ef423a4023fdba3d 100644 (file)
    Switzerland, email:ftf@fsfeurope.org.
 */
 
+/*
+
+Device {
+  Name = Drive-1                      #
+  Maximum File Size = 800M
+  Maximum Volume Size = 3G
+  Device Type = TAPE
+  Archive Device = /tmp/fake
+  Media Type = DLT-8000
+  AutomaticMount = yes;               # when device opened, read it
+  AlwaysOpen = yes;
+  RemovableMedia = yes;
+  RandomAccess = no;
+}
+
+  Block description :
+
+  block {
+    int32  size;
+    void   *data;
+  }
+
+  EOF description :
+
+  EOF {
+    int32  size=0;
+  }
+
+
+ */
+
+#include "bacula.h"            /* define 64bit file usage */
+#include "stored.h"
 #include "faketape.h"
-#include <dirent.h>
-#include <sys/mtio.h>
-#include <ctype.h>
 
 static int dbglevel = 10;
-
+#define FILE_OFFSET 30
 faketape *ftape_list[FTAPE_MAX_DRIVE];
 
 static faketape *get_tape(int fd)
@@ -60,17 +90,22 @@ static bool put_tape(faketape *ftape)
    return true;
 }
 
+void faketape_debug(int level)
+{
+   dbglevel = level;
+}
+
 /****************************************************************/
 /* theses function will replace open/read/write/close/ioctl
  * in bacula core
  */
-int faketape_open(const char *pathname, int flags, int mode)
+int faketape_open(const char *pathname, int flags)
 {
    ASSERT(pathname != NULL);
 
    int fd;
    faketape *tape = new faketape();
-   fd = tape->open(pathname, flags, mode);
+   fd = tape->open(pathname, flags);
    if (fd > 0) {
       put_tape(tape);
    }
@@ -117,13 +152,9 @@ int faketape_ioctl(int fd, unsigned long int request, ...)
       result = t->tape_op(va_arg(argp, mtop *));
    } else if (request == MTIOCGET) {
       result = t->tape_get(va_arg(argp, mtget *));
-   }
-//
-//   case MTIOCPOS:
-//      result = tape_pos(fd, va_arg(argp, mtpos *));
-//      break;
-//
-   else {
+   } else if (request == MTIOCPOS) {
+      result = t->tape_pos(va_arg(argp, mtpos *));
+   } else {
       errno = ENOTTY;
       result = -1;
    }
@@ -159,16 +190,7 @@ int faketape::tape_op(struct mtop *mt_com)
       break;
 
    case MTBSF:                 /* Backward space over mt_count filemarks. */
-      current_file = current_file - mt_com->mt_count;
-      if (current_file < 0) {
-        current_file = 0;
-        errno = EIO;
-        result = -1;
-      }
-      atEOD = false;
-      atEOF = false;
-      atBOT = false;
-      open_file();
+      result = bsf(mt_com->mt_count);
       break;
 
    case MTFSR:     /* Forward space over mt_count records (tape blocks). */
@@ -179,7 +201,7 @@ int faketape::tape_op(struct mtop *mt_com)
     file number = 1
     block number = 1
    
-    mt: /dev/lto2: Erreur d'entrée/sortie
+    mt: /dev/lto2: Erreur d'entree/sortie
    
     file number = 2
     block number = 0
@@ -189,19 +211,20 @@ int faketape::tape_op(struct mtop *mt_com)
       break;
 
    case MTBSR:      /* Backward space over mt_count records (tape blocks). */
-      result = -1;
+      result = bsr(mt_com->mt_count);
       break;
 
    case MTWEOF:                        /* Write mt_count filemarks. */
-      weof(mt_com->mt_count);
+      result = weof(mt_com->mt_count);
       break;
 
    case MTREW:                 /* Rewind. */
-      close_file();
+      Dmsg0(dbglevel, "rewind faketape\n");
       atEOF = atEOD = false;
       atBOT = true;
       current_file = 0;
       current_block = 0;
+      seek_file();
       break;
 
    case MTOFFL:                        /* put tape offline */
@@ -229,22 +252,24 @@ int faketape::tape_op(struct mtop *mt_com)
 */
       /* Can be at EOM */
       atBOT = false;
-      atEOF = true;
+      atEOF = false;
       atEOD = true;
-      close_file();
+      atEOT = false;
+
       current_file = last_file;
       current_block = -1;
-      /* Ne pas creer le fichier si on est a la fin */
-
+      seek_file();
       break;
 
    case MTERASE:               /* not used by bacula */
       atEOD = true;
       atEOF = false;
       atEOT = false;
+
       current_file = 0;
       current_block = -1;
-      delete_files(current_file);
+      seek_file();
+      truncate_file();
       break;
 
    case MTSETBLK:
@@ -286,42 +311,14 @@ int faketape::tape_op(struct mtop *mt_com)
    case MTMKPART:
       break;
    }
-//
-//   switch (result) {
-//   case NO_ERROR:
-//   case -1:   /* Error has already been translated into errno */
-//      break;
-//
-//   default:
-//   case ERROR_FILEMARK_DETECTED:
-//      errno = EIO;
-//      break;
-//
-//   case ERROR_END_OF_MEDIA:
-//      errno = EIO;
-//      break;
-//
-//   case ERROR_NO_DATA_DETECTED:
-//      errno = EIO;
-//      break;
-//
-//   case ERROR_NO_MEDIA_IN_DRIVE:
-//      errno = ENOMEDIUM;
-//      break;
-//
-//   case ERROR_INVALID_HANDLE:
-//   case ERROR_ACCESS_DENIED:
-//   case ERROR_LOCK_VIOLATION:
-//      errno = EBADF;
-//      break;
-//   }
-//
+
    return result == 0 ? 0 : -1;
 }
 
 int faketape::tape_get(struct mtget *mt_get)
 {
    int density = 1;
+   int block_size = 1024;
 
    mt_get->mt_type = MT_ISSCSI2;
    mt_get->mt_blkno = current_block;
@@ -333,7 +330,7 @@ int faketape::tape_get(struct mtget *mt_get)
    /* TODO */
    mt_get->mt_dsreg = 
       ((density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK) |
-      ((tape_info.block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK);
+      ((block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK);
 
 
    mt_get->mt_gstat = 0x00010000;  /* Immediate report mode.*/
@@ -369,7 +366,12 @@ int faketape::tape_get(struct mtget *mt_get)
 
 int faketape::tape_pos(struct mtpos *mt_pos)
 {
-   return 0;
+   if (current_block >= 0) {
+      mt_pos->mt_blkno = current_block;
+      return 0;
+   }
+
+   return -1;
 }
 
 /*
@@ -377,83 +379,39 @@ int faketape::tape_pos(struct mtpos *mt_pos)
  * of a tape. When you wrote something, data after the
  * current position are discarded.
  */
-int faketape::delete_files(int startfile)
+int faketape::truncate_file()
 {  
-   int cur,max=0;
-   char *p;
-   POOL_MEM tmp;
-   DIR *fp_dir;
-   struct dirent *dir;
-   struct stat statp;
-
-   Dmsg1(dbglevel, "delete_files %i\n", startfile);
-
-   fp_dir = opendir(this->volume);
-   if (!fp_dir) {
-      this->last_file=0;
-      this->size = 0;
-      return -1;
-   }
-
-   this->size = 0;
-
-   /* search for all digit files 
-    * and we remove all ones that are greater than
-    * startfile
-    */
-   while ((dir = readdir (fp_dir)) != NULL)
-   {
-      Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
-      cur = 0;
-      /* check if d_name contains only digits */
-      for(p = dir->d_name; *p && isdigit(*p); p++)
-      {
-        cur *= 10;
-        cur += *p - '0';
-      }
-      if (!*p && cur > 0) {
-        if (cur >= startfile) { /* remove it */
-           unlink(tmp.c_str());
-        } else {
-           if (lstat(tmp.c_str(), &statp) == 0) {
-              this->size += statp.st_size;
-           }
-           max = (max > cur)?max:cur;
-        }
-      }
-   }
-
-   closedir(fp_dir);
-   this->last_file = max;
-   return max;
+   Dmsg2(dbglevel, "truncate %i:%i\n", current_file, current_block);
+   ftruncate(fd, lseek(fd, 0, SEEK_CUR));
+   last_file = current_file;
+   atEOD=true;
+   return 0;
 }
 
 faketape::faketape()
 {
    fd = -1;
-   cur_fd = -1;
 
    atEOF = false;
    atBOT = false;
    atEOT = false;
    atEOD = false;
    online = false;
-   
-   size = 0;
+   inplace = false;
+   needEOF = false;
+
+   file_size = 0;
    last_file = 0;
    current_file = 0;
    current_block = -1;
+   current_pos = 0;
+
+   max_block = 1024*1024*1024*1024*8;
 
-   volume = get_pool_memory(PM_NAME);
-   cur_file = get_pool_memory(PM_NAME);
-   cur_info = get_pool_memory(PM_NAME);
 }
 
 faketape::~faketape()
 {
-   free_pool_memory(volume);
-   free_pool_memory(cur_file);
-   free_pool_memory(cur_info);
 }
 
 int faketape::get_fd()
@@ -461,38 +419,56 @@ int faketape::get_fd()
    return this->fd;
 }
 
+/*
+ * TODO: check if after a write op, and other tape op put a EOF
+ */
 int faketape::write(const void *buffer, unsigned int count)
 {
+   ASSERT(current_file >= 0);
+   ASSERT(count > 0);
+   ASSERT(buffer);
+
    unsigned int nb;
-   Dmsg2(dbglevel, "write len=%i blocks=%i\n", count, current_block);
-   check_file();
+   Dmsg3(dbglevel, "write len=%i %i:%i\n", count, current_file,current_block);
 
    if (atEOT) {
       Dmsg0(dbglevel, "write nothing, EOT !\n");
-      return 0;
+      errno = ENOSPC;
+      return -1;
    }
 
+   if (!inplace) {
+      seek_file();
+   }
+
+   if (!atEOD) {               /* if not at the end of the data */
+      truncate_file();
+   }
    if (current_block != -1) {
       current_block++;
    }
 
    atBOT = false;
-   atEOD = true;
+   atEOF = false;
+   atEOD = true;               /* End of data */
 
-   /* TODO: remove all files > current_file and 
-    * remove blocks > current_block 
-    */
-   if (count + size > tape_info.max_size) {
-      Dmsg2(dbglevel, 
-           "EOT writing only %i of %i requested\n", 
-           tape_info.max_size - size, count);
-      count = tape_info.max_size - size;
-      atEOT = true;
-   }
+   needEOF = true;             /* next operation need EOF mark */
+
+//   if ((count + file_size) > max_size) {
+//      Dmsg2(dbglevel, 
+//         "EOT writing only %i of %i requested\n", 
+//         max_size - file_size, count);
+//      count = max_size - file_size;
+//      atEOT = true;
+//   }
 
-   ::write(cur_fd, &count, sizeof(count));
-   nb = ::write(cur_fd, buffer, count);
+   uint32_t size = count;
+   ::write(fd, &size, sizeof(uint32_t));
+   nb = ::write(fd, buffer, count);
    
+   file_size += sizeof(uint32_t) + nb;
+
    if (nb != count) {
       atEOT = true;
       Dmsg2(dbglevel, 
@@ -505,114 +481,208 @@ int faketape::write(const void *buffer, unsigned int count)
 
 int faketape::weof(int count)
 {
-   Dmsg2(dbglevel, "Writing EOF %i:%i\n", current_file, current_block);
+   ASSERT(current_file >= 0);
+   Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n", 
+        current_file, current_block,last_file);
    if (atEOT) {
+      errno = ENOSPC;
       current_block = -1;
       return -1;
    }
+   needEOF = false;
+   truncate_file();            /* nothing after this point */
 
-   count--;                    /* end this file */
-   ftruncate(cur_fd, lseek(cur_fd, 0, SEEK_CUR));
-   current_file++;
-   open_file();
+   /* TODO: check this */
+   current_file += count;
+   current_block = 0;
 
-   /* we erase all previous information */
-   if (last_file > current_file) {
-      delete_files(current_file);
-   }
-   atEOF = true;
-   atEOD = false;
+   uint32_t c=0;
+   seek_file();
+   ::write(fd, &c, sizeof(uint32_t));
+   seek_file();
 
-   if (count > 0) {
-      current_block = -1;
-      return -1;
-   } else {
-      current_block = 0;
-   }
+   atEOD = false;
+   atBOT = false;
+   atEOF = true;
 
    return 0;
 }
 
 int faketape::fsf(int count)
-{
-
+{   
+   ASSERT(current_file >= 0);
+   ASSERT(fd >= 0);
 /*
  * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
  */
+   check_eof();
+
+   int ret;
    if (atEOT) {
       current_block = -1;
       return -1;
    }
 
-   close_file();
-
-   atEOF=1;
+   atBOT = atEOF = false;
    Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file);
 
    if ((current_file + count) <= last_file) {
       current_file += count;
       current_block = 0;
-      return 0;
+      ret = 0;
    } else {
       Dmsg0(dbglevel, "Try to FSF after EOT\n");
       current_file = last_file ;
       current_block = -1;
       atEOD=true;
-      return -1;
+      ret = -1;
    }
+   seek_file();
+   return ret;
 }
 
 int faketape::fsr(int count)
 {
-   int i,nb;
-   off_t where=0, size;
-   Dmsg2(dbglevel, "fsr current_block=%i count=%i\n", current_block, count);
+   ASSERT(current_file >= 0);
+   ASSERT(fd >= 0);
+   
+   int i,nb, ret=0;
+   off_t where=0;
+   uint32_t s;
+   Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count);
+
+   check_eof();
 
    if (atEOT) {
+      errno = EIO;
       current_block = -1;
       return -1;
    }
 
-   check_file();
+   if (atEOD) {
+      errno = EIO;
+      return -1;
+   }
 
-   for(i=0; (i < count) && (where != -1) ; i++) {
-      Dmsg3(dbglevel,"  fsr ok count=%i i=%i where=%i\n", count, i, where);
-      nb = ::read(cur_fd, &size, sizeof(size));
-      if (nb == sizeof(size)) {
-        where = lseek(cur_fd, size, SEEK_CUR);
-        if (where == -1) {
-           errno = EIO;
-           return -1;
-        }
+   atBOT = atEOF = false;   
+
+   /* check all block record */
+   for(i=0; (i < count) && !atEOF ; i++) {
+      nb = ::read(fd, &s, sizeof(uint32_t)); /* get size of next block */
+      if (nb == sizeof(uint32_t) && s) {
         current_block++;
+        where = lseek(fd, s, SEEK_CUR);     /* seek after this block */
       } else {
+        Dmsg4(dbglevel, "read EOF %i:%i nb=%i s=%i\n",
+              current_file, current_block, nb,s);
         errno = EIO;
-        return -1;
+        ret = -1;
+        if (current_file < last_file) {
+           current_block = 0;
+           current_file++;
+           seek_file();
+        }
+        atEOF = true;          /* stop the loop */
       }
    }
-   Dmsg2(dbglevel,"  fsr ok i=%i where=%i\n", i, where);
+
+   find_maxfile();             /* refresh stats */
+
+   if (where == file_size) {
+      atEOD = true;
+   }
+   return ret;
+}
+
+int faketape::bsr(int count)
+{
+   Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", 
+        current_block, count);
+
+   ASSERT(current_file >= 0);
+   ASSERT(count == 1);
+   ASSERT(fd >= 0);
+
+   check_eof();
+
+   if (!count) {
+      return 0;
+   }
+
+   int ret=0;
+   int last_f=0;
+   int last_b=0;
+
+   off_t last=-1, last2=-1;
+   off_t orig = lseek(fd, 0, SEEK_CUR);
+   int orig_f = current_file;
+   int orig_b = current_block;
+
+   current_block=0;
+   seek_file();
+
+   do {
+      if (!atEOF) {
+        last2 = last;
+        last = lseek(fd, 0, SEEK_CUR);
+        last_f = current_file;
+        last_b = current_block;
+        Dmsg5(dbglevel, "EOF=%i last=%lli orig=%lli %i:%i\n", 
+              atEOF, last, orig, current_file, current_block);
+      }
+      ret = fsr(1);
+   } while ((lseek(fd, 0, SEEK_CUR) < orig) && (ret == 0));
+
+   if (last2 > 0 && atEOF) {   /* we take the previous position */
+      lseek(fd, last2, SEEK_SET);
+      current_file = last_f;
+      current_block = last_b - 1;
+      Dmsg3(dbglevel, "set offset2=%lli %i:%i\n", 
+           last, current_file, current_block);
+
+   } else if (last > 0) {
+      lseek(fd, last, SEEK_SET);
+      current_file = last_f;
+      current_block = last_b;
+      Dmsg3(dbglevel, "set offset=%lli %i:%i\n", 
+           last, current_file, current_block);
+   } else {
+      lseek(fd, orig, SEEK_SET);
+      current_file = orig_f;
+      current_block = orig_b;
+      return -1;
+   }
+
+   Dmsg2(dbglevel, "bsr %i:%i\n", current_file, current_block);
+   atEOT = atEOF = atEOD = false;
+
    return 0;
 }
 
 int faketape::bsf(int count)
 {
-   close_file();
-   atEOT = atEOD = false;
+   ASSERT(current_file >= 0);
+   Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count);
+   int ret = 0;
+
+   check_eof();
+   atBOT = atEOF = atEOT = atEOD = false;
 
    if (current_file - count < 0) {
       current_file = 0;
       current_block = 0;
       atBOT = true;
-      return -1;
-   }
-
-   current_file = current_file - count;
-   current_block = 0;
-   if (!current_file) {
-      atBOT = true;
+      errno = EIO;
+      ret = -1;
+   } else {
+      current_file = current_file - count + 1;
+      current_block = -1;
+      seek_file();
+      current_file--;
+      /* go just before last EOF */
+      lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
    }
-
-   return 1;
+   return ret;
 }
 
 /* 
@@ -620,37 +690,24 @@ int faketape::bsf(int count)
  */
 int faketape::offline()
 {
-   ASSERT(cur_fd > 0);
-
-   close_file();
-
-   cur_fd = -1;
-   atEOF = false;
-   atEOT = false;
-   atEOD = false;
-   atBOT = false;
+   close();
+   
+   atEOF = false;              /* End of file */
+   atEOT = false;              /* End of tape */
+   atEOD = false;              /* End of data */
+   atBOT = false;              /* Begin of tape */
 
    current_file = -1;
    current_block = -1;
-   last_file = 0;
-   return 0;
-}
-
-int faketape::close_file()
-{
-   Dmsg0(dbglevel, "close_file\n");
-   if (cur_fd > 0) {
-      ::close(cur_fd);
-      cur_fd = -1;
-   }
+   last_file = -1;
    return 0;
 }
 
 int faketape::close()
 {
-   close_file();
+   check_eof();
    ::close(fd);
-
+   fd = -1;
    return 0;
 }
 /*
@@ -667,24 +724,48 @@ int faketape::close()
 
 int faketape::read(void *buffer, unsigned int count)
 {
-   unsigned int nb, size;
-   check_file();
+   ASSERT(current_file >= 0);
+   unsigned int nb;
+   uint32_t s;
+   
+   Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block);
 
    if (atEOT || atEOD) {
       return 0;
    }
 
-   atBOT = false;
+   if (atEOF) {
+      current_file++;
+      current_block=0;
+      inplace = false;
+      atEOF = false;
+   }
+
+   if (!inplace) {
+      seek_file();
+   }
+
+   atEOD = atBOT = false;
    current_block++;
 
-   nb = ::read(cur_fd, &size, sizeof(size));
-   if (size > count) {
-      lseek(cur_fd, size, SEEK_CUR);
+   nb = ::read(fd, &s, sizeof(uint32_t));
+   if (nb <= 0) {
+      atEOF = true;
+      return 0;
+   }
+   if (s > count) {            /* not enough buffer to read block */
+      Dmsg2(dbglevel, "Need more buffer to read next block %i > %i\n",s,count);
+      lseek(fd, s, SEEK_CUR);
       errno = ENOMEM;
       return -1;
    }
-   nb = ::read(cur_fd, buffer, size);
-   if (size != nb) {
+   if (!s) {                   /* EOF */
+      atEOF = true;
+      lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
+      return 0;
+   }
+   nb = ::read(fd, buffer, s);
+   if (s != nb) {
       atEOF = true;
       if (current_file == last_file) {
         atEOD = true;
@@ -695,135 +776,71 @@ int faketape::read(void *buffer, unsigned int count)
    return nb;
 }
 
-int faketape::read_volinfo()
+int faketape::open(const char *pathname, int uflags)
 {
-   struct stat statp;
-   memset(&tape_info, 0, sizeof(FTAPE_FORMAT));
-
-   Dmsg2(dbglevel, "read_volinfo %p %p\n", cur_info, volume);
-   Mmsg(cur_info, "%s/info", volume);
-   fd = ::open(cur_info, O_CREAT | O_RDWR | O_BINARY, 0640);
-   
-   if (fd < 0) {
-      return -1;
-   }
-   
-   fstat(fd, &statp);
-   
-   /* read volume info */
-   int nb = ::read(fd, &tape_info, sizeof(FTAPE_FORMAT));
-   if (nb != sizeof(FTAPE_FORMAT)) { /* new tape ? */
-      Dmsg1(dbglevel, "Initialize %s\n", volume);
-      tape_info.version = 1;
-      tape_info.block_max = 2000000;
-      tape_info.block_size = statp.st_blksize;
-      tape_info.max_size = 10000000;
-
-      lseek(fd, SEEK_SET, 0);
-      nb = ::write(fd, &tape_info, sizeof(FTAPE_FORMAT));
-
-      if (nb != sizeof(FTAPE_FORMAT)) {
-        ::close(fd);
-        return -1;
-      }
-   }
-
-   Dmsg0(dbglevel, "read_volinfo OK\n");
-   find_maxfile();
-
-   return fd;
-}
-
-int faketape::open(const char *pathname, int uflags, int umode)
-{
-   Dmsg3(dbglevel, "faketape::open(%s, %i, %i)\n", pathname, uflags, umode);
-   pm_strcpy(volume, pathname);
+   Dmsg2(dbglevel, "faketape::open(%s, %i)\n", pathname, uflags);
 
    struct stat statp;   
-   if (stat(volume, &statp) != 0) {
-      Dmsg1(dbglevel, "Can't stat on %s\n", volume);
+   if (stat(pathname, &statp) != 0) {
+      Dmsg1(dbglevel, "Can't stat on %s\n", pathname);
       return -1;
    }
 
-   if (!S_ISDIR(statp.st_mode)) {
-      Dmsg1(dbglevel, "%s is not a directory\n", volume);
-      errno = EACCES;
+   fd = ::open(pathname, O_CREAT | O_RDWR | O_LARGEFILE, 0700);
+   if (fd < 0) {
       return -1;
    }
 
    /* open volume descriptor and get this->fd */
-   if (read_volinfo() < 0) {
+   if (find_maxfile() < 0) {
       return -1;
    }
 
-   current_block=-1;
+   current_block = 0;
+   current_file = 0;
+   needEOF = false;
+   online = inplace = true;
+   atBOT = true;
+   atEOT = atEOD = false;
 
    return fd;
 }
 
 /*
- * read volume directory to get the last file number
+ * read volume to get the last file number
  */
 int faketape::find_maxfile()
 {
-   int max=0;
-   int cur;
-   char *p;
-   POOL_MEM tmp;
-   DIR *fp_dir;
-   struct dirent *dir;
    struct stat statp;
-
-   fp_dir = opendir(this->volume);
-   if (!fp_dir) {
-      last_file=0;
-      return -1;
-   }
-
-   this->size = 0;
-
-   /* search for all digit file */
-   while ((dir = readdir (fp_dir)) != NULL)
-   {
-      Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
-      if (lstat(tmp.c_str(), &statp) == 0) {
-        this->size += statp.st_size;
-      } else {
-        Dmsg1(dbglevel, "Can't stat %s\n", tmp.c_str());
-      }
-      cur = 0;
-      /* TODO: compute size */
-      for(p = dir->d_name; *p && isdigit(*p); p++)
-      {
-        cur *= 10;
-        cur += *p;
-      }
-      if (!*p && cur) {
-        max = (max > cur)?max:cur;
-      }
+   if (fstat(fd, &statp) != 0) {
+      return 0;
    }
+   last_file = statp.st_size>>FILE_OFFSET;
+   file_size = statp.st_size;
+      
+   current_pos = lseek(fd, 0, SEEK_CUR); /* get current position */
+   Dmsg3(dbglevel+1, "last_file=%i file_size=%u current_pos=%i\n", 
+        last_file, file_size, current_pos);
 
-   closedir(fp_dir);
-   this->last_file = max;
-   return max;
+   return last_file;
 }
 
-int faketape::open_file() 
+int faketape::seek_file()
 {
    ASSERT(current_file >= 0);
-   close_file();
+   Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block);
 
-   Mmsg(cur_file, "%s/%i", volume, current_file);
-   cur_fd = ::open(cur_file, O_CREAT | O_RDWR | O_BINARY, 0640);
-   if (cur_fd < 0) {
+   off_t pos = ((off_t)current_file)<<FILE_OFFSET;
+   if(lseek(fd, pos, SEEK_SET) == -1) {
       return -1;
    }
-   current_block = 0;
    last_file = (last_file > current_file)?last_file:current_file;
+   if (current_block > 0) {
+      fsr(current_block);
+   }
+   inplace = true;
 
-   Dmsg1(dbglevel, "open_file %s\n", cur_file);
-
-   return cur_fd;
+   return 0;
 }
 
 void faketape::dump()
@@ -831,116 +848,7 @@ void faketape::dump()
    Dmsg0(dbglevel+1, "===================\n");
    Dmsg2(dbglevel, "file:block = %i:%i\n", current_file, current_block);
    Dmsg1(dbglevel+1, "last_file=%i\n", last_file);
-   Dmsg1(dbglevel+1, "volume=%s\n", volume);
-   Dmsg1(dbglevel+1, "cur_file=%s\n", cur_file);  
-   Dmsg1(dbglevel+1, "size=%i\n", size);  
-   Dmsg1(dbglevel+1, "EOF=%i\n", atEOF);  
-   Dmsg1(dbglevel+1, "EOT=%i\n", atEOT);  
-   Dmsg1(dbglevel+1, "EOD=%i\n", atEOD);  
+   Dmsg1(dbglevel+1, "file_size=%i\n", file_size);  
+   Dmsg4(dbglevel+1, "EOF=%i EOT=%i EOD=%i BOT=%i\n", 
+        atEOF, atEOT, atEOD, atBOT);  
 }
-
-/****************************************************************
-
-#define GMT_EOF(x)              ((x) & 0x80000000)
-#define GMT_BOT(x)              ((x) & 0x40000000)
-#define GMT_EOT(x)              ((x) & 0x20000000)
-#define GMT_SM(x)               ((x) & 0x10000000)
-#define GMT_EOD(x)              ((x) & 0x08000000)
-
-
- GMT_EOF(x) : La bande est positionnée juste après une filemark (toujours faux
-     après une opération MTSEEK).
-
- GMT_BOT(x) : La bande est positionnée juste au début du premier fichier
-     (toujours faux après une opération MTSEEK).
- GMT_EOT(x) : Une opération a atteint la fin physique de la bande (End Of
- Tape).
-
- GMT_SM(x) : La bande est positionnée sur une setmark (toujours faux après une
- opération MTSEEK).
-
- GMT_EOD(x) : La bande est positionnée à la fin des données enregistrées.
-
-
-blkno = -1 (after MTBSF MTBSS or MTSEEK)
-fileno = -1 (after MTBSS or MTSEEK)
-
-*** mtx load
-drive type = Generic SCSI-2 tape
-drive status = 0
-sense key error = 0
-residue count = 0
-file number = 0
-block number = 0
-Tape block size 0 bytes. Density code 0x0 (default).
-Soft error count since last status=0
-General status bits on (41010000):
- BOT ONLINE IM_REP_EN
-
-*** read empty block
-dd if=/dev/lto2 of=/tmp/toto count=1
-dd: lecture de `/dev/lto2': Ne peut allouer de la mémoire
-0+0 enregistrements lus
-0+0 enregistrements écrits
-1 octet (1B) copié, 4,82219 seconde, 0,0 kB/s
-
-file number = 0
-block number = 1
-
-*** read file mark
-dd if=/dev/lto2 of=/tmp/toto count=1
-0+0 enregistrements lus
-0+0 enregistrements écrits
-1 octet (1B) copié, 0,167274 seconde, 0,0 kB/s
-
-file number = 1
-block number = 0
-
- *** write 2 blocks after rewind
-dd if=/dev/zero of=/dev/lto2 count=2
-2+0 enregistrements lus
-2+0 enregistrements écrits
-1024 octets (1,0 kB) copiés, 6,57402 seconde, 0,2 kB/s
-
-file number = 1
-block number = 0
-
-*** write 2 blocks
-file number = 2
-block number = 0
-
-*** rewind and fsr
-file number = 0
-block number = 1
-
-*** rewind and 2x fsr (we have just 2 blocks)
-file number = 0
-block number = 2
-
-*** fsr
-mt: /dev/lto2: Erreur
-file number = 1
-block number = 0
-
-
- ****************************************************************/
-
-
-#ifdef TEST
-
-int main()
-{
-   int fd;
-   char buf[500];
-   printf("Starting FakeTape\n");
-
-   mkdir("/tmp/fake", 0700);
-
-
-
-
-   return 0;
-}
-
-#endif