3 * Bacula Director -- Tape labeling commands
5 * Kern Sibbald, April MMIII
10 Copyright (C) 2003-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
27 /* Slot list definition */
28 typedef struct s_vol_list {
29 struct s_vol_list *next;
35 /* Forward referenced functions */
36 static int do_label(UAContext *ua, const char *cmd, int relabel);
37 static void label_from_barcodes(UAContext *ua, int drive);
38 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
39 POOL_DBR *pr, int relabel, bool media_record_exits, int drive);
40 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan);
41 static void free_vol_list(vol_list_t *vol_list);
42 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr);
43 static BSOCK *open_sd_bsock(UAContext *ua);
44 static void close_sd_bsock(UAContext *ua);
45 static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive);
46 static int get_num_slots_from_SD(UAContext *ua);
52 * label storage=xxx volume=vvv
54 int label_cmd(UAContext *ua, const char *cmd)
56 return do_label(ua, cmd, 0); /* standard label */
59 int relabel_cmd(UAContext *ua, const char *cmd)
61 return do_label(ua, cmd, 1); /* relabel tape */
64 static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots)
69 /* slots are numbered 1 to num_slots */
70 for (int i=0; i <= num_slots; i++) {
73 i = find_arg_with_value(ua, "slots");
75 /* scan slot list in ua->argv[i] */
79 strip_trailing_junk(ua->argv[i]);
80 for (p=ua->argv[i]; p && *p; p=e) {
87 h = strchr(p, '-'); /* range? */
89 msg = _("Negative numbers not permitted\n");
94 if (!is_an_integer(h)) {
95 msg = _("Range end is not integer.\n");
99 if (!is_an_integer(p)) {
100 msg = _("Range start is not an integer.\n");
106 msg = _("Range end not bigger than start.\n");
111 if (!is_an_integer(p)) {
112 msg = _("Input value is not an integer.\n");
117 if (beg <= 0 || end <= 0) {
118 msg = _("Values must be be greater than zero.\n");
121 if (end > num_slots) {
122 msg = _("Slot too large.\n");
125 for (i=beg; i<=end; i++) {
126 slot_list[i] = 1; /* Turn on specified range */
130 /* Turn everything on */
131 for (i=1; i <= num_slots; i++) {
135 Dmsg0(100, "Slots turned on:\n");
136 for (i=1; i <= num_slots; i++) {
138 Dmsg1(100, "%d\n", i);
148 * Update Slots corresponding to Volumes in autochanger
150 int update_slots(UAContext *ua)
153 vol_list_t *vl, *vol_list = NULL;
164 store = get_storage_resource(ua, true/*arg is storage*/);
168 drive = get_storage_drive(ua, store);
169 set_storage(ua->jcr, store);
171 scan = find_arg(ua, N_("scan")) >= 0;
173 max_slots = get_num_slots_from_SD(ua);
174 if (max_slots <= 0) {
175 bsendmsg(ua, _("No slots in changer to scan.\n"));
178 slot_list = (char *)malloc(max_slots+1);
179 if (!get_user_slot_list(ua, slot_list, max_slots)) {
184 vol_list = get_vol_list_from_SD(ua, scan);
187 bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
191 /* Walk through the list updating the media records */
192 for (vl=vol_list; vl; vl=vl->next) {
193 if (vl->Slot > max_slots) {
194 bsendmsg(ua, _("Slot %d greater than max %d ignored.\n"),
195 vl->Slot, max_slots);
198 /* Check if user wants us to look at this slot */
199 if (!slot_list[vl->Slot]) {
200 Dmsg1(100, "Skipping slot=%d\n", vl->Slot);
203 /* If scanning, we read the label rather than the barcode */
209 vl->VolName = get_volume_name_from_SD(ua, vl->Slot, drive);
210 Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot);
212 slot_list[vl->Slot] = 0; /* clear Slot */
213 memset(&mr, 0, sizeof(mr));
216 mr.StorageId = store->StorageId;
217 /* Set InChanger to zero for this Slot */
219 db_make_inchanger_unique(ua->jcr, ua->db, &mr);
222 Dmsg1(000, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
223 bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), vl->Slot);
226 memset(&mr, 0, sizeof(mr));
227 bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
229 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
230 if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) {
233 mr.StorageId = store->StorageId;
234 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
235 bsendmsg(ua, "%s", db_strerror(ua->db));
238 "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
239 mr.VolumeName, mr.Slot);
242 bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
248 bsendmsg(ua, _("Volume \"%s\" not found in catalog. Slot=%d set InChanger to zero.\n"),
249 mr.VolumeName, vl->Slot);
253 memset(&mr, 0, sizeof(mr));
255 mr.StorageId = store->StorageId;
257 for (int i=1; i <= max_slots; i++) {
260 /* Set InChanger to zero for this Slot */
261 db_make_inchanger_unique(ua->jcr, ua->db, &mr);
268 free_vol_list(vol_list);
277 * Common routine for both label and relabel
279 static int do_label(UAContext *ua, const char *cmd, int relabel)
283 char dev_name[MAX_NAME_LENGTH];
286 bool print_reminder = true;
287 bool label_barcodes = false;
291 bool media_record_exists = false;
292 static const char *barcode_keyword[] = {
298 memset(&pr, 0, sizeof(pr));
303 if (!relabel && (i=find_arg_keyword(ua, barcode_keyword)) >= 0) {
304 *ua->argk[i] = 0; /* zap barcode keyword */
305 label_barcodes = true;
308 store = get_storage_resource(ua, true/*use default*/);
312 drive = get_storage_drive(ua, store);
313 set_storage(ua->jcr, store);
315 if (label_barcodes) {
316 label_from_barcodes(ua, drive);
320 /* If relabel get name of Volume to relabel */
322 /* Check for oldvolume=name */
323 i = find_arg_with_value(ua, "oldvolume");
325 memset(&omr, 0, sizeof(omr));
326 bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
327 if (db_get_media_record(ua->jcr, ua->db, &omr)) {
330 bsendmsg(ua, "%s", db_strerror(ua->db));
332 /* No keyword or Vol not found, ask user to select */
333 if (!select_media_dbr(ua, &omr)) {
337 /* Require Volume to be Purged or Recycled */
339 if (strcmp(omr.VolStatus, "Purged") != 0 && strcmp(omr.VolStatus, "Recycle") != 0) {
340 bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"),
341 omr.VolumeName, omr.VolStatus);
346 /* Check for volume=NewVolume */
347 i = find_arg_with_value(ua, "volume");
349 pm_strcpy(ua->cmd, ua->argv[i]);
353 /* Get a new Volume name */
355 media_record_exists = false;
356 if (!get_cmd(ua, _("Enter new Volume name: "))) {
360 if (!is_volume_name_legal(ua, ua->cmd)) {
364 memset(&mr, 0, sizeof(mr));
365 bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));
366 /* If VolBytes are zero the Volume is not labeled */
367 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
368 if (mr.VolBytes != 0) {
369 bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
373 media_record_exists = true;
378 /* If autochanger, request slot */
379 i = find_arg_with_value(ua, "slot");
381 mr.Slot = atoi(ua->argv[i]);
382 mr.InChanger = 1; /* assumed if we are labeling it */
383 } else if (store->autochanger) {
384 if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
387 mr.Slot = ua->pint32_val;
388 mr.InChanger = 1; /* assumed if we are labeling it */
390 mr.StorageId = store->StorageId;
392 bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
394 /* Must select Pool if not already done */
395 if (pr.PoolId == 0) {
396 memset(&pr, 0, sizeof(pr));
397 if (!select_pool_dbr(ua, &pr)) {
402 ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists, drive);
405 sd = ua->jcr->store_bsock;
407 /* Delete the old media record */
408 if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
409 bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"),
410 omr.VolumeName, db_strerror(ua->db));
412 bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
414 /* Update the number of Volumes in the pool */
416 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
417 bsendmsg(ua, "%s", db_strerror(ua->db));
422 bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
423 bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name);
424 bash_spaces(dev_name);
425 bnet_fsend(sd, "mount %s drive=%d", dev_name, drive);
426 unbash_spaces(dev_name);
427 while (bnet_recv(sd) >= 0) {
428 bsendmsg(ua, "%s", sd->msg);
430 * 3001 OK mount. Device=xxx or
431 * 3001 Mounted Volume vvvv
432 * 3002 Device "DVD-Writer" (/dev/hdc) is mounted.
433 * 3906 is cannot mount non-tape
434 * So for those, no need to print a reminder
436 if (strncmp(sd->msg, "3001 ", 5) == 0 ||
437 strncmp(sd->msg, "3002 ", 5) == 0 ||
438 strncmp(sd->msg, "3906 ", 5) == 0) {
439 print_reminder = false;
444 if (print_reminder) {
445 bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
453 * Request SD to send us the slot:barcodes, then wiffle
454 * through them all labeling them.
456 static void label_from_barcodes(UAContext *ua, int drive)
458 STORE *store = ua->jcr->store;
461 vol_list_t *vl, *vol_list = NULL;
462 bool media_record_exists;
467 max_slots = get_num_slots_from_SD(ua);
468 if (max_slots <= 0) {
469 bsendmsg(ua, _("No slots in changer to scan.\n"));
472 slot_list = (char *)malloc(max_slots+1);
473 if (!get_user_slot_list(ua, slot_list, max_slots)) {
477 vol_list = get_vol_list_from_SD(ua, false /*no scan*/);
480 bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
484 /* Display list of Volumes and ask if he really wants to proceed */
485 bsendmsg(ua, _("The following Volumes will be labeled:\n"
487 "==============\n"));
488 for (vl=vol_list; vl; vl=vl->next) {
489 if (!vl->VolName || !slot_list[vl->Slot]) {
492 bsendmsg(ua, "%4d %s\n", vl->Slot, vl->VolName);
494 if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
495 (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
499 memset(&pr, 0, sizeof(pr));
500 if (!select_pool_dbr(ua, &pr)) {
503 memset(&omr, 0, sizeof(omr));
505 /* Fire off the label requests */
506 for (vl=vol_list; vl; vl=vl->next) {
507 if (!vl->VolName || !slot_list[vl->Slot]) {
510 memset(&mr, 0, sizeof(mr));
511 bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
512 media_record_exists = false;
513 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
514 if (mr.VolBytes != 0) {
515 bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"),
516 vl->Slot, mr.VolumeName);
519 mr.StorageId = store->StorageId;
520 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
521 bsendmsg(ua, _("Error setting InChanger: ERR=%s"), db_strerror(ua->db));
525 media_record_exists = true;
528 mr.StorageId = store->StorageId;
530 * Deal with creating cleaning tape here. Normal tapes created in
531 * send_label_request() below
533 if (is_cleaning_tape(ua, &mr, &pr)) {
534 if (media_record_exists) { /* we update it */
536 bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
538 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
539 bsendmsg(ua, "%s", db_strerror(ua->db));
541 } else { /* create the media record */
542 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
543 bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
545 if (db_create_media_record(ua->jcr, ua->db, &mr)) {
546 bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
548 pr.NumVols++; /* this is a bit suspect */
549 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
550 bsendmsg(ua, "%s", db_strerror(ua->db));
553 bsendmsg(ua, _("Catalog error on cleaning tape: %s"), db_strerror(ua->db));
556 continue; /* done, go handle next volume */
558 bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
561 send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists, drive);
567 free_vol_list(vol_list);
574 * Check if the Volume name has legal characters
575 * If ua is non-NULL send the message
577 bool is_volume_name_legal(UAContext *ua, const char *name)
581 const char *accept = ":.-_";
583 /* Restrict the characters permitted in the Volume name */
584 for (p=name; *p; p++) {
585 if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) {
589 bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p);
594 if (len >= MAX_NAME_LENGTH) {
596 bsendmsg(ua, _("Volume name too long.\n"));
602 bsendmsg(ua, _("Volume name must be at least one character long.\n"));
610 * NOTE! This routine opens the SD socket but leaves it open
612 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
613 POOL_DBR *pr, int relabel, bool media_record_exists,
617 char dev_name[MAX_NAME_LENGTH];
620 if (!(sd=open_sd_bsock(ua))) {
623 bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name));
624 bash_spaces(dev_name);
625 bash_spaces(mr->VolumeName);
626 bash_spaces(mr->MediaType);
627 bash_spaces(pr->Name);
629 bash_spaces(omr->VolumeName);
630 bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s "
631 "MediaType=%s Slot=%d drive=%d",
632 dev_name, omr->VolumeName, mr->VolumeName, pr->Name,
633 mr->MediaType, mr->Slot, drive);
634 bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
635 omr->VolumeName, mr->VolumeName);
637 bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s "
639 dev_name, mr->VolumeName, pr->Name, mr->MediaType,
641 bsendmsg(ua, _("Sending label command for Volume \"%s\" Slot %d ...\n"),
642 mr->VolumeName, mr->Slot);
643 Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n",
644 dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive);
647 while (bnet_recv(sd) >= 0) {
648 bsendmsg(ua, "%s", sd->msg);
649 if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
653 unbash_spaces(mr->VolumeName);
654 unbash_spaces(mr->MediaType);
655 unbash_spaces(pr->Name);
656 mr->LabelDate = time(NULL);
657 mr->set_label_date = true;
659 if (media_record_exists) { /* we update it */
662 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
663 bsendmsg(ua, "%s", db_strerror(ua->db));
666 } else { /* create the media record */
667 set_pool_dbr_defaults_in_media_dbr(mr, pr);
668 mr->VolBytes = 1; /* flag indicating Volume labeled */
670 if (db_create_media_record(ua->jcr, ua->db, mr)) {
671 bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"),
672 mr->VolumeName, mr->Slot);
673 /* Update number of volumes in pool */
675 if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
676 bsendmsg(ua, "%s", db_strerror(ua->db));
679 bsendmsg(ua, "%s", db_strerror(ua->db));
684 bsendmsg(ua, _("Label command failed for Volume %s.\n"), mr->VolumeName);
689 static BSOCK *open_sd_bsock(UAContext *ua)
691 STORE *store = ua->jcr->store;
693 if (!ua->jcr->store_bsock) {
694 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
695 store->hdr.name, store->address, store->SDport);
696 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
697 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
701 return ua->jcr->store_bsock;
704 static void close_sd_bsock(UAContext *ua)
706 if (ua->jcr->store_bsock) {
707 bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
708 bnet_close(ua->jcr->store_bsock);
709 ua->jcr->store_bsock = NULL;
713 static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive)
715 STORE *store = ua->jcr->store;
717 char dev_name[MAX_NAME_LENGTH];
718 char *VolName = NULL;
721 if (!(sd=open_sd_bsock(ua))) {
722 bsendmsg(ua, _("Could not open SD socket.\n"));
725 bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
726 bash_spaces(dev_name);
727 /* Ask for autochanger list of volumes */
728 bnet_fsend(sd, _("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive);
729 Dmsg1(100, "Sent: %s", sd->msg);
731 /* Get Volume name in this Slot */
732 while (bnet_recv(sd) >= 0) {
733 bsendmsg(ua, "%s", sd->msg);
734 Dmsg1(100, "Got: %s", sd->msg);
735 if (strncmp(sd->msg, "3001 Volume=", 12) == 0) {
736 VolName = (char *)malloc(sd->msglen);
737 if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) {
745 Dmsg1(100, "get_vol_name=%s\n", NPRT(VolName));
750 * We get the slot list from the Storage daemon.
751 * If scan is set, we return all slots found,
752 * otherwise, we return only slots with valid barcodes (Volume names)
754 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
756 STORE *store = ua->jcr->store;
757 char dev_name[MAX_NAME_LENGTH];
760 vol_list_t *vol_list = NULL;
763 if (!(sd=open_sd_bsock(ua))) {
767 bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
768 bash_spaces(dev_name);
769 /* Ask for autochanger list of volumes */
770 bnet_fsend(sd, _("autochanger list %s \n"), dev_name);
772 /* Read and organize list of Volumes */
773 while (bnet_recv(sd) >= 0) {
776 strip_trailing_junk(sd->msg);
778 /* Check for returned SD messages */
779 if (sd->msg[0] == '3' && B_ISDIGIT(sd->msg[1]) &&
780 B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
782 bsendmsg(ua, "%s\n", sd->msg); /* pass them on to user */
786 /* Validate Slot: if scanning, otherwise Slot:Barcode */
787 p = strchr(sd->msg, ':');
789 /* Scanning -- require only valid slot */
790 Slot = atoi(sd->msg);
794 bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
799 if (p && strlen(p) > 1) {
801 if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
804 bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
810 if (!is_volume_name_legal(ua, p)) {
813 bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
818 /* Add Slot and VolumeName to list */
819 vl = (vol_list_t *)malloc(sizeof(vol_list_t));
823 p++; /* skip separator */
825 vl->VolName = bstrdup(p);
829 Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
834 /* Add new entry to end of list */
835 for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
848 static void free_vol_list(vol_list_t *vol_list)
853 for (vl=vol_list; vl; ) {
865 * We get the number of slots in the changer from the SD
867 static int get_num_slots_from_SD(UAContext *ua)
869 STORE *store = ua->jcr->store;
870 char dev_name[MAX_NAME_LENGTH];
875 if (!(sd=open_sd_bsock(ua))) {
879 bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
880 bash_spaces(dev_name);
881 /* Ask for autochanger number of slots */
882 bnet_fsend(sd, _("autochanger slots %s\n"), dev_name);
884 while (bnet_recv(sd) >= 0) {
885 if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
888 bsendmsg(ua, "%s", sd->msg);
892 bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
897 * We get the number of drives in the changer from the SD
899 int get_num_drives_from_SD(UAContext *ua)
901 STORE *store = ua->jcr->store;
902 char dev_name[MAX_NAME_LENGTH];
907 if (!(sd=open_sd_bsock(ua))) {
911 bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
912 bash_spaces(dev_name);
913 /* Ask for autochanger number of slots */
914 bnet_fsend(sd, _("autochanger drives %s\n"), dev_name);
916 while (bnet_recv(sd) >= 0) {
917 if (sscanf(sd->msg, "drives=%d\n", &drives) == 1) {
920 bsendmsg(ua, "%s", sd->msg);
924 // bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives);
932 * Check if this is a cleaning tape by comparing the Volume name
933 * with the Cleaning Prefix. If they match, this is a cleaning
936 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
938 /* Find Pool resource */
939 ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
940 if (!ua->jcr->pool) {
941 bsendmsg(ua, _("Pool \"%s\" resource not found!\n"), pr->Name);
944 if (ua->jcr->pool->cleaning_prefix == NULL) {
947 Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
948 ua->jcr->pool->cleaning_prefix, mr->VolumeName,
949 strlen(ua->jcr->pool->cleaning_prefix),
950 strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
951 strlen(ua->jcr->pool->cleaning_prefix)));
952 return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
953 strlen(ua->jcr->pool->cleaning_prefix)) == 0;