Exemple #1
0
void dvd_remove_empty_part(DCR *dcr) 
{
   DEVICE *dev = dcr->dev;

   /* Remove the last part file if it is empty */
   if (dev->is_dvd() && dev->num_dvd_parts > 0) {
      struct stat statp;
      uint32_t part_save = dev->part;
      POOL_MEM archive_name(PM_FNAME);
      int status;

      dev->part = dev->num_dvd_parts;
      make_spooled_dvd_filename(dev, archive_name);
      /* Check that the part file is empty */
      status = stat(archive_name.c_str(), &statp);
      if (status == 0 && statp.st_size == 0) {
         Dmsg3(100, "Unlink empty part in close call make_dvd_filename. part=%d num=%d vol=%s\n", 
                part_save, dev->num_dvd_parts, dev->getVolCatName());
         Dmsg1(100, "unlink(%s)\n", archive_name.c_str());
         unlink(archive_name.c_str());
         if (part_save == dev->part) {
            dev->set_part_spooled(false);  /* no spooled part left */
         }
      } else if (status < 0) {                         
         if (part_save == dev->part) {
            dev->set_part_spooled(false);  /* spool doesn't exit */
         }
      }       
      dev->part = part_save;               /* restore part number */
   }
}
Exemple #2
0
bool dvd_close_job(DCR *dcr)
{
   DEVICE *dev = dcr->dev;
   JCR *jcr = dcr->jcr;
   bool ok = true;

   /*
    * If the device is a dvd and WritePartAfterJob
    * is set to yes, open the next part, so, in case of a device
    * that requires mount, it will be written to the device.
    */
   if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
      Dmsg1(400, "Writing last part=%d write_partafter_job is set.\n",
         dev->part);
      if (dev->part < dev->num_dvd_parts+1) {
         Jmsg3(jcr, M_FATAL, 0, _("Error writing. Current part less than total number of parts (%d/%d, device=%s)\n"),
               dev->part, dev->num_dvd_parts, dev->print_name());
         dev->dev_errno = EIO;
         ok = false;
      }
      
      if (ok && !dvd_write_part(dcr)) {
         Jmsg2(jcr, M_FATAL, 0, _("Unable to write last on %s: ERR=%s\n"),
               dev->print_name(), dev->bstrerror());
         dev->dev_errno = EIO;
         ok = false;
      }
   }
   return ok;
}
Exemple #3
0
/* 
 * Mount a DVD device, then scan to find out how many parts
 *  there are.
 */
int find_num_dvd_parts(DCR *dcr)
{
   DEVICE *dev = dcr->dev;
   int num_parts = 0;

   if (!dev->is_dvd()) {
      return 0;
   }
   
   if (dev->mount(1)) {
      DIR* dp;
      struct dirent *entry, *result;
      int name_max;
      int len = strlen(dcr->getVolCatName());

      /* Now count the number of parts */
      name_max = pathconf(".", _PC_NAME_MAX);
      if (name_max < 1024) {
         name_max = 1024;
      }
         
      if (!(dp = opendir(dev->device->mount_point))) {
         berrno be;
         dev->dev_errno = errno;
         Dmsg3(29, "find_num_dvd_parts: failed to open dir %s (dev=%s), ERR=%s\n", 
               dev->device->mount_point, dev->print_name(), be.bstrerror());
         goto get_out;
      }
      
      entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);

      Dmsg1(100, "Looking for Vol=%s\n", dcr->getVolCatName());
      for ( ;; ) {
         int flen;
         bool ignore;
         if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
            dev->dev_errno = EIO;
            Dmsg2(129, "find_num_dvd_parts: failed to find suitable file in dir %s (dev=%s)\n", 
                  dev->device->mount_point, dev->print_name());
            break;
         }
         flen = strlen(result->d_name);
         ignore = true;
         if (flen >= len) {
            result->d_name[len] = 0;
            if (strcmp(dcr->getVolCatName(), result->d_name) == 0) {
               num_parts++;
               Dmsg1(100, "find_num_dvd_parts: found part: %s\n", result->d_name);
               ignore = false;
            }
         }
         if (ignore) {
            Dmsg2(129, "find_num_dvd_parts: ignoring %s in %s\n", 
                  result->d_name, dev->device->mount_point);
         }
      }
      free(entry);
      closedir(dp);
      Dmsg1(29, "find_num_dvd_parts = %d\n", num_parts);
   }
   
get_out:
   dev->set_freespace_ok();
   if (dev->is_mounted()) {
      dev->unmount(0);
   }
   return num_parts;
}
Exemple #4
0
/*
 * Open the next part file.
 *  - Close the fd
 *  - Increment part number 
 *  - Reopen the device
 */
