]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_label.c
- Make Director loop over alternative Devices specified in the
[bacula/bacula] / bacula / src / dird / ua_label.c
1 /*
2  *
3  *   Bacula Director -- Tape labeling commands
4  *
5  *     Kern Sibbald, April MMIII
6  *
7  *   Version $Id$
8  */
9
10 /*
11    Copyright (C) 2000-2005 Kern Sibbald
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of
16    the License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public
24    License along with this program; if not, write to the Free
25    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "dird.h"
32
33 /* Slot list definition */
34 typedef struct s_vol_list {
35    struct s_vol_list *next;
36    char *VolName;
37    int Slot;
38 } vol_list_t;
39
40
41 /* Forward referenced functions */
42 static int do_label(UAContext *ua, const char *cmd, int relabel);
43 static void label_from_barcodes(UAContext *ua);
44 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
45                POOL_DBR *pr, int relabel, bool media_record_exits);
46 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan);
47 static void free_vol_list(vol_list_t *vol_list);
48 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr);
49 static BSOCK *open_sd_bsock(UAContext *ua);
50 static void close_sd_bsock(UAContext *ua);
51 static char *get_volume_name_from_SD(UAContext *ua, int Slot);
52
53
54 /*
55  * Label a tape
56  *
57  *   label storage=xxx volume=vvv
58  */
59 int label_cmd(UAContext *ua, const char *cmd)
60 {
61    return do_label(ua, cmd, 0);       /* standard label */
62 }
63
64 int relabel_cmd(UAContext *ua, const char *cmd)
65 {
66    return do_label(ua, cmd, 1);      /* relabel tape */
67 }
68
69 static int const max_slots = 5000;
70
71 static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots)
72 {
73    int i;
74    const char *msg;
75
76    for (int i=0; i<num_slots; i++) {
77       slot_list[i] = 0;
78    }
79    i = find_arg_with_value(ua, "slots");
80    if (i >= 0) {
81       /* scan slot list in ua->argv[i] */
82       char *p, *e, *h;
83       int beg, end;
84
85       strip_trailing_junk(ua->argv[i]);
86       for (p=ua->argv[i]; p && *p; p=e) {
87          /* Check for list */
88          e = strchr(p, ',');
89          if (e) {
90             *e++ = 0;
91          }
92          /* Check for range */
93          h = strchr(p, '-');             /* range? */
94          if (h == p) {
95             msg = _("Negative numbers not permitted\n");
96             goto bail_out;
97          }
98          if (h) {
99             *h++ = 0;
100             if (!is_an_integer(h)) {
101                msg = _("Range end is not integer.\n");
102                goto bail_out;
103             }
104             skip_spaces(&p);
105             if (!is_an_integer(p)) {
106                msg = _("Range start is not an integer.\n");
107                goto bail_out;
108             }
109             beg = atoi(p);
110             end = atoi(h);
111             if (end < beg) {
112                msg = _("Range end not bigger than start.\n");
113                goto bail_out;
114             }
115          } else {
116             skip_spaces(&p);
117             if (!is_an_integer(p)) {
118                msg = _("Input value is not an integer.\n");
119                goto bail_out;
120             }
121             beg = end = atoi(p);
122          }
123          if (beg <= 0 || end <= 0) {
124             msg = _("Values must be be greater than zero.\n");
125             goto bail_out;
126          }
127          if (end >= num_slots) {
128             msg = _("Slot too large.\n");
129             goto bail_out;
130          }
131          for (i=beg; i<=end; i++) {
132             slot_list[i] = 1;         /* Turn on specified range */
133          }
134       }
135    } else {
136       /* Turn everything on */
137       for (i=0; i<num_slots; i++) {
138          slot_list[i] = 1;
139       }
140    }
141 #ifdef xxx_debug
142    printf("Slots turned on:\n");
143    for (i=1; i<num_slots; i++) {
144       if (slot_list[i]) {
145          printf("%d\n", i);
146       }
147    }
148 #endif
149    return true;
150
151 bail_out:
152    return false;
153 }
154
155 /*
156  * Update Slots corresponding to Volumes in autochanger
157  */
158 int update_slots(UAContext *ua)
159 {
160    STORE *store;
161    vol_list_t *vl, *vol_list = NULL;
162    MEDIA_DBR mr;
163    char *slot_list;
164    bool scan;
165
166    if (!open_db(ua)) {
167       return 1;
168    }
169    store = get_storage_resource(ua, 1);
170    if (!store) {
171       return 1;
172    }
173    set_storage(ua->jcr, store);
174
175    scan = find_arg(ua, _("scan")) >= 0;
176
177    slot_list = (char *)malloc(max_slots);
178    if (!get_user_slot_list(ua, slot_list, max_slots)) {
179       free(slot_list);
180       return 1;
181    }
182
183    vol_list = get_vol_list_from_SD(ua, scan);
184
185    if (!vol_list) {
186       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
187       goto bail_out;
188    }
189
190    /* Walk through the list updating the media records */
191    for (vl=vol_list; vl; vl=vl->next) {
192       if (vl->Slot >= max_slots) {
193          bsendmsg(ua, _("Slot %d larger than max %d ignored.\n"));
194          continue;
195       }
196       /* Check if user wants us to look at this slot */
197       if (!slot_list[vl->Slot]) {
198          Dmsg1(100, "Skipping slot=%d\n", vl->Slot);
199          continue;
200       }
201       /* If scanning, we read the label rather than the barcode */
202       if (scan) {
203          if (vl->VolName) {
204             free(vl->VolName);
205             vl->VolName = NULL;
206          }
207          vl->VolName = get_volume_name_from_SD(ua, vl->Slot);
208          Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot);
209       }
210       slot_list[vl->Slot] = 0;        /* clear Slot */
211       if (!vl->VolName) {
212          Dmsg1(100, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
213          memset(&mr, 0, sizeof(mr));
214          mr.Slot = vl->Slot;
215          mr.InChanger = 1;
216          mr.StorageId = store->StorageId;
217          /* Set InChanger to zero for this Slot */
218          db_lock(ua->db);
219          db_make_inchanger_unique(ua->jcr, ua->db, &mr);
220          db_unlock(ua->db);
221          bsendmsg(ua, _("No VolName for Slot=%d set InChanger to zero.\n"), vl->Slot);
222          continue;
223       }
224       memset(&mr, 0, sizeof(mr));
225       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
226       db_lock(ua->db);
227       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
228          if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) {
229             mr.Slot = vl->Slot;
230             mr.InChanger = 1;
231             mr.StorageId = store->StorageId;
232             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
233                bsendmsg(ua, "%s", db_strerror(ua->db));
234             } else {
235                bsendmsg(ua, _(
236                  "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
237                  mr.VolumeName, mr.Slot);
238             }
239          } else {
240             bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
241                mr.VolumeName);
242          }
243          db_unlock(ua->db);
244          continue;
245       } else {
246          bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"),
247              mr.VolumeName);
248       }
249       db_unlock(ua->db);
250    }
251    memset(&mr, 0, sizeof(mr));
252    mr.InChanger = 1;
253    mr.StorageId = store->StorageId;
254    db_lock(ua->db);
255    for (int i=1; i<max_slots; i++) {
256       if (slot_list[i]) {
257          mr.Slot = i;
258          /* Set InChanger to zero for this Slot */
259          db_make_inchanger_unique(ua->jcr, ua->db, &mr);
260       }
261    }
262    db_unlock(ua->db);
263
264 bail_out:
265
266    free_vol_list(vol_list);
267    free(slot_list);
268    close_sd_bsock(ua);
269
270    return 1;
271 }
272
273
274 /*
275  * Common routine for both label and relabel
276  */
277 static int do_label(UAContext *ua, const char *cmd, int relabel)
278 {
279    STORE *store;
280    BSOCK *sd;
281    char dev_name[MAX_NAME_LENGTH];
282    MEDIA_DBR mr, omr;
283    POOL_DBR pr;
284    bool print_reminder = true;
285    int ok = FALSE;
286    int i;
287    bool media_record_exists = false;
288    static const char *barcode_keyword[] = {
289       "barcode",
290       "barcodes",
291       NULL};
292
293
294    memset(&pr, 0, sizeof(pr));
295    if (!open_db(ua)) {
296       return 1;
297    }
298    store = get_storage_resource(ua, 1);
299    if (!store) {
300       return 1;
301    }
302    set_storage(ua->jcr, store);
303
304    if (!relabel && find_arg_keyword(ua, barcode_keyword) >= 0) {
305       label_from_barcodes(ua);
306       return 1;
307    }
308
309    /* If relabel get name of Volume to relabel */
310    if (relabel) {
311       /* Check for oldvolume=name */
312       i = find_arg_with_value(ua, "oldvolume");
313       if (i >= 0) {
314          memset(&omr, 0, sizeof(omr));
315          bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
316          if (db_get_media_record(ua->jcr, ua->db, &omr)) {
317             goto checkVol;
318          }
319          bsendmsg(ua, "%s", db_strerror(ua->db));
320       }
321       /* No keyword or Vol not found, ask user to select */
322       if (!select_media_dbr(ua, &omr)) {
323          return 1;
324       }
325
326       /* Require Volume to be Purged or Recycled */
327 checkVol:
328       if (strcmp(omr.VolStatus, "Purged") != 0 && strcmp(omr.VolStatus, "Recycle") != 0) {
329          bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"),
330             omr.VolumeName, omr.VolStatus);
331          return 1;
332       }
333    }
334
335    /* Check for volume=NewVolume */
336    i = find_arg_with_value(ua, "volume");
337    if (i >= 0) {
338       pm_strcpy(ua->cmd, ua->argv[i]);
339       goto checkName;
340    }
341
342    /* Get a new Volume name */
343    for ( ;; ) {
344       media_record_exists = false;
345       if (!get_cmd(ua, _("Enter new Volume name: "))) {
346          return 1;
347       }
348 checkName:
349       if (!is_volume_name_legal(ua, ua->cmd)) {
350          continue;
351       }
352
353       memset(&mr, 0, sizeof(mr));
354       bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));
355       /* If VolBytes are zero the Volume is not labeled */
356       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
357          if (mr.VolBytes != 0) {
358              bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
359                 mr.VolumeName);
360              continue;
361           }
362           media_record_exists = true;
363       }
364       break;                          /* Got it */
365    }
366
367    /* If autochanger, request slot */
368    if (store->autochanger) {
369       i = find_arg_with_value(ua, "slot");
370       if (i >= 0) {
371          mr.Slot = atoi(ua->argv[i]);
372       } else if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
373          return 1;
374       } else {
375          mr.Slot = ua->pint32_val;
376       }
377       mr.InChanger = 1;               /* assumed if we are labeling it */
378    }
379    mr.StorageId = store->StorageId;
380
381    bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
382
383    /* Must select Pool if not already done */
384    if (pr.PoolId == 0) {
385       memset(&pr, 0, sizeof(pr));
386       if (!select_pool_dbr(ua, &pr)) {
387          return 1;
388       }
389    }
390
391    ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists);
392
393    if (ok) {
394       sd = ua->jcr->store_bsock;
395       if (relabel) {
396          /* Delete the old media record */
397          if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
398             bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"),
399                omr.VolumeName, db_strerror(ua->db));
400          } else {
401             bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
402                omr.VolumeName);
403             /* Update the number of Volumes in the pool */
404             pr.NumVols--;
405             if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
406                bsendmsg(ua, "%s", db_strerror(ua->db));
407             }
408          }
409       }
410       if (ua->automount) {
411          bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
412          bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name);
413          bash_spaces(dev_name);
414          bnet_fsend(sd, "mount %s", dev_name);
415          unbash_spaces(dev_name);
416          while (bnet_recv(sd) >= 0) {
417             bsendmsg(ua, "%s", sd->msg);
418             /* Here we can get
419              *  3001 OK mount. Device=xxx      or
420              *  3001 Mounted Volume vvvv
421              *  3906 is cannot mount non-tape
422              * So for those, no need to print a reminder
423              */
424             if (strncmp(sd->msg, "3001 ", 5) == 0 ||
425                 strncmp(sd->msg, "3906 ", 5) == 0) {
426                print_reminder = false;
427             }
428          }
429       }
430    }
431    if (print_reminder) {
432       bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
433    }
434    close_sd_bsock(ua);
435
436    return 1;
437 }
438
439 /*
440  * Request SD to send us the slot:barcodes, then wiffle
441  *  through them all labeling them.
442  */
443 static void label_from_barcodes(UAContext *ua)
444 {
445    STORE *store = ua->jcr->store;
446    POOL_DBR pr;
447    MEDIA_DBR mr, omr;
448    vol_list_t *vl, *vol_list = NULL;
449    bool media_record_exists;
450    char *slot_list;
451
452    slot_list = (char *)malloc(max_slots);
453    if (!get_user_slot_list(ua, slot_list, max_slots)) {
454       goto bail_out;
455    }
456
457    vol_list = get_vol_list_from_SD(ua, false /*no scan*/);
458
459    if (!vol_list) {
460       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
461       goto bail_out;
462    }
463
464    /* Display list of Volumes and ask if he really wants to proceed */
465    bsendmsg(ua, _("The following Volumes will be labeled:\n"
466                   "Slot  Volume\n"
467                   "==============\n"));
468    for (vl=vol_list; vl; vl=vl->next) {
469       if (!vl->VolName || !slot_list[vl->Slot]) {
470          continue;
471       }
472       bsendmsg(ua, "%4d  %s\n", vl->Slot, vl->VolName);
473    }
474    if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
475        (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
476       goto bail_out;
477    }
478    /* Select a pool */
479    memset(&pr, 0, sizeof(pr));
480    if (!select_pool_dbr(ua, &pr)) {
481       goto bail_out;
482    }
483    memset(&omr, 0, sizeof(omr));
484
485    /* Fire off the label requests */
486    for (vl=vol_list; vl; vl=vl->next) {
487       if (!vl->VolName || !slot_list[vl->Slot]) {
488          continue;
489       }
490       memset(&mr, 0, sizeof(mr));
491       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
492       media_record_exists = false;
493       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
494           if (mr.VolBytes != 0) {
495              bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"),
496                 vl->Slot, mr.VolumeName);
497              mr.Slot = vl->Slot;
498              mr.InChanger = 1;
499              mr.StorageId = store->StorageId;
500              if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
501                 bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db));
502              }
503              continue;
504           }
505           media_record_exists = true;
506       }
507       mr.InChanger = 1;
508       mr.StorageId = store->StorageId;
509       /*
510        * Deal with creating cleaning tape here. Normal tapes created in
511        *  send_label_request() below
512        */
513       if (is_cleaning_tape(ua, &mr, &pr)) {
514          if (media_record_exists) {      /* we update it */
515             mr.VolBytes = 1;
516             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
517                 bsendmsg(ua, "%s", db_strerror(ua->db));
518             }
519          } else {                        /* create the media record */
520             set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
521             if (db_create_media_record(ua->jcr, ua->db, &mr)) {
522                bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
523                   mr.VolumeName);
524                pr.NumVols++;          /* this is a bit suspect */
525                if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
526                   bsendmsg(ua, "%s", db_strerror(ua->db));
527                }
528             } else {
529                bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db));
530             }
531          }
532          continue;                    /* done, go handle next volume */
533       }
534       bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
535
536       mr.Slot = vl->Slot;
537       send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists);
538    }
539
540
541 bail_out:
542    free(slot_list);
543    free_vol_list(vol_list);
544    close_sd_bsock(ua);
545
546    return;
547 }
548
549 /*
550  * Check if the Volume name has legal characters
551  * If ua is non-NULL send the message
552  */
553 bool is_volume_name_legal(UAContext *ua, const char *name)
554 {
555    int len;
556    const char *p;
557    const char *accept = ":.-_";
558
559    /* Restrict the characters permitted in the Volume name */
560    for (p=name; *p; p++) {
561       if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) {
562          continue;
563       }
564       if (ua) {
565          bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p);
566       }
567       return 0;
568    }
569    len = strlen(name);
570    if (len >= MAX_NAME_LENGTH) {
571       if (ua) {
572          bsendmsg(ua, _("Volume name too long.\n"));
573       }
574       return 0;
575    }
576    if (len == 0) {
577       if (ua) {
578          bsendmsg(ua, _("Volume name must be at least one character long.\n"));
579       }
580       return 0;
581    }
582    return 1;
583 }
584
585 /*
586  * NOTE! This routine opens the SD socket but leaves it open
587  */
588 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
589                                POOL_DBR *pr, int relabel, bool media_record_exists)
590 {
591    BSOCK *sd;
592    char dev_name[MAX_NAME_LENGTH];
593    bool ok = false;
594
595    if (!(sd=open_sd_bsock(ua))) {
596       return false;
597    }
598    bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name));
599    bash_spaces(dev_name);
600    bash_spaces(mr->VolumeName);
601    bash_spaces(mr->MediaType);
602    bash_spaces(pr->Name);
603    if (relabel) {
604       bash_spaces(omr->VolumeName);
605       bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d",
606          dev_name, omr->VolumeName, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
607       bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
608          omr->VolumeName, mr->VolumeName);
609    } else {
610       bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d",
611          dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
612       bsendmsg(ua, _("Sending label command for Volume \"%s\" Slot %d ...\n"),
613          mr->VolumeName, mr->Slot);
614       Dmsg5(200, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d\n",
615          dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
616    }
617
618    while (bnet_recv(sd) >= 0) {
619       bsendmsg(ua, "%s", sd->msg);
620       if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
621          ok = true;
622       }
623    }
624    unbash_spaces(mr->VolumeName);
625    unbash_spaces(mr->MediaType);
626    unbash_spaces(pr->Name);
627    mr->LabelDate = time(NULL);
628    mr->set_label_date = true;
629    if (ok) {
630       if (media_record_exists) {      /* we update it */
631          mr->VolBytes = 1;
632          mr->InChanger = 1;
633          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
634              bsendmsg(ua, "%s", db_strerror(ua->db));
635              ok = false;
636          }
637       } else {                        /* create the media record */
638          set_pool_dbr_defaults_in_media_dbr(mr, pr);
639          mr->VolBytes = 1;               /* flag indicating Volume labeled */
640          mr->InChanger = 1;
641          if (db_create_media_record(ua->jcr, ua->db, mr)) {
642             bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
643             mr->VolumeName, mr->Slot);
644             /* Update number of volumes in pool */
645             pr->NumVols++;
646             if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
647                bsendmsg(ua, "%s", db_strerror(ua->db));
648             }
649          } else {
650             bsendmsg(ua, "%s", db_strerror(ua->db));
651             ok = false;
652          }
653       }
654    } else {
655       bsendmsg(ua, _("Label command failed for Volume %s.\n"), mr->VolumeName);
656    }
657    return ok;
658 }
659
660 static BSOCK *open_sd_bsock(UAContext *ua)
661 {
662    STORE *store = ua->jcr->store;
663
664    if (!ua->jcr->store_bsock) {
665       bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
666          store->hdr.name, store->address, store->SDport);
667       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
668          bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
669          return NULL;
670       }
671    }
672    return ua->jcr->store_bsock;
673 }
674
675 static void close_sd_bsock(UAContext *ua)
676 {
677    if (ua->jcr->store_bsock) {
678       bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
679       bnet_close(ua->jcr->store_bsock);
680       ua->jcr->store_bsock = NULL;
681    }
682 }
683
684 static char *get_volume_name_from_SD(UAContext *ua, int Slot)
685 {
686    STORE *store = ua->jcr->store;
687    BSOCK *sd;
688    char dev_name[MAX_NAME_LENGTH];
689    char *VolName = NULL;
690    int rtn_slot;
691
692    if (!(sd=open_sd_bsock(ua))) {
693       bsendmsg(ua, _("Could not open SD socket.\n"));
694       return NULL;
695    }
696    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
697    bash_spaces(dev_name);
698    /* Ask for autochanger list of volumes */
699    bnet_fsend(sd, _("readlabel %s Slot=%d\n"), dev_name, Slot);
700    Dmsg1(100, "Sent: %s", sd->msg);
701
702    /* Get Volume name in this Slot */
703    while (bnet_recv(sd) >= 0) {
704       bsendmsg(ua, "%s", sd->msg);
705       Dmsg1(100, "Got: %s", sd->msg);
706       if (strncmp(sd->msg, "3001 Volume=", 12) == 0) {
707          VolName = (char *)malloc(sd->msglen);
708          if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) {
709             break;
710          }
711          free(VolName);
712          VolName = NULL;
713       }
714    }
715    close_sd_bsock(ua);
716    Dmsg1(200, "get_vol_name=%s\n", NPRT(VolName));
717    return VolName;
718 }
719
720 /*
721  * We get the slot list from the Storage daemon.
722  *  If scan is set, we return all slots found,
723  *  otherwise, we return only slots with valid barcodes (Volume names)
724  */
725 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
726 {
727    STORE *store = ua->jcr->store;
728    char dev_name[MAX_NAME_LENGTH];
729    BSOCK *sd;
730    vol_list_t *vl;
731    vol_list_t *vol_list = NULL;
732
733
734    if (!(sd=open_sd_bsock(ua))) {
735       return NULL;
736    }
737
738    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
739    bash_spaces(dev_name);
740    /* Ask for autochanger list of volumes */
741    bnet_fsend(sd, _("autochanger list %s \n"), dev_name);
742
743    /* Read and organize list of Volumes */
744    while (bnet_recv(sd) >= 0) {
745       char *p;
746       int Slot;
747       strip_trailing_junk(sd->msg);
748
749       /* Check for returned SD messages */
750       if (sd->msg[0] == '3'     && B_ISDIGIT(sd->msg[1]) &&
751           B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
752           sd->msg[4] == ' ') {
753          bsendmsg(ua, "%s\n", sd->msg);   /* pass them on to user */
754          continue;
755       }
756
757       /* Validate Slot: if scanning, otherwise  Slot:Barcode */
758       p = strchr(sd->msg, ':');
759       if (scan && p) {
760          /* Scanning -- require only valid slot */
761          Slot = atoi(sd->msg);
762          if (Slot <= 0) {
763             p--;
764             *p = ':';
765             bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
766             continue;
767          }
768       } else {
769          /* Not scanning */
770          if (p && strlen(p) > 1) {
771             *p++ = 0;
772             if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
773                p--;
774                *p = ':';
775                bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
776                continue;
777             }
778          } else {
779             continue;
780          }
781          if (!is_volume_name_legal(ua, p)) {
782             p--;
783             *p = ':';
784             bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
785             continue;
786          }
787       }
788
789       /* Add Slot and VolumeName to list */
790       vl = (vol_list_t *)malloc(sizeof(vol_list_t));
791       vl->Slot = Slot;
792       if (p) {
793          if (*p == ':') {
794             p++;                      /* skip separator */
795          }
796          vl->VolName = bstrdup(p);
797       } else {
798          vl->VolName = NULL;
799       }
800       Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
801       if (!vol_list) {
802          vl->next = vol_list;
803          vol_list = vl;
804       } else {
805          /* Add new entry to end of list */
806          for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
807             if (!tvl->next) {
808                tvl->next = vl;
809                vl->next = NULL;
810                break;
811             }
812          }
813       }
814    }
815    close_sd_bsock(ua);
816    return vol_list;
817 }
818
819 static void free_vol_list(vol_list_t *vol_list)
820 {
821    vol_list_t *vl;
822
823    /* Free list */
824    for (vl=vol_list; vl; ) {
825       vol_list_t *ovl;
826       if (vl->VolName) {
827          free(vl->VolName);
828       }
829       ovl = vl;
830       vl = vl->next;
831       free(ovl);
832    }
833 }
834
835
836 /*
837  * Check if this is a cleaning tape by comparing the Volume name
838  *  with the Cleaning Prefix. If they match, this is a cleaning
839  *  tape.
840  */
841 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
842 {
843    /* Find Pool resource */
844    ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
845    if (!ua->jcr->pool) {
846       bsendmsg(ua, _("Pool \"%s\" resource not found!\n"), pr->Name);
847       return true;
848    }
849    if (ua->jcr->pool->cleaning_prefix == NULL) {
850       return false;
851    }
852    Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
853       ua->jcr->pool->cleaning_prefix, mr->VolumeName,
854       strlen(ua->jcr->pool->cleaning_prefix),
855       strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
856                   strlen(ua->jcr->pool->cleaning_prefix)));
857    return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
858                   strlen(ua->jcr->pool->cleaning_prefix)) == 0;
859 }