]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/faketape.c
ebl rename faketape to vtape
[bacula/bacula] / bacula / src / stored / faketape.c
index 62b9857c74f2a752302f0fea93fae70269f69b15..e2cef892e8380d7b379d8527af5d1fd1068fcb6d 100644 (file)
@@ -60,14 +60,13 @@ Device {
 #include "bacula.h"             /* define 64bit file usage */
 #include "stored.h"
 
-#ifdef USE_FAKETAPE
-#include "faketape.h"
+#include "vtape.h"
 
-static int dbglevel = 10;
+static int dbglevel = 100;
 #define FILE_OFFSET 30
-faketape *ftape_list[FTAPE_MAX_DRIVE];
+vtape *ftape_list[FTAPE_MAX_DRIVE];
 
-static faketape *get_tape(int fd)
+static vtape *get_tape(int fd)
 {
    ASSERT(fd >= 0);
 
@@ -79,7 +78,7 @@ static faketape *get_tape(int fd)
    return ftape_list[fd];
 }
 
-static bool put_tape(faketape *ftape)
+static bool put_tape(vtape *ftape)
 {
    ASSERT(ftape != NULL);
 
@@ -92,7 +91,7 @@ static bool put_tape(faketape *ftape)
    return true;
 }
 
-void faketape_debug(int level)
+void vtape_debug(int level)
 {
    dbglevel = level;
 }
@@ -101,12 +100,12 @@ void faketape_debug(int level)
 /* theses function will replace open/read/write/close/ioctl
  * in bacula core
  */
-int faketape_open(const char *pathname, int flags)
+int vtape_open(const char *pathname, int flags, ...)
 {
    ASSERT(pathname != NULL);
 
    int fd;
-   faketape *tape = new faketape();
+   vtape *tape = new vtape();
    fd = tape->open(pathname, flags);
    if (fd > 0) {
       put_tape(tape);
@@ -114,35 +113,35 @@ int faketape_open(const char *pathname, int flags)
    return fd;
 }
 
-int faketape_read(int fd, void *buffer, unsigned int count)
+int vtape_read(int fd, void *buffer, unsigned int count)
 {
-   faketape *tape = get_tape(fd);
+   vtape *tape = get_tape(fd);
    ASSERT(tape != NULL);
    return tape->read(buffer, count);
 }
 
-int faketape_write(int fd, const void *buffer, unsigned int count)
+int vtape_write(int fd, const void *buffer, unsigned int count)
 {
-   faketape *tape = get_tape(fd);
+   vtape *tape = get_tape(fd);
    ASSERT(tape != NULL);
    return tape->write(buffer, count);
 }
 
-int faketape_close(int fd)
+int vtape_close(int fd)
 {
-   faketape *tape = get_tape(fd);
+   vtape *tape = get_tape(fd);
    ASSERT(tape != NULL);
    tape->close();
    delete tape;
    return 0;
 }
 
-int faketape_ioctl(int fd, unsigned long int request, ...)
+int vtape_ioctl(int fd, unsigned long int request, ...)
 {
    va_list argp;
    int result=0;
 
-   faketape *t = get_tape(fd);
+   vtape *t = get_tape(fd);
    if (!t) {
       errno = EBADF;
       return -1;
@@ -167,9 +166,10 @@ int faketape_ioctl(int fd, unsigned long int request, ...)
 
 /****************************************************************/
 
-int faketape::tape_op(struct mtop *mt_com)
+int vtape::tape_op(struct mtop *mt_com)
 {
    int result=0;
+   int count = mt_com->mt_count;
 
    if (!online) {
       errno = ENOMEDIUM;
@@ -193,11 +193,15 @@ int faketape::tape_op(struct mtop *mt_com)
       break;
 
    case MTFSF:                  /* Forward space over mt_count filemarks. */
-      result = fsf(mt_com->mt_count);
+      do {
+        result = fsf();
+      } while (--count > 0 && result == 0);
       break;
 
    case MTBSF:                  /* Backward space over mt_count filemarks. */
-      result = bsf(mt_com->mt_count);
+      do {
+        result = bsf();
+      } while (--count > 0 && result == 0);
       break;
 
    case MTFSR:      /* Forward space over mt_count records (tape blocks). */
@@ -222,16 +226,20 @@ int faketape::tape_op(struct mtop *mt_com)
       break;
 
    case MTWEOF:                 /* Write mt_count filemarks. */
-      result = weof(mt_com->mt_count);
+      do {
+        result = weof();
+      } while (result == 0 && --count > 0);
       break;
 
    case MTREW:                  /* Rewind. */
-      Dmsg0(dbglevel, "rewind faketape\n");
+      Dmsg0(dbglevel, "rewind vtape\n");
+      check_eof();
       atEOF = atEOD = false;
       atBOT = true;
       current_file = 0;
       current_block = 0;
-      seek_file();
+      lseek(fd, 0, SEEK_SET);
+      result = !read_fm(VT_READ_EOF);
       break;
 
    case MTOFFL:                 /* put tape offline */
@@ -253,19 +261,30 @@ int faketape::tape_op(struct mtop *mt_com)
       break;
 
    case MTEOM:/* Go to the end of the recorded media (for appending files). */
+      while (next_FM) {
+        lseek(fd, next_FM, SEEK_SET);
+        if (read_fm(VT_READ_EOF)) {
+           current_file++;
+        }
+      }
+      off_t l;
+      while (::read(fd, &l, sizeof(l)) > 0) {
+        if (l) {
+           lseek(fd, l, SEEK_CUR);
+        } else {
+           ASSERT(0);
+        }
+        Dmsg0(dbglevel, "skip 1 block\n");
+      }
+      current_block = -1;
+      atEOF = false;
+      atEOD = true;
+
 /*
    file number = 3
    block number = -1
 */
       /* Can be at EOM */
-      atBOT = false;
-      atEOF = false;
-      atEOD = true;
-      atEOT = false;
-
-      current_file = last_file;
-      current_block = -1;
-      seek_file();
       break;
 
    case MTERASE:                /* not used by bacula */
@@ -275,7 +294,8 @@ int faketape::tape_op(struct mtop *mt_com)
 
       current_file = 0;
       current_block = -1;
-      seek_file();
+      lseek(fd, 0, SEEK_SET);
+      read_fm(VT_READ_EOF);
       truncate_file();
       break;
 
@@ -322,7 +342,7 @@ int faketape::tape_op(struct mtop *mt_com)
    return result == 0 ? 0 : -1;
 }
 
-int faketape::tape_get(struct mtget *mt_get)
+int vtape::tape_get(struct mtget *mt_get)
 {
    int density = 1;
    int block_size = 1024;
@@ -371,7 +391,7 @@ int faketape::tape_get(struct mtget *mt_get)
    return 0;
 }
 
-int faketape::tape_pos(struct mtpos *mt_pos)
+int vtape::tape_pos(struct mtpos *mt_pos)
 {
    if (current_block >= 0) {
       mt_pos->mt_blkno = current_block;
@@ -386,7 +406,7 @@ int faketape::tape_pos(struct mtpos *mt_pos)
  * of a tape. When you wrote something, data after the
  * current position are discarded.
  */
-int faketape::truncate_file()
+int vtape::truncate_file()
 {  
    Dmsg2(dbglevel, "truncate %i:%i\n", current_file, current_block);
    ftruncate(fd, lseek(fd, 0, SEEK_CUR));
@@ -396,7 +416,7 @@ int faketape::truncate_file()
    return 0;
 }
 
-faketape::faketape()
+vtape::vtape()
 {
    fd = -1;
 
@@ -405,7 +425,6 @@ faketape::faketape()
    atEOT = false;
    atEOD = false;
    online = false;
-   inplace = false;
    needEOF = false;
 
    file_block = 0;
@@ -413,14 +432,14 @@ faketape::faketape()
    current_file = 0;
    current_block = -1;
 
-   max_block = 2*1024*100;      /* 100MB */
+   max_block = 2*1024*2048;      /* 2GB */
 }
 
-faketape::~faketape()
+vtape::~vtape()
 {
 }
 
-int faketape::get_fd()
+int vtape::get_fd()
 {
    return this->fd;
 }
@@ -428,7 +447,7 @@ int faketape::get_fd()
 /*
  * TODO: check if after a write op, and other tape op put a EOF
  */
-int faketape::write(const void *buffer, unsigned int count)
+int vtape::write(const void *buffer, unsigned int count)
 {
    ASSERT(online);
    ASSERT(current_file >= 0);
@@ -436,7 +455,8 @@ int faketape::write(const void *buffer, unsigned int count)
    ASSERT(buffer);
 
    unsigned int nb;
-   Dmsg3(dbglevel, "write len=%i %i:%i\n", count, current_file,current_block);
+   Dmsg3(dbglevel*2, "write len=%i %i:%i\n", 
+        count, current_file,current_block);
 
    if (atEOT) {
       Dmsg0(dbglevel, "write nothing, EOT !\n");
@@ -444,10 +464,6 @@ int faketape::write(const void *buffer, unsigned int count)
       return -1;
    }
 
-   if (!inplace) {
-      seek_file();
-   }
-
    if (!atEOD) {                /* if not at the end of the data */
       truncate_file();
    }
@@ -462,14 +478,6 @@ int faketape::write(const void *buffer, unsigned int count)
 
    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;
-//   }
-
    uint32_t size = count;
    ::write(fd, &size, sizeof(uint32_t));
    nb = ::write(fd, buffer, count);
@@ -486,39 +494,66 @@ int faketape::write(const void *buffer, unsigned int count)
    return nb;
 }
 
-int faketape::weof(int count)
+/*
+ *  +---+---------+---+------------------+---+-------------------+
+ *  |00N|  DATA   |0LN|   DATA           |0LC|     DATA          |
+ *  +---+---------+---+------------------+---+-------------------+
+ *
+ *  0 : zero
+ *  L : Last FileMark offset
+ *  N : Next FileMark offset
+ *  C : Current FileMark Offset
+ */
+int vtape::weof()
 {
    ASSERT(online);
    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 */
 
-   /* TODO: check this */
-   current_file += count;
-   current_block = 0;
+   if (!atEOD) {
+      truncate_file();             /* nothing after this point */
+   }
+
+   last_FM = cur_FM;
+   cur_FM = lseek(fd, 0, SEEK_CUR); // current position
+   
+   /* update previous next_FM  */
+   lseek(fd, last_FM + sizeof(uint32_t)+sizeof(off_t), SEEK_SET);
+   ::write(fd, &cur_FM, sizeof(off_t));
+   lseek(fd, cur_FM, SEEK_SET);
+
+   next_FM = 0;
 
    uint32_t c=0;
-   seek_file();
-   ::write(fd, &c, sizeof(uint32_t));
-   seek_file();
+   ::write(fd, &c,       sizeof(uint32_t)); // EOF
+   ::write(fd, &last_FM, sizeof(last_FM));  // F-1
+   ::write(fd, &next_FM, sizeof(next_FM));  // F   (will be updated next time)
+
+   current_file++;
+   current_block = 0;
 
+   needEOF = false;
    atEOD = false;
    atBOT = false;
    atEOF = true;
 
-   update_pos();
+   last_file = MAX(current_file, last_file);
+
+   Dmsg4(dbglevel, "Writing EOF %i:%i last=%lli cur=%lli next=0\n", 
+         current_file, current_block, last_FM, cur_FM);
 
    return 0;
 }
 
-int faketape::fsf(int count)
+/*
+ * Go to next FM
+ */
+int vtape::fsf()
 {   
    ASSERT(online);
    ASSERT(current_file >= 0);
@@ -526,33 +561,78 @@ int faketape::fsf(int count)
 /*
  * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
  */
-   check_eof();
 
-   int ret;
-   if (atEOT) {
+   int ret=0;
+   if (atEOT || atEOD) {
+      errno = EIO;
       current_block = -1;
       return -1;
    }
 
-   atBOT = atEOF = false;
-   Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file);
+   atBOT = false;
+   Dmsg2(dbglevel+1, "fsf %i <= %i\n", current_file, last_file);
 
-   if ((current_file + count) <= last_file) {
-      current_file += count;
-      current_block = 0;
+   if (next_FM > cur_FM) {     /* not the last file */
+      lseek(fd, next_FM, SEEK_SET);
+      read_fm(VT_READ_EOF);
+      current_file++;
+      atEOF = true;
       ret = 0;
-   } else {
+
+   } else if (atEOF) {         /* last file mark */
+      current_block=-1;
+      errno = EIO;
+      atEOF = false;
+      atEOD = true;
+
+   } else {                    /* last file, but no at the end */
+      fsr(100000);
+
       Dmsg0(dbglevel, "Try to FSF after EOT\n");
+      errno = EIO;
       current_file = last_file ;
       current_block = -1;
       atEOD=true;
       ret = -1;
    }
-   seek_file();
    return ret;
 }
 
-int faketape::fsr(int count)
+/* /------------\ /---------------\
+ * +---+------+---+---------------+-+
+ * |OLN|      |0LN|               | |
+ * +---+------+---+---------------+-+
+ */
+
+bool vtape::read_fm(VT_READ_FM_MODE read_all)
+{
+   int ret;
+   uint32_t c;
+   if (read_all == VT_READ_EOF) {
+      ::read(fd, &c, sizeof(c));
+      if (c != 0) {
+        lseek(fd, cur_FM, SEEK_SET);
+        return false;
+      }
+   }
+
+   cur_FM = lseek(fd, 0, SEEK_CUR) - sizeof(c);
+
+   ::read(fd, &last_FM, sizeof(last_FM));
+   ret = ::read(fd, &next_FM, sizeof(next_FM));
+
+   current_block=0;
+   
+   Dmsg3(dbglevel, "Read FM cur=%lli last=%lli next=%lli\n", 
+        cur_FM, last_FM, next_FM);
+
+   return (ret == sizeof(next_FM));
+}
+
+/*
+ * TODO: Check fsr with EOF
+ */
+int vtape::fsr(int count)
 {
    ASSERT(online);
    ASSERT(current_file >= 0);
@@ -561,7 +641,8 @@ int faketape::fsr(int count)
    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);
+   Dmsg4(dbglevel, "fsr %i:%i EOF=%i c=%i\n", 
+        current_file,current_block,atEOF,count);
 
    check_eof();
 
@@ -589,25 +670,24 @@ int faketape::fsr(int count)
                current_file, current_block, nb,s);
          errno = EIO;
          ret = -1;
-         if (current_file < last_file) {
-            current_block = 0;
+        if (next_FM) {
             current_file++;
-            seek_file();
-         }
+           read_fm(VT_SKIP_EOF);
+        }
          atEOF = true;          /* stop the loop */
       }
    }
 
-   find_maxfile();              /* refresh stats */
-
    return ret;
 }
 
-int faketape::bsr(int count)
+/*
+ * BSR + EOF => begin of EOF + EIO
+ * BSR + BSR + EOF => last block
+ * current_block = -1
+ */
+int vtape::bsr(int count)
 {
-   Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", 
-         current_block, count);
-
    ASSERT(online);
    ASSERT(current_file >= 0);
    ASSERT(count == 1);
@@ -628,17 +708,47 @@ int faketape::bsr(int count)
    int orig_f = current_file;
    int orig_b = current_block;
 
-   current_block=0;
-   seek_file();
+   Dmsg4(dbglevel, "bsr(%i) cur_blk=%i orig=%lli cur_FM=%lli\n", 
+         count, current_block, orig, cur_FM);
+
+   /* begin of tape, do nothing */
+   if (atBOT) {
+      errno = EIO;
+      return -1;
+   }
+
+   /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error  */
+   if (atEOF) {
+      lseek(fd, cur_FM, SEEK_SET);
+      atEOF = false;
+      if (current_file > 0) {
+        current_file--;
+      }
+      current_block=-1;
+      errno = EIO;
+      return -1;
+   }
+
+   /*
+    * First, go to cur/last_FM and read all blocks to find the good one
+    */
+   if (cur_FM == orig) {       /* already just before  EOF */
+      lseek(fd, last_FM, SEEK_SET);
+
+   } else {
+      lseek(fd, cur_FM, SEEK_SET);
+   }
+
+   ret = read_fm(VT_READ_EOF);
 
    do {
       if (!atEOF) {
-         last2 = last;
+         last2 = last;         /* keep track of the 2 last blocs position */
          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);
+         Dmsg6(dbglevel, "EOF=%i last2=%lli last=%lli < orig=%lli %i:%i\n", 
+               atEOF, last2, last, orig, current_file, current_block);
       }
       ret = fsr(1);
    } while ((lseek(fd, 0, SEEK_CUR) < orig) && (ret == 0));
@@ -647,14 +757,14 @@ int faketape::bsr(int count)
       lseek(fd, last2, SEEK_SET);
       current_file = last_f;
       current_block = last_b - 1;
-      Dmsg3(dbglevel, "set offset2=%lli %i:%i\n", 
+      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", 
+      Dmsg3(dbglevel, "set offset=%lli %i:%i\n", 
             last, current_file, current_block);
    } else {
       lseek(fd, orig, SEEK_SET);
@@ -664,42 +774,53 @@ int faketape::bsr(int count)
    }
 
    Dmsg2(dbglevel, "bsr %i:%i\n", current_file, current_block);
+   errno=0;
    atEOT = atEOF = atEOD = false;
+   atBOT = (lseek(fd, 0, SEEK_CUR) - (sizeof(uint32_t)+2*sizeof(off_t))) == 0;
+
+   if (orig_b == -1) {
+      current_block = orig_b;
+   }
 
    return 0;
 }
 
-int faketape::bsf(int count)
+/* BSF => just before last EOF
+ * EOF + BSF => just before EOF
+ * file 0 + BSF => BOT + errno
+ */
+int vtape::bsf()
 {
    ASSERT(online);
    ASSERT(current_file >= 0);
-   Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count);
+   Dmsg2(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block);
    int ret = 0;
 
    check_eof();
+
    atBOT = atEOF = atEOT = atEOD = false;
 
-   if (current_file - count < 0) {
+   if (current_file == 0) {/* BOT + errno */      
+      lseek(fd, 0, SEEK_SET);
+      read_fm(VT_READ_EOF);
       current_file = 0;
       current_block = 0;
       atBOT = true;
       errno = EIO;
       ret = -1;
    } else {
-      current_file = current_file - count + 1;
-      current_block = -1;
-      seek_file();
+      Dmsg1(dbglevel, "bsf last=%lli\n", last_FM);
+      lseek(fd, cur_FM, SEEK_SET);
       current_file--;
-      /* go just before last EOF */
-      lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
+      current_block=-1;
    }
    return ret;
 }
 
 /* 
- * Put faketape in offline mode
+ * Put vtape in offline mode
  */
-int faketape::offline()
+int vtape::offline()
 {
    close();
    
@@ -716,83 +837,96 @@ int faketape::offline()
    return 0;
 }
 
-int faketape::close()
+/* A filemark is automatically written to tape if the last tape operation
+ * before close was a write.
+ */
+int vtape::close()
 {
    check_eof();
    ::close(fd);
    fd = -1;
    return 0;
 }
+
 /*
- **rb
- **status
- * EOF Bacula status: file=2 block=0
- * Device status: EOF ONLINE IM_REP_EN file=2 block=0
- **rb
- **status
- * EOD EOF Bacula status: file=2 block=0
- * Device status: EOD ONLINE IM_REP_EN file=2 block=-1
- *
+ * When a filemark is encountered while reading, the following happens.  If
+ * there are data remaining in the buffer when the filemark is found, the
+ * buffered data is returned.  The next read returns zero bytes.  The following
+ * read returns data from the next file.  The end of recorded data is sig‐
+ * naled by returning zero bytes for two consecutive read calls.  The third
+ * read returns an error.
  */
-
-int faketape::read(void *buffer, unsigned int count)
+int vtape::read(void *buffer, unsigned int count)
 {
    ASSERT(online);
    ASSERT(current_file >= 0);
    unsigned int nb;
    uint32_t s;
    
-   Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block);
+   Dmsg2(dbglevel*2, "read %i:%i\n", current_file, current_block);
 
    if (atEOT || atEOD) {
-      return 0;
+      errno = EIO;
+      return -1;
    }
 
    if (atEOF) {
-      current_file++;
-      current_block=0;
-      inplace = false;
-      atEOF = false;
+      if (!next_FM) {
+         atEOD = true;
+         atEOF = false;
+         current_block=-1;
+         return 0;
+      }
+      atEOF=false;
    }
 
-   if (!inplace) {
-      seek_file();
-   }
+   check_eof();
 
    atEOD = atBOT = false;
-   current_block++;
 
+   /* reading size of data */
    nb = ::read(fd, &s, sizeof(uint32_t));
    if (nb <= 0) {
-      atEOF = true;
+      atEOF = true;            /* TODO: check this */
       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;
    }
+
    if (!s) {                    /* EOF */
       atEOF = true;
-      lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
+      if (read_fm(VT_SKIP_EOF)) {
+        current_file++;
+      }
+
       return 0;
    }
+
+   /* reading data itself */
    nb = ::read(fd, buffer, s);
-   if (s != nb) {
-      atEOF = true;
-      if (current_file == last_file) {
-         atEOD = true;
-         current_block = -1;
-      }
-      Dmsg0(dbglevel, "EOF during reading\n");
+   if (s != nb) {              /* read error */
+      errno=EIO;
+      atEOT=true;
+      current_block = -1;
+      Dmsg0(dbglevel, "EOT during reading\n");
+      return -1;
+   }                   /* read ok */
+
+   if (current_block >= 0) {
+      current_block++;
    }
+
    return nb;
 }
 
-int faketape::open(const char *pathname, int uflags)
+int vtape::open(const char *pathname, int uflags)
 {
-   Dmsg2(dbglevel, "faketape::open(%s, %i)\n", pathname, uflags);
+   Dmsg2(dbglevel, "vtape::open(%s, %i)\n", pathname, uflags);
 
    online = true;               /* assume that drive contains a tape */
 
@@ -812,37 +946,25 @@ int faketape::open(const char *pathname, int uflags)
       return -1;
    }
 
-   /* open volume descriptor and get this->fd */
-   find_maxfile();
-
    file_block = 0;
    current_block = 0;
    current_file = 0;
+   cur_FM = next_FM = last_FM = 0;
    needEOF = false;
-   inplace = true;
    atBOT = true;
    atEOT = atEOD = false;
 
-   return fd;
-}
-
-/*
- * read volume to get the last file number
- */
-int faketape::find_maxfile()
-{
-   struct stat statp;
-   if (fstat(fd, &statp) != 0) {
-      return 0;
+   /* If the vtape is empty, start by writing a EOF */
+   if (online && !read_fm(VT_READ_EOF)) {
+      weof();
+      last_file = current_file=0;
    }
-   last_file = statp.st_size>>FILE_OFFSET;
-      
-   Dmsg1(dbglevel+1, "last_file=%i\n", last_file);
 
-   return last_file;
+   return fd;
 }
 
-void faketape::update_pos()
+/* use this to track file usage */
+void vtape::update_pos()
 {
    ASSERT(online);
    struct stat statp;
@@ -859,26 +981,7 @@ void faketape::update_pos()
    }
 }
 
-int faketape::seek_file()
-{
-   ASSERT(online);
-   ASSERT(current_file >= 0);
-   Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block);
-
-   off_t pos = ((off_t)current_file)<<FILE_OFFSET;
-   if(lseek(fd, pos, SEEK_SET) == -1) {
-      return -1;
-   }
-   last_file = MAX(last_file, current_file);
-   if (current_block > 0) {
-      fsr(current_block);
-   }
-   inplace = true;
-
-   return 0;
-}
-
-void faketape::dump()
+void vtape::dump()
 {
    Dmsg0(dbglevel+1, "===================\n");
    Dmsg2(dbglevel, "file:block = %i:%i\n", current_file, current_block);
@@ -888,4 +991,3 @@ void faketape::dump()
          atEOF, atEOT, atEOD, atBOT);  
 }
 
-#endif /* USE_FAKETAPE */