int dvd_open_next_part(DCR *dcr)
{
   DEVICE *dev = dcr->dev;

   Dmsg6(29, "Enter: == open_next_part part=%d npart=%d dev=%s vol=%s mode=%d file_addr=%d\n", 
      dev->part, dev->num_dvd_parts, dev->print_name(),
         dev->getVolCatName(), dev->openmode, dev->file_addr);
   if (!dev->is_dvd()) {
      Dmsg1(100, "Device %s is not dvd!!!!\n", dev->print_name()); 
      return -1;
   }
   
   /* When appending, do not open a new part if the current is empty */
   if (dev->can_append() && (dev->part > dev->num_dvd_parts) && 
       (dev->part_size == 0)) {
      Dmsg0(29, "open_next_part exited immediately (dev->part_size == 0).\n");
      return dev->fd();
   }

   dev->close_part(dcr);               /* close current part */
   
   /*
    * If we have a spooled part open, write it to the
    *  DVD before opening the next part.
    */
   if (dev->is_part_spooled()) {
      Dmsg2(100, "Before open next write previous. part=%d num_parts=%d\n",
         dev->part, dev->num_dvd_parts);
      if (!dvd_write_part(dcr)) {
         Dmsg0(29, "Error in dvd_write part.\n");
         return -1;
      }
   }
     
   dev->part_start += dev->part_size;
   dev->part++;
   Dmsg2(29, "Inc part=%d num_dvd_parts=%d\n", dev->part, dev->num_dvd_parts);

   /* Are we working on a part past what is written in the DVD? */
   if (dev->num_dvd_parts < dev->part) {
      POOL_MEM archive_name(PM_FNAME);
      struct stat buf;
      /* 
       * First check what is on DVD.  If our part is there, we
       *   are in trouble, so bail out.
       * NB: This is however not a problem if we are writing the first part.
       * It simply means that we are over writing an existing volume...
       */
      if (dev->num_dvd_parts > 0) {
         make_mounted_dvd_filename(dev, archive_name);   /* makes dvd name */
         Dmsg1(100, "Check if part on DVD: %s\n", archive_name.c_str());
         if (stat(archive_name.c_str(), &buf) == 0) {
            /* bad news bail out */
            dev->set_part_spooled(false);
            Mmsg1(&dev->errmsg, _("Next Volume part already exists on DVD. Cannot continue: %s\n"),
               archive_name.c_str());
            return -1;
         }
      }

#ifdef neeeded
      Dmsg2(400, "num_dvd_parts=%d part=%d\n", dev->num_dvd_parts, dev->part);
      make_spooled_dvd_filename(dev, archive_name);   /* makes spool name */
      
      /* Check if the next part exists in spool directory . */
      Dmsg1(100, "Check if part on spool: %s\n", archive_name.c_str());
      if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
         Dmsg1(29, "======= Part %s is in the way, deleting it...\n", archive_name.c_str());
         /* Then try to unlink it */
         if (unlink(archive_name.c_str()) < 0) {
            berrno be;
            dev->set_part_spooled(false);
            dev->dev_errno = errno;
            Mmsg2(dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), 
                   archive_name.c_str(), be.bstrerror());
            return -1;
         }
      }
#endif
   }

   Dmsg2(400, "Call dev->open(vol=%s, mode=%d)\n", dcr->getVolCatName(), 
         dev->openmode);

   /* Open next part.  Note, this sets part_size for part opened. */
   if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
      return -1;
   } 
   dev->set_labeled();                   /* all next parts are "labeled" */
   
   return dev->fd();
}
Exemple #5
0
/*
 * Acquire device for writing. We permit multiple writers.
 *  If this is the first one, we read the label.
 *
 *  Returns: NULL if failed for any reason
 *           dcr if successful.
 *   Note, normally reserve_device_for_append() is called
 *   before this routine.
 */
DCR *acquire_device_for_append(DCR *dcr)
{
   DEVICE *dev = dcr->dev;
   JCR *jcr = dcr->jcr;
   bool ok = false;
   bool have_vol = false;

   Enter(200);
   init_device_wait_timers(dcr);

   dev->Lock_acquire();             /* only one job at a time */
   dev->Lock();
   Dmsg1(100, "acquire_append device is %s\n", dev->is_tape()?"tape":
        (dev->is_dvd()?"DVD":"disk"));
   /*
    * With the reservation system, this should not happen
    */
   if (dev->can_read()) {
      Mmsg2(jcr->errmsg, "Want to append but %s device %s is busy reading.\n",
         dev->print_type(), dev->print_name());
      Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
      Dmsg0(50, jcr->errmsg);
      goto get_out;
   }

   dev->clear_unload();

   /*
    * have_vol defines whether or not mount_next_write_volume should
    *   ask the Director again about what Volume to use.
    */
   if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
       strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
      Dmsg0(190, "device already in append.\n");
      /*
       * At this point, the correct tape is already mounted, so
       *   we do not need to do mount_next_write_volume(), unless
       *   we need to recycle the tape.
       */
       if (dev->num_writers == 0) {
          dev->VolCatInfo = dcr->VolCatInfo;   /* structure assignment */
       }
       have_vol = dcr->is_tape_position_ok();
   }

   if (!have_vol) {
      dev->rLock(true);
      block_device(dev, BST_DOING_ACQUIRE);
      dev->Unlock();
      Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
      if (!dcr->mount_next_write_volume()) {
         if (!job_canceled(jcr)) {
            /* Reduce "noise" -- don't print if job canceled */
            Mmsg2(jcr->errmsg, _("Could not ready %s device %s for append.\n"),
               dev->print_type(), dev->print_name());
            Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
            Dmsg0(50, jcr->errmsg);
         }
         dev->Lock();
         unblock_device(dev);
         goto get_out;
      }
      Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
      dev->Lock();
      unblock_device(dev);
   }

   if (generate_plugin_event(jcr, bsdEventDeviceOpen, dcr) != bRC_OK) {
      Mmsg0(jcr->errmsg,  _("generate_plugin_event(bsdEventDeviceOpen) Failed\n"));
      Jmsg(jcr, M_FATAL, 0, jcr->errmsg);
      Dmsg0(50, jcr->errmsg);
      goto get_out;
   }

   dev->num_writers++;                /* we are now a writer */
   if (jcr->NumWriteVolumes == 0) {
      jcr->NumWriteVolumes = 1;
   }
   dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs on vol */
   Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n",
      dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs,
      dev->print_name());
   ok = dir_update_volume_info(dcr, false, false); /* send Volume info to Director */

get_out:
   /* Don't plugin close here, we might have multiple writers */
   dcr->clear_reserved();
   dev->Unlock();
   dev->Unlock_acquire();
   Leave(200);
   return ok ? dcr : NULL;
}