]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/dev.c
kes Fix mtx-changer to detect both versions of Ubuntu (Debian)
[bacula/bacula] / bacula / src / stored / dev.c
index 558fd729843497ab579324159c2a4ff5663658bd..0e72db6a84530de7182b80d605238ad46ff934b3 100644 (file)
@@ -127,6 +127,13 @@ init_dev(JCR *jcr, DEVRES *device)
          device->dev_type = B_TAPE_DEV;
       } else if (S_ISFIFO(statp.st_mode)) {
          device->dev_type = B_FIFO_DEV;
+#ifdef USE_VTAPE
+      /* must set DeviceType = Vtape 
+       * in normal mode, autodetection is disabled
+       */
+      } else if (S_ISREG(statp.st_mode)) { 
+         device->dev_type = B_VTAPE_DEV;
+#endif
       } else if (!(device->cap_bits & CAP_REQMOUNT)) {
          Jmsg2(jcr, M_ERROR, 0, _("%s is an unknown device type. Must be tape or directory\n"
                " or have RequiresMount=yes for DVD. st_mode=%x\n"),
@@ -139,7 +146,7 @@ init_dev(JCR *jcr, DEVRES *device)
 
    dev = (DEVICE *)malloc(sizeof(DEVICE));
    memset(dev, 0, sizeof(DEVICE));
-   dev->Slot = -1;       /* unknown */
+   dev->clear_slot();         /* unknown */
 
    /* Copy user supplied device parameters from Resource */
    dev->dev_name = get_memory(strlen(device->device_name)+1);
@@ -162,6 +169,7 @@ init_dev(JCR *jcr, DEVRES *device)
    dev->drive_index = device->drive_index;
    dev->autoselect = device->autoselect;
    dev->dev_type = device->dev_type;
+   dev->init_backend();
    if (dev->is_tape()) { /* No parts on tapes */
       dev->max_part_size = 0;
    } else {
@@ -264,6 +272,44 @@ init_dev(JCR *jcr, DEVRES *device)
    return dev;
 }
 
+/* Choose the right backend */
+void DEVICE::init_backend()
+{
+
+#ifdef HAVE_WIN32
+   if (is_tape()) {
+      d_open  = win32_tape_open;
+      d_write = win32_tape_write;
+      d_close = win32_tape_close;
+      d_ioctl = win32_tape_ioctl;
+      d_read  = win32_tape_read;
+
+   } else {
+      d_open  = ::open;
+      d_close = ::close;
+      d_ioctl = win32_ioctl;    /* dummy function */
+      d_write = win32_write;    /* win32 read/write are not POSIX */
+      d_read  = win32_read;
+   }
+
+#else  /* POSIX / UNIX Interface */
+   if (is_vtape()) {            /* test backend */
+      d_open  = vtape_open;     /* vtape isn't available for WIN32 or FreeBSD */
+      d_write = vtape_write;
+      d_close = vtape_close;
+      d_ioctl = vtape_ioctl;
+      d_read  = vtape_read;
+
+   } else {                     /* tape and file are using normal io */
+      d_open  = ::open;
+      d_write = ::write;
+      d_close = ::close;
+      d_ioctl = ::ioctl;
+      d_read  = ::read;
+   }
+#endif
+}
+
 /*
  * Open the device with the operating system and
  * initialize buffer pointers.
@@ -285,11 +331,7 @@ DEVICE::open(DCR *dcr, int omode)
       if (openmode == omode) {
          return m_fd;
       } else {
-         if (is_tape()) {
-            tape_close(m_fd);
-         } else {
-            ::close(m_fd);
-         }
+         d_close(m_fd);
          clear_opened();
          Dmsg0(100, "Close fd for mode change.\n");
          preserve = state & (ST_LABEL|ST_APPEND|ST_READ);
@@ -302,7 +344,6 @@ DEVICE::open(DCR *dcr, int omode)
    Dmsg4(100, "open dev: type=%d dev_name=%s vol=%s mode=%s\n", dev_type,
          print_name(), VolCatInfo.VolCatName, mode_to_str(omode));
    state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
-   Slot = -1;          /* unknown slot */
    label_type = B_BACULA_LABEL;
    if (is_tape() || is_fifo()) {
       open_tape_device(dcr, omode);
@@ -369,7 +410,7 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
 #if defined(HAVE_WIN32)
 
    /*   Windows Code */
-   if ((m_fd = tape_open(dev_name, mode)) < 0) {
+   if ((m_fd = d_open(dev_name, mode)) < 0) {
       dev_errno = errno;
    }
 
@@ -379,7 +420,7 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
    /* If busy retry each second for max_open_wait seconds */
    for ( ;; ) {
       /* Try non-blocking open */
-      m_fd = tape_open(dev_name, mode+O_NONBLOCK);
+      m_fd = d_open(dev_name, mode+O_NONBLOCK);
       if (m_fd < 0) {
          berrno be;
          dev_errno = errno;
@@ -391,10 +432,10 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
          mt_com.mt_op = MTREW;
          mt_com.mt_count = 1;
          /* rewind only if dev is a tape */
-         if (is_tape() && (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0)) {
+         if (is_tape() && (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0)) {
             berrno be;
             dev_errno = errno;           /* set error status from rewind */
-            tape_close(m_fd);
+            d_close(m_fd);
             clear_opened();
             Dmsg2(100, "Rewind error on %s close: ERR=%s\n", print_name(),
                   be.bstrerror(dev_errno));
@@ -404,8 +445,8 @@ void DEVICE::open_tape_device(DCR *dcr, int omode)
             }
          } else {
             /* Got fd and rewind worked, so we must have medium in drive */
-            tape_close(m_fd);
-            m_fd = tape_open(dev_name, mode);  /* open normally */
+            d_close(m_fd);
+            m_fd = d_open(dev_name, mode);  /* open normally */
             if (m_fd < 0) {
                berrno be;
                dev_errno = errno;
@@ -689,7 +730,7 @@ void DEVICE::open_dvd_device(DCR *dcr, int omode)
                be.bstrerror());
          Dmsg1(100, "open failed: %s", errmsg);
          /* Use system close() */
-         ::close(m_fd);
+         d_close(m_fd);
          clear_opened();
       } else {
          part_size = filestat.st_size;
@@ -733,7 +774,7 @@ bool DEVICE::rewind(DCR *dcr)
        * retrying every 5 seconds.
        */
       for (i=max_rewind_wait; ; i -= 5) {
-         if (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
+         if (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
             berrno be;
             clrerror(MTREW);
             if (i == max_rewind_wait) {
@@ -747,7 +788,7 @@ bool DEVICE::rewind(DCR *dcr)
              */
             if (first && dcr) {
                int open_mode = openmode;
-               tape_close(m_fd);
+               d_close(m_fd);
                clear_opened();
                open(dcr, open_mode);
                if (m_fd < 0) {
@@ -887,7 +928,7 @@ bool DEVICE::eod(DCR *dcr)
          mt_com.mt_count = 1;
       }
 
-      if (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
+      if (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
          berrno be;
          clrerror(mt_com.mt_op);
          Dmsg1(50, "ioctl error: %s\n", be.bstrerror());
@@ -1031,7 +1072,7 @@ uint32_t status_dev(DEVICE *dev)
       stat |= BMT_TAPE;
       Pmsg0(-20,_(" Bacula status:"));
       Pmsg2(-20,_(" file=%d block=%d\n"), dev->file, dev->block_num);
-      if (tape_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCGET, (char *)&mt_stat) < 0) {
          berrno be;
          dev->dev_errno = errno;
          Mmsg2(dev->errmsg, _("ioctl MTIOCGET error on %s. ERR=%s.\n"),
@@ -1158,7 +1199,7 @@ bool load_dev(DEVICE *dev)
    dev->file_addr = 0;
    mt_com.mt_op = MTLOAD;
    mt_com.mt_count = 1;
-   if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+   if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
       berrno be;
       dev->dev_errno = errno;
       Mmsg2(dev->errmsg, _("ioctl MTLOAD error on %s. ERR=%s.\n"),
@@ -1189,7 +1230,7 @@ bool DEVICE::offline()
    unlock_door();
    mt_com.mt_op = MTOFFL;
    mt_com.mt_count = 1;
-   if (tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
+   if (d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com) < 0) {
       berrno be;
       dev_errno = errno;
       Mmsg2(errmsg, _("ioctl MTOFFL error on %s. ERR=%s.\n"),
@@ -1264,7 +1305,7 @@ bool DEVICE::fsf(int num)
       int my_errno = 0;
       mt_com.mt_op = MTFSF;
       mt_com.mt_count = num;
-      stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+      stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
       if (stat < 0) {
          my_errno = errno;            /* save errno */
       } else if ((os_file=get_os_tape_file()) < 0) {
@@ -1345,7 +1386,7 @@ bool DEVICE::fsf(int num)
          }
 
          Dmsg0(100, "Doing MTFSF\n");
-         stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+         stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
          if (stat < 0) {                 /* error => EOT */
             berrno be;
             set_eot();
@@ -1419,7 +1460,7 @@ bool DEVICE::bsf(int num)
    file_size = 0;
    mt_com.mt_op = MTBSF;
    mt_com.mt_count = num;
-   stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
    if (stat < 0) {
       berrno be;
       clrerror(MTBSF);
@@ -1459,7 +1500,7 @@ bool DEVICE::fsr(int num)
    Dmsg1(100, "fsr %d\n", num);
    mt_com.mt_op = MTFSR;
    mt_com.mt_count = num;
-   stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
    if (stat == 0) {
       clear_eof();
       block_num += num;
@@ -1518,7 +1559,7 @@ bool DEVICE::bsr(int num)
    clear_eot();
    mt_com.mt_op = MTBSR;
    mt_com.mt_count = num;
-   stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
    if (stat < 0) {
       berrno be;
       clrerror(MTBSR);
@@ -1534,7 +1575,7 @@ void DEVICE::lock_door()
    struct mtop mt_com;
    mt_com.mt_op = MTLOCK;
    mt_com.mt_count = 1;
-   tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
 #endif
 }
 
@@ -1544,9 +1585,22 @@ void DEVICE::unlock_door()
    struct mtop mt_com;
    mt_com.mt_op = MTUNLOCK;
    mt_com.mt_count = 1;
-   tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
 #endif
 }
+
+void DEVICE::set_slot(int32_t slot)
+{ 
+   m_slot = slot; 
+   if (vol) vol->clear_slot();
+}
+
+void DEVICE::clear_slot()
+{ 
+   m_slot = -1; 
+   if (vol) vol->set_slot(-1);
+}
+
  
 
 /*
@@ -1633,7 +1687,7 @@ bool DEVICE::weof(int num)
 {
    struct mtop mt_com;
    int stat;
-   Dmsg0(129, "weof_dev\n");
+   Dmsg1(129, "=== weof_dev=%s\n", print_name());
    
    if (!is_open()) {
       dev_errno = EBADF;
@@ -1656,7 +1710,7 @@ bool DEVICE::weof(int num)
    clear_eot();
    mt_com.mt_op = MTWEOF;
    mt_com.mt_count = num;
-   stat = tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   stat = d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
    if (stat == 0) {
       block_num = 0;
       file += num;
@@ -1787,7 +1841,7 @@ void DEVICE::clrerror(int func)
 /* Found on Solaris */
 #ifdef MTIOCLRERR
 {
-   tape_ioctl(m_fd, MTIOCLRERR);
+   d_ioctl(m_fd, MTIOCLRERR);
    Dmsg0(200, "Did MTIOCLRERR\n");
 }
 #endif
@@ -1800,7 +1854,7 @@ void DEVICE::clrerror(int func)
    union mterrstat mt_errstat;
    Dmsg2(200, "Doing MTIOCERRSTAT errno=%d ERR=%s\n", dev_errno,
       be.bstrerror(dev_errno));
-   tape_ioctl(m_fd, MTIOCERRSTAT, (char *)&mt_errstat);
+   d_ioctl(m_fd, MTIOCERRSTAT, (char *)&mt_errstat);
 }
 #endif
 
@@ -1811,13 +1865,25 @@ void DEVICE::clrerror(int func)
    mt_com.mt_op = MTCSE;
    mt_com.mt_count = 1;
    /* Clear any error condition on the tape */
-   tape_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
+   d_ioctl(m_fd, MTIOCTOP, (char *)&mt_com);
    Dmsg0(200, "Did MTCSE\n");
 }
 #endif
 }
 
 
+/*
+ * Set to unload the current volume in the drive
+ */
+void DEVICE::set_unload()
+{
+   if (!m_unload && VolHdr.VolumeName[0] != 0) {
+       m_unload = true;
+       memcpy(UnloadVolName, VolHdr.VolumeName, sizeof(UnloadVolName));
+   }
+}
+
+
 /*
  * Clear volume header
  */
@@ -1846,12 +1912,11 @@ void DEVICE::close()
 
    switch (dev_type) {
    case B_VTL_DEV:
+   case B_VTAPE_DEV:
    case B_TAPE_DEV:
       unlock_door(); 
-      tape_close(m_fd);
-      break;
    default:
-      ::close(m_fd);
+      d_close(m_fd);
    }
 
    /* Clean up device packet so it can be reused */
@@ -1868,7 +1933,6 @@ void DEVICE::close()
    file_addr = 0;
    EndFile = EndBlock = 0;
    openmode = 0;
-   Slot = -1;             /* unknown slot */
    clear_volhdr();
    memset(&VolCatInfo, 0, sizeof(VolCatInfo));
    if (tid) {
@@ -1922,6 +1986,7 @@ bool DEVICE::truncate(DCR *dcr) /* We need the DCR for DVD-writing */
    Dmsg1(100, "truncate %s\n", print_name());
    switch (dev_type) {
    case B_VTL_DEV:
+   case B_VTAPE_DEV:
    case B_TAPE_DEV:
       /* maybe we should rewind and write and eof ???? */
       return true;                    /* we don't really truncate tapes */
@@ -2251,11 +2316,7 @@ ssize_t DEVICE::read(void *buf, size_t len)
 
    get_timer_count();
 
-   if (this->is_tape()) {
-      read_len = tape_read(m_fd, buf, len);
-   } else {
-      read_len = ::read(m_fd, buf, len);
-   }
+   read_len = d_read(m_fd, buf, len);
 
    last_tick = get_timer_count();
 
@@ -2276,11 +2337,7 @@ ssize_t DEVICE::write(const void *buf, size_t len)
 
    get_timer_count();
 
-   if (this->is_tape()) {
-      write_len = tape_write(m_fd, buf, len);
-   } else {
-      write_len = ::write(m_fd, buf, len);
-   }
+   write_len = d_write(m_fd, buf, len);
 
    last_tick = get_timer_count();
 
@@ -2306,7 +2363,7 @@ int32_t DEVICE::get_os_tape_file()
    struct mtget mt_stat;
 
    if (has_cap(CAP_MTIOCGET) &&
-       tape_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) {
+       d_ioctl(m_fd, MTIOCGET, (char *)&mt_stat) == 0) {
       return mt_stat.mt_fileno;
    }
    return -1;
@@ -2369,7 +2426,6 @@ void init_device_wait_timers(DCR *dcr)
    dev->rem_wait_sec = dev->wait_sec;
    dev->num_wait = 0;
    dev->poll = false;
-   dev->BadVolName[0] = 0;
 
    jcr->min_wait = 60 * 60;
    jcr->max_wait = 24 * 60 * 60;
@@ -2431,7 +2487,7 @@ void set_os_device_parameters(DCR *dcr)
       mt_com.mt_op = MTSETBLK;
       mt_com.mt_count = 0;
       Dmsg0(100, "Set block size to zero\n");
-      if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
          dev->clrerror(MTSETBLK);
       }
    }
@@ -2447,7 +2503,7 @@ void set_os_device_parameters(DCR *dcr)
          mt_com.mt_count |= MT_ST_FAST_MTEOM;
       }
       Dmsg0(100, "MTSETDRVBUFFER\n");
-      if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
          dev->clrerror(MTSETDRVBUFFER);
       }
    }
@@ -2461,13 +2517,13 @@ void set_os_device_parameters(DCR *dcr)
        dev->min_block_size == 0) {    /* variable block mode */
       mt_com.mt_op = MTSETBSIZ;
       mt_com.mt_count = 0;
-      if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
          dev->clrerror(MTSETBSIZ);
       }
       /* Get notified at logical end of tape */
       mt_com.mt_op = MTEWARN;
       mt_com.mt_count = 1;
-      if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
          dev->clrerror(MTEWARN);
       }
    }
@@ -2480,7 +2536,7 @@ void set_os_device_parameters(DCR *dcr)
        dev->min_block_size == 0) {    /* variable block mode */
       mt_com.mt_op = MTSETBSIZ;
       mt_com.mt_count = 0;
-      if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
          dev->clrerror(MTSETBSIZ);
       }
    }
@@ -2491,7 +2547,7 @@ void set_os_device_parameters(DCR *dcr)
    } else {
       neof = 1;
    }
-   if (tape_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) {
+   if (dev->d_ioctl(dev->fd(), MTIOCSETEOTMODEL, (caddr_t)&neof) < 0) {
       berrno be;
       dev->dev_errno = errno;         /* save errno */
       Mmsg2(dev->errmsg, _("Unable to set eotmodel on device %s: ERR=%s\n"),
@@ -2508,7 +2564,7 @@ void set_os_device_parameters(DCR *dcr)
        dev->min_block_size == 0) {    /* variable block mode */
       mt_com.mt_op = MTSRSZ;
       mt_com.mt_count = 0;
-      if (tape_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
+      if (dev->d_ioctl(dev->fd(), MTIOCTOP, (char *)&mt_com) < 0) {
          dev->clrerror(MTSRSZ);
       }
    }
@@ -2520,7 +2576,7 @@ static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat)
 {
    Dmsg0(100, "dev_get_os_pos\n");
    return dev->has_cap(CAP_MTIOCGET) && 
-          tape_ioctl(dev->fd(), MTIOCGET, (char *)mt_stat) == 0 &&
+          dev->d_ioctl(dev->fd(), MTIOCGET, (char *)mt_stat) == 0 &&
           mt_stat->mt_fileno >= 0;
 }