+
+static BSOCK *open_sd_bsock(UAContext *ua)
+{
+ STORE *store = ua->jcr->wstore;
+
+ if (!ua->jcr->store_bsock) {
+ bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
+ store->name(), store->address, store->SDport);
+ if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
+ bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
+ return NULL;
+ }
+ }
+ return ua->jcr->store_bsock;
+}
+
+static void close_sd_bsock(UAContext *ua)
+{
+ if (ua->jcr->store_bsock) {
+ bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
+ bnet_close(ua->jcr->store_bsock);
+ ua->jcr->store_bsock = NULL;
+ }
+}
+
+static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive)
+{
+ STORE *store = ua->jcr->wstore;
+ BSOCK *sd;
+ char dev_name[MAX_NAME_LENGTH];
+ char *VolName = NULL;
+ int rtn_slot;
+
+ if (!(sd=open_sd_bsock(ua))) {
+ bsendmsg(ua, _("Could not open SD socket.\n"));
+ return NULL;
+ }
+ bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+ bash_spaces(dev_name);
+ /* Ask for autochanger list of volumes */
+ bnet_fsend(sd, NT_("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive);
+ Dmsg1(100, "Sent: %s", sd->msg);
+
+ /* Get Volume name in this Slot */
+ while (bnet_recv(sd) >= 0) {
+ bsendmsg(ua, "%s", sd->msg);
+ Dmsg1(100, "Got: %s", sd->msg);
+ if (strncmp(sd->msg, NT_("3001 Volume="), 12) == 0) {
+ VolName = (char *)malloc(sd->msglen);
+ if (sscanf(sd->msg, NT_("3001 Volume=%s Slot=%d"), VolName, &rtn_slot) == 2) {
+ break;
+ }
+ free(VolName);
+ VolName = NULL;
+ }
+ }
+ close_sd_bsock(ua);
+ Dmsg1(100, "get_vol_name=%s\n", NPRT(VolName));
+ return VolName;
+}
+
+/*
+ * We get the slot list from the Storage daemon.
+ * If scan is set, we return all slots found,
+ * otherwise, we return only slots with valid barcodes (Volume names)
+ */
+static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
+{
+ STORE *store = ua->jcr->wstore;
+ char dev_name[MAX_NAME_LENGTH];
+ BSOCK *sd;
+ vol_list_t *vl;
+ vol_list_t *vol_list = NULL;
+
+
+ if (!(sd=open_sd_bsock(ua))) {
+ return NULL;
+ }
+
+ bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+ bash_spaces(dev_name);
+ /* Ask for autochanger list of volumes */
+ bnet_fsend(sd, NT_("autochanger list %s \n"), dev_name);
+
+ /* Read and organize list of Volumes */
+ while (bnet_recv(sd) >= 0) {
+ char *p;
+ int Slot;
+ strip_trailing_junk(sd->msg);
+
+ /* Check for returned SD messages */
+ if (sd->msg[0] == '3' && B_ISDIGIT(sd->msg[1]) &&
+ B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
+ sd->msg[4] == ' ') {
+ bsendmsg(ua, "%s\n", sd->msg); /* pass them on to user */
+ continue;
+ }
+
+ /* Validate Slot: if scanning, otherwise Slot:Barcode */
+ p = strchr(sd->msg, ':');
+ if (scan && p) {
+ /* Scanning -- require only valid slot */
+ Slot = atoi(sd->msg);
+ if (Slot <= 0) {
+ p--;
+ *p = ':';
+ bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
+ continue;
+ }
+ } else {
+ /* Not scanning */
+ if (p && strlen(p) > 1) {
+ *p++ = 0;
+ if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
+ p--;
+ *p = ':';
+ bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
+ continue;
+ }
+ } else {
+ continue;
+ }
+ if (!is_volume_name_legal(ua, p)) {
+ p--;
+ *p = ':';
+ bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
+ continue;
+ }
+ }
+
+ /* Add Slot and VolumeName to list */
+ vl = (vol_list_t *)malloc(sizeof(vol_list_t));
+ vl->Slot = Slot;
+ if (p) {
+ if (*p == ':') {
+ p++; /* skip separator */
+ }
+ vl->VolName = bstrdup(p);
+ } else {
+ vl->VolName = NULL;
+ }
+ Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
+ if (!vol_list) {
+ vl->next = vol_list;
+ vol_list = vl;
+ } else {
+ /* Add new entry to end of list */
+ for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
+ if (!tvl->next) {
+ tvl->next = vl;
+ vl->next = NULL;
+ break;
+ }
+ }
+ }
+ }
+ close_sd_bsock(ua);
+ return vol_list;
+}
+
+static void free_vol_list(vol_list_t *vol_list)
+{
+ vol_list_t *vl;
+
+ /* Free list */
+ for (vl=vol_list; vl; ) {
+ vol_list_t *ovl;
+ if (vl->VolName) {
+ free(vl->VolName);
+ }
+ ovl = vl;
+ vl = vl->next;
+ free(ovl);
+ }
+}
+
+/*
+ * We get the number of slots in the changer from the SD
+ */
+static int get_num_slots_from_SD(UAContext *ua)
+{
+ STORE *store = ua->jcr->wstore;
+ char dev_name[MAX_NAME_LENGTH];
+ BSOCK *sd;
+ int slots = 0;
+
+
+ if (!(sd=open_sd_bsock(ua))) {
+ return 0;
+ }
+
+ bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+ bash_spaces(dev_name);
+ /* Ask for autochanger number of slots */
+ bnet_fsend(sd, NT_("autochanger slots %s\n"), dev_name);
+
+ while (bnet_recv(sd) >= 0) {
+ if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
+ break;
+ } else {
+ bsendmsg(ua, "%s", sd->msg);
+ }
+ }
+ close_sd_bsock(ua);
+ bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
+ return slots;
+}
+
+/*
+ * We get the number of drives in the changer from the SD
+ */
+int get_num_drives_from_SD(UAContext *ua)
+{
+ STORE *store = ua->jcr->wstore;
+ char dev_name[MAX_NAME_LENGTH];
+ BSOCK *sd;
+ int drives = 0;
+
+
+ if (!(sd=open_sd_bsock(ua))) {
+ return 0;
+ }
+
+ bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+ bash_spaces(dev_name);
+ /* Ask for autochanger number of slots */
+ bnet_fsend(sd, NT_("autochanger drives %s\n"), dev_name);
+
+ while (bnet_recv(sd) >= 0) {
+ if (sscanf(sd->msg, NT_("drives=%d\n"), &drives) == 1) {
+ break;
+ } else {
+ bsendmsg(ua, "%s", sd->msg);
+ }
+ }
+ close_sd_bsock(ua);
+// bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives);
+ return drives;
+}
+
+
+
+
+/*
+ * Check if this is a cleaning tape by comparing the Volume name
+ * with the Cleaning Prefix. If they match, this is a cleaning
+ * tape.
+ */
+static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
+{
+ /* Find Pool resource */
+ ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
+ if (!ua->jcr->pool) {
+ bsendmsg(ua, _("Pool \"%s\" resource not found for volume \"%s\"!\n"),
+ pr->Name, mr->VolumeName);
+ return false;
+ }
+ if (ua->jcr->pool->cleaning_prefix == NULL) {
+ return false;
+ }
+ Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
+ ua->jcr->pool->cleaning_prefix, mr->VolumeName,
+ strlen(ua->jcr->pool->cleaning_prefix),
+ strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
+ strlen(ua->jcr->pool->cleaning_prefix)));
+ return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
+ strlen(ua->jcr->pool->cleaning_prefix)) == 0;
+}