+ return true;
+}
+
+/*
+ * Read and return the Volume label
+ */
+static bool readlabel_cmd(JCR *jcr)
+{
+ POOL_MEM devname;
+ BSOCK *dir = jcr->dir_bsock;
+ DEVICE *dev;
+ DCR *dcr;
+ int Slot;
+ int drive;
+
+ if (sscanf(dir->msg, "readlabel %127s Slot=%d drive=%d", devname.c_str(),
+ &Slot, &drive) == 3) {
+ dcr = find_device(jcr, devname, drive);
+ if (dcr) {
+ dev = dcr->dev;
+ P(dev->mutex); /* Use P to avoid indefinite block */
+ if (!dev->is_open()) {
+ read_volume_label(jcr, dev, Slot);
+ dev->close();
+ /* Under certain "safe" conditions, we can steal the lock */
+ } else if (dev->can_steal_lock()) {
+ read_volume_label(jcr, dev, Slot);
+ } else if (dev->is_busy() || dev->is_blocked()) {
+ send_dir_busy_message(dir, dev);
+ } else { /* device not being used */
+ read_volume_label(jcr, dev, Slot);
+ }
+ V(dev->mutex);
+ free_dcr(dcr);
+ jcr->dcr = NULL;
+ } else {
+ bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
+ }
+ } else {
+ pm_strcpy(jcr->errmsg, dir->msg);
+ bnet_fsend(dir, _("3909 Error scanning readlabel command: %s\n"), jcr->errmsg);
+ }
+ bnet_sig(dir, BNET_EOD);
+ return true;
+}
+
+
+/*
+ * Read the tape label
+ *
+ * Enter with the mutex set
+ */
+static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot)
+{
+ BSOCK *dir = jcr->dir_bsock;
+ bsteal_lock_t hold;
+ DCR *dcr = jcr->dcr;
+
+ dcr->dev = dev;
+ steal_device_lock(dev, &hold, BST_WRITING_LABEL);
+
+ if (!try_autoload_device(jcr, Slot, "")) {
+ goto bail_out; /* error */
+ }
+
+ dev->clear_labeled(); /* force read of label */
+ switch (read_dev_volume_label(dcr)) {
+ case VOL_OK:
+ /* DO NOT add quotes around the Volume name. It is scanned in the DIR */
+ bnet_fsend(dir, _("3001 Volume=%s Slot=%d\n"), dev->VolHdr.VolumeName, Slot);
+ Dmsg1(100, "Volume: %s\n", dev->VolHdr.VolumeName);
+ break;
+ default:
+ bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device %s because:\n%s"),
+ dev->print_name(), jcr->errmsg);
+ break;
+ }
+
+bail_out:
+ give_back_device_lock(dev, &hold);
+ return;
+}
+
+static bool try_autoload_device(JCR *jcr, int slot, const char *VolName)
+{
+ DCR *dcr = jcr->dcr;
+ BSOCK *dir = jcr->dir_bsock;
+
+ bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
+ dcr->VolCatInfo.Slot = slot;
+ dcr->VolCatInfo.InChanger = slot > 0;
+ if (autoload_device(dcr, 0, dir) < 0) { /* autoload if possible */
+ return false;
+ }
+ return true;
+}
+
+static void send_dir_busy_message(BSOCK *dir, DEVICE *dev)
+{
+ if (dev->is_blocked()) {
+ switch (dev->dev_blocked) {
+ case BST_UNMOUNTED:
+ bnet_fsend(dir, _("3931 Device %s is BLOCKED. user unmounted.\n"),
+ dev->print_name());
+ break;
+ case BST_UNMOUNTED_WAITING_FOR_SYSOP:
+ bnet_fsend(dir, _("3932 Device %s is BLOCKED. user unmounted during wait for media/mount.\n"),
+ dev->print_name());
+ break;
+ case BST_WAITING_FOR_SYSOP:
+ bnet_fsend(dir, _("3933 Device %s is BLOCKED waiting for media.\n"),
+ dev->print_name());
+ break;
+ case BST_DOING_ACQUIRE:
+ bnet_fsend(dir, _("3934 Device %s is being initialized.\n"),
+ dev->print_name());
+ break;
+ case BST_WRITING_LABEL:
+ bnet_fsend(dir, _("3935 Device %s is blocked labeling a Volume.\n"),
+ dev->print_name());
+ break;
+ default:
+ bnet_fsend(dir, _("3935 Device %s is blocked for unknown reason.\n"),
+ dev->print_name());
+ break;
+ }
+ } else if (dev->can_read()) {
+ bnet_fsend(dir, _("3936 Device %s is busy reading.\n"),
+ dev->print_name());;
+ } else {
+ bnet_fsend(dir, _("3937 Device %s is busy with %d writer(s).\n"),
+ dev->print_name(), dev->num_writers);
+ }