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