]> git.sur5r.net Git - bacula/bacula/commitdiff
ebl Start a new faketape driver.
authorEric Bollengier <eric@eb.homelinux.org>
Fri, 2 May 2008 21:03:42 +0000 (21:03 +0000)
committerEric Bollengier <eric@eb.homelinux.org>
Fri, 2 May 2008 21:03:42 +0000 (21:03 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6880 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/patches/testing/faketape.c [new file with mode: 0644]
bacula/patches/testing/faketape.h [new file with mode: 0644]

diff --git a/bacula/patches/testing/faketape.c b/bacula/patches/testing/faketape.c
new file mode 100644 (file)
index 0000000..c9196d9
--- /dev/null
@@ -0,0 +1,615 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation, which is 
+   listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+
+#include "faketape.h"
+#include <dirent.h>
+#include <sys/mtio.h>
+#include <ctype.h>
+
+static int tape_get(int fd, struct mtget *mt_get);
+static int tape_op(int fd, struct mtop *mt_com);
+static int tape_pos(int fd, struct mtpos *mt_pos);
+
+static int dbglevel = 0;
+
+
+faketape *ftape_list[FTAPE_MAX_DRIVE];
+
+static faketape *get_tape(int fd)
+{
+   ASSERT(fd >= 0);
+
+   if (fd >= FTAPE_MAX_DRIVE) {
+      /* error */
+      return NULL;
+   }
+
+   return ftape_list[fd];
+}
+
+static bool put_tape(faketape *ftape)
+{
+   ASSERT(ftape != NULL);
+
+   int fd = ftape->get_fd();
+   if (fd >= FTAPE_MAX_DRIVE) {
+      /* error */
+      return false;
+   }
+   ftape_list[fd] = ftape;
+   return true;
+}
+
+int faketape_open(const char *pathname, int flags, int mode)
+{
+   int fd;
+   faketape *tape = new faketape();
+   fd = tape->open(pathname, flags, mode);
+   if (fd > 0) {
+      put_tape(tape);
+   }
+   return fd;
+}
+
+int faketape_read(int fd, void *buffer, unsigned int count)
+{
+   faketape *tape = get_tape(fd);
+   ASSERT(tape != NULL);
+   return tape->read(buffer, count);
+}
+
+int faketape_write(int fd, const void *buffer, unsigned int count)
+{
+   faketape *tape = get_tape(fd);
+   ASSERT(tape != NULL);
+   return tape->write(buffer, count);
+}
+
+int faketape_close(int fd)
+{
+   faketape *tape = get_tape(fd);
+   ASSERT(tape != NULL);
+   tape->close();
+   delete tape;
+   return 0;
+}
+
+int faketape_ioctl(int fd, unsigned long int request, ...)
+{
+   va_list argp;
+   int result=0;
+
+   faketape *t = get_tape(fd);
+   if (!t) {
+      errno = EBADF;
+      return -1;
+   }
+
+   va_start(argp, request);
+
+//  switch (request) {
+//  case MTIOCTOP:
+        result = t->tape_op(va_arg(argp, mtop *));
+//      break;
+
+//   case MTIOCGET:
+//      result = tape_get(fd, va_arg(argp, mtget *));
+//      break;
+//
+//   case MTIOCPOS:
+//      result = tape_pos(fd, va_arg(argp, mtpos *));
+//      break;
+//
+//   default:
+//      errno = ENOTTY;
+//      result = -1;
+//      break;
+//   }
+
+   va_end(argp);
+
+   return result;
+}
+
+int faketape::tape_op(struct mtop *mt_com)
+{
+   int result=0;
+   struct stat statp;
+   
+   switch (mt_com->mt_op)
+   {
+   case MTRESET:
+   case MTNOP:
+   case MTSETDRVBUFFER:
+      break;
+
+   default:
+   case MTRAS1:
+   case MTRAS2:
+   case MTRAS3:
+   case MTSETDENSITY:
+      errno = ENOTTY;
+      result = -1;
+      break;
+
+   case MTFSF:                 /* Forward space over mt_count filemarks. */
+      /* we are already at EOT */
+      if (current_file > max_file) {
+        atEOF = true;
+        errno = EIO;
+        result = -1;
+      }
+
+      /* we are at the last file */
+      if (current_file == max_file) {
+        current_file++;
+        atEOF = true;
+      }
+
+      break;
+
+   case MTBSF:                 /* Backward space over mt_count filemarks. */
+      current_file = current_file - mt_op->mt_count;
+      if (current_file < 0) {
+        current_file = 0;
+        errno = EIO;
+        result = -1;
+      }
+      atEOD = false;
+      atEOF = false;
+      atEOM = false;
+      open_file();
+      break;
+
+   case MTFSR:     /* Forward space over mt_count records (tape blocks). */
+/*
+    file number = 1
+    block number = 0
+   
+    file number = 1
+    block number = 1
+   
+    mt: /dev/lto2: Erreur d'entrée/sortie
+   
+    file number = 2
+    block number = 0
+*/
+      /* tester si on se trouve a la fin du fichier */
+      fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count);
+      break;
+
+   case MTBSR:      /* Backward space over mt_count records (tape blocks). */
+
+/*
+   file number = 1
+   block number = -1
+
+   mt: /dev/lto2: Erreur d'entrée/sortie
+
+   file number = 0
+   block number = -1
+*/
+
+      fstat(cur_file, &statp);
+      off_t cur_pos = lseek(cur_fd, 0, SEEK_CUR);
+
+      fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count);
+      break;
+
+   case MTWEOF:                        /* Write mt_count filemarks. */
+      break;
+
+   case MTREW:                 /* Rewind. */
+      atEOF = atEOD = atEOM = false;
+      current_file = 0;
+      open_file();
+      break;
+
+   case MTOFFL:                        /* put tape offline */
+      // check if can_read/can_write
+      result = 0;
+      break;
+
+   case MTRETEN:               /* Re-tension tape. */
+      result = 0;
+      break;
+
+   case MTBSFM:                        /* not used by bacula */
+      errno = EIO;
+      result = -1;
+      break;
+
+   case MTFSFM:                        /* not used by bacula */
+      errno = EIO;
+      result = -1;
+      break;
+
+   case MTEOM:/* Go to the end of the recorded media (for appending files). */
+/*
+   file number = 3
+   block number = -1
+*/
+      /* Can be at EOM */
+      atEOF = true;
+      current_block = -1;
+      /* Ne pas creer le fichier si on est a la fin */
+
+      break;
+
+   case MTERASE:
+      atEOD = true;
+      atEOF = false;
+      atEOT = false;
+      current_file = 0;
+      current_block = -1;
+      delete_files(current_file);
+      break;
+
+   case MTSETBLK:
+      break;
+
+   case MTSEEK:
+      break;
+
+   case MTTELL:
+      break;
+
+   case MTFSS:
+      break;
+
+   case MTBSS:
+      break;
+
+   case MTWSM:
+      break;
+
+   case MTLOCK:
+      break;
+
+   case MTUNLOCK:
+      break;
+
+   case MTLOAD:
+      break;
+
+   case MTUNLOAD:
+      break;
+
+   case MTCOMPRESSION:
+      break;
+
+   case MTSETPART:
+      break;
+
+   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)
+{
+   return 0;
+}
+
+int faketape::tape_pos(struct mtpos *mt_pos)
+{
+   return 0;
+}
+
+int faketape::delete_files(int startfile)
+{  
+   int cur,max=0;
+   char *p;
+   POOL_MEM tmp;
+   DIR *fp_dir;
+   struct dirent *dir;
+   struct stat statp;
+
+   fp_dir = opendir(this->volume);
+   if (!fp_dir) {
+      this->max_file=0;
+      this->size = 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);
+      cur = 0;
+      /* check if d_name contains only digits */
+      for(p = dir->d_name; *p && isdigit(*p); p++)
+      {
+        cur *= 10;
+        cur += *p;
+      }
+      if (!*p && cur) {
+        if (cur >= startfile) { /* remove it */
+           unlink(tmp);
+        } else {
+           if (lstat(tmp.c_str(), &statp) == 0) {
+              this->size += statp.st_size;
+           }
+           max = (max > cur)?max:cur;
+        }
+      }
+   }
+
+   closedir(fp_dir);
+   this->max_file = max;
+   return max;
+}
+
+faketape::faketape()
+{
+   fd = 0;
+   atEOF = 0;
+   atEOM = 0;
+   current_file = 0;
+   current_block = 0;
+   max_file = 0;
+
+   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()
+{
+   return this->fd;
+}
+
+int faketape::write(const void *buffer, unsigned int count)
+{
+   ASSERT(cur_fd > 0);
+   if (current_block == -1) {
+      open_file();
+   }
+   /* remove all file > current_file */
+   return ::write(cur_fd, buffer, count);
+}
+
+int faketape::close()
+{
+   ASSERT(cur_fd > 0);
+   ::close(cur_fd);
+   ::close(fd);
+
+   return 0;
+}
+
+int faketape::read(void *buffer, unsigned int count)
+{
+   ASSERT(cur_fd > 0);
+   if (current_block == -1) {
+      open_file();
+   }
+   return ::read(cur_fd, buffer, count);
+}
+
+int faketape::read_volinfo()
+{
+   struct stat statp;
+   memset(&tape_info, 0, sizeof(FTAPE_FORMAT));
+
+   Dmsg2(0, "Info %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(cur_info, &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_file_mark = 2000;
+
+      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);
+
+   struct stat statp;   
+   if (lstat(volume, &statp) != 0) {
+      Dmsg1(dbglevel, "Can't stat on %s\n", volume);
+      return -1;
+   }
+
+   if (!S_ISDIR(statp.st_mode)) {
+      Dmsg1(dbglevel, "%s is not a directory\n", volume);
+      errno = EACCES;
+      return -1;
+   }
+
+   /* open volume descriptor and get this->fd */
+   if (read_volinfo() < 0) {
+      return -1;
+   }
+
+   current_block=-1;
+
+   return fd;
+}
+
+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) {
+      max_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;
+      }
+   }
+
+   closedir(fp_dir);
+   this->max_file = max;
+   return max;
+}
+
+int faketape::open_file() 
+{
+   if (cur_fd) {
+      ::close(cur_fd);
+   }
+
+   Mmsg(cur_file, "%s/%i", volume, current_file);
+   cur_fd = ::open(cur_file, O_CREAT | O_RDWR | O_BINARY, 0640);
+   if (cur_fd < 0) {
+      return -1;
+   }
+   current_block = 0;
+   max_file = (max_file > current_file)?max_file:current_file;
+
+   return cur_fd;
+
+}
+
+void faketape::dump()
+{
+   Dmsg1(dbglevel, "max_file=%i\n", max_file);
+   Dmsg1(dbglevel, "current_file=%i\n", current_file);
+   Dmsg1(dbglevel, "volume=%s\n", volume);
+   Dmsg1(dbglevel, "cur_info=%s\n", cur_info);
+   Dmsg1(dbglevel, "cur_file=%s\n", cur_file);  
+   Dmsg1(dbglevel, "size=%i\n", size);  
+}
+
+#ifdef TEST
+
+int main()
+{
+   int fd;
+   printf("Starting FakeTape\n");
+
+   mkdir("/tmp/fake", 0777);
+   fd = faketape_open("/tmp/fake", O_CREAT | O_RDWR | O_BINARY, 0666);
+   if (fd < 0) {
+      perror("open ERR");
+      return 1;
+   }
+
+   faketape *tape = get_tape(fd);
+   tape->dump();
+
+   faketape_close(fd);
+
+   return 0;
+}
+
+#endif
diff --git a/bacula/patches/testing/faketape.h b/bacula/patches/testing/faketape.h
new file mode 100644 (file)
index 0000000..47065e5
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation, which is
+   listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
+/*
+ * faketape.h - Emulate the Linux st (scsi tape) driver on file.
+ * for regression and bug hunting purpose
+ *
+ */
+
+#ifndef FAKETAPE_H
+#define FAKETAPE_H
+
+#include <stdarg.h>
+#include <stddef.h>
+#include "bacula.h"
+
+typedef struct
+{
+   /* format infos */
+   int16_t     version;
+   int16_t     max_file_mark;
+   int16_t     block_size;
+   int32_t     block_max;
+} FTAPE_FORMAT;
+
+#define FTAPE_MAX_DRIVE 20
+
+/* 
+ * Theses functions will replace open/read/write
+ */
+int faketape_open(const char *pathname, int flags, int mode);
+int faketape_read(int fd, void *buffer, unsigned int count);
+int faketape_write(int fd, const void *buffer, unsigned int count);
+int faketape_close(int fd);
+int faketape_ioctl(int fd, unsigned long int request, ...);
+
+class faketape {
+private:
+   int         fd;             /* Our file descriptor */
+
+   int         cur_fd;         /* OS file descriptor */
+   off_t       size;           /* size */
+
+   bool        atEOF;          /* End of file */
+   bool        atEOM;          /* End of media */
+   bool        atEOD;          /* End of data */
+
+   POOLMEM     *volume;                /* volume name */
+   POOLMEM     *cur_info;      /* volume info */
+   POOLMEM     *cur_file;      /* current file name */
+
+   int16_t     max_file;
+   int16_t     current_file;   /* max 65000 files */
+   int32_t     current_block;  /* max 4G blocks of 1KB */
+
+   FTAPE_FORMAT tape_info;
+
+   void destroy();
+   int read_volinfo();              /* read current volume format */
+   int find_maxfile();
+   int open_file();
+   int delete_files();
+
+public:
+   faketape();
+   ~faketape();
+
+   int get_fd();
+   void dump();
+   int open(const char *pathname, int flags, int mode);
+   int read(void *buffer, unsigned int count);
+   int write(const void *buffer, unsigned int count);
+   int close();
+
+   int tape_op(struct mtop *mt_com);
+   int tape_get(struct mtget *mt_com);
+   int tape_pos(struct mtpos *mt_com);
+};
+
+#endif /* !FAKETAPE_H */