]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_label.c
Make sure to set storage before trying to set drive.
[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, 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);
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    /* slots are numbered 1 to num_slots */
70    for (int i=0; i <= num_slots; i++) {
71       slot_list[i] = 0;
72    }
73    i = find_arg_with_value(ua, "slots");
74    if (i > 0) {
75       /* scan slot list in ua->argv[i] */
76       char *p, *e, *h;
77       int beg, end;
78
79       strip_trailing_junk(ua->argv[i]);
80       for (p=ua->argv[i]; p && *p; p=e) {
81          /* Check for list */
82          e = strchr(p, ',');
83          if (e) {
84             *e++ = 0;
85          }
86          /* Check for range */
87          h = strchr(p, '-');             /* range? */
88          if (h == p) {
89             msg = _("Negative numbers not permitted\n");
90             goto bail_out;
91          }
92          if (h) {
93             *h++ = 0;
94             if (!is_an_integer(h)) {
95                msg = _("Range end is not integer.\n");
96                goto bail_out;
97             }
98             skip_spaces(&p);
99             if (!is_an_integer(p)) {
100                msg = _("Range start is not an integer.\n");
101                goto bail_out;
102             }
103             beg = atoi(p);
104             end = atoi(h);
105             if (end < beg) {
106                msg = _("Range end not bigger than start.\n");
107                goto bail_out;
108             }
109          } else {
110             skip_spaces(&p);
111             if (!is_an_integer(p)) {
112                msg = _("Input value is not an integer.\n");
113                goto bail_out;
114             }
115             beg = end = atoi(p);
116          }
117          if (beg <= 0 || end <= 0) {
118             msg = _("Values must be be greater than zero.\n");
119             goto bail_out;
120          }
121          if (end > num_slots) {
122             msg = _("Slot too large.\n");
123             goto bail_out;
124          }
125          for (i=beg; i<=end; i++) {
126             slot_list[i] = 1;         /* Turn on specified range */
127          }
128       }
129    } else {
130       /* Turn everything on */
131       for (i=1; i <= num_slots; i++) {
132          slot_list[i] = 1;
133       }
134    }
135    Dmsg0(100, "Slots turned on:\n");
136    for (i=1; i <= num_slots; i++) {
137       if (slot_list[i]) {
138          Dmsg1(100, "%d\n", i);
139       }
140    }
141    return true;
142
143 bail_out:
144    return false;
145 }
146
147 /*
148  * Update Slots corresponding to Volumes in autochanger
149  */
150 int update_slots(UAContext *ua)
151 {
152    STORE *store;
153    vol_list_t *vl, *vol_list = NULL;
154    MEDIA_DBR mr;
155    char *slot_list;
156    bool scan;
157    int max_slots;
158    int drive;
159
160
161    if (!open_db(ua)) {
162       return 1;
163    }
164    store = get_storage_resource(ua, true/*arg is storage*/);
165    if (!store) {
166       return 1;
167    }
168    set_storage(ua->jcr, store);
169    drive = get_storage_drive(ua, store);
170
171    scan = find_arg(ua, N_("scan")) >= 0;
172
173    max_slots = get_num_slots_from_SD(ua);
174    if (max_slots <= 0) {
175       bsendmsg(ua, _("No slots in changer to scan.\n"));
176       return 1;
177    }
178    slot_list = (char *)malloc(max_slots+1);
179    if (!get_user_slot_list(ua, slot_list, max_slots)) {
180       free(slot_list);
181       return 1;
182    }
183
184    vol_list = get_vol_list_from_SD(ua, scan);
185
186    if (!vol_list) {
187       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
188       goto bail_out;
189    }
190
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);
196          continue;
197       }
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);
201          continue;
202       }
203       /* If scanning, we read the label rather than the barcode */
204       if (scan) {
205          if (vl->VolName) {
206             free(vl->VolName);
207             vl->VolName = NULL;
208          }
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);
211       }
212       slot_list[vl->Slot] = 0;        /* clear 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       if (!vl->VolName) {
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);
224          continue;
225       }
226       memset(&mr, 0, sizeof(mr));
227       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
228       db_lock(ua->db);
229       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
230          if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) {
231             mr.Slot = vl->Slot;
232             mr.InChanger = 1;
233             mr.StorageId = store->StorageId;
234             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
235                bsendmsg(ua, "%s", db_strerror(ua->db));
236             } else {
237                bsendmsg(ua, _(
238                  "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
239                  mr.VolumeName, mr.Slot);
240             }
241          } else {
242             bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
243                mr.VolumeName);
244          }
245          db_unlock(ua->db);
246          continue;
247       } else {
248          bsendmsg(ua, _("Volume \"%s\" not found in catalog. Slot=%d set InChanger to zero.\n"),
249              mr.VolumeName, vl->Slot);
250       }
251       db_unlock(ua->db);
252    }
253    memset(&mr, 0, sizeof(mr));
254    mr.InChanger = 1;
255    mr.StorageId = store->StorageId;
256    db_lock(ua->db);
257    for (int i=1; i <= max_slots; i++) {
258       if (slot_list[i]) {
259          mr.Slot = i;
260          /* Set InChanger to zero for this Slot */
261          db_make_inchanger_unique(ua->jcr, ua->db, &mr);
262       }
263    }
264    db_unlock(ua->db);
265
266 bail_out:
267
268    free_vol_list(vol_list);
269    free(slot_list);
270    close_sd_bsock(ua);
271
272    return 1;
273 }
274
275
276 /*
277  * Common routine for both label and relabel
278  */
279 static int do_label(UAContext *ua, const char *cmd, int relabel)
280 {
281    STORE *store;
282    BSOCK *sd;
283    char dev_name[MAX_NAME_LENGTH];
284    MEDIA_DBR mr, omr;
285    POOL_DBR pr;
286    bool print_reminder = true;
287    bool label_barcodes = false;
288    int ok = FALSE;
289    int i;
290    int drive;
291    bool media_record_exists = false;
292    static const char *barcode_keyword[] = {
293       "barcode",
294       "barcodes",
295       NULL};
296
297
298    memset(&pr, 0, sizeof(pr));
299    if (!open_db(ua)) {
300       return 1;
301    }
302
303    if (!relabel && (i=find_arg_keyword(ua, barcode_keyword)) >= 0) {
304       *ua->argk[i] = 0;      /* zap barcode keyword */
305       label_barcodes = true;
306    }
307
308    store = get_storage_resource(ua, true/*use default*/);
309    if (!store) {
310       return 1;
311    }
312    set_storage(ua->jcr, store);
313    drive = get_storage_drive(ua, store);
314
315    if (label_barcodes) {
316       label_from_barcodes(ua, drive);
317       return 1;
318    }
319
320    /* If relabel get name of Volume to relabel */
321    if (relabel) {
322       /* Check for oldvolume=name */
323       i = find_arg_with_value(ua, "oldvolume");
324       if (i >= 0) {
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)) {
328             goto checkVol;
329          }
330          bsendmsg(ua, "%s", db_strerror(ua->db));
331       }
332       /* No keyword or Vol not found, ask user to select */
333       if (!select_media_dbr(ua, &omr)) {
334          return 1;
335       }
336
337       /* Require Volume to be Purged or Recycled */
338 checkVol:
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);
342          return 1;
343       }
344    }
345
346    /* Check for volume=NewVolume */
347    i = find_arg_with_value(ua, "volume");
348    if (i >= 0) {
349       pm_strcpy(ua->cmd, ua->argv[i]);
350       goto checkName;
351    }
352
353    /* Get a new Volume name */
354    for ( ;; ) {
355       media_record_exists = false;
356       if (!get_cmd(ua, _("Enter new Volume name: "))) {
357          return 1;
358       }
359 checkName:
360       if (!is_volume_name_legal(ua, ua->cmd)) {
361          continue;
362       }
363
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"),
370                 mr.VolumeName);
371              continue;
372           }
373           media_record_exists = true;
374       }
375       break;                          /* Got it */
376    }
377
378    /* If autochanger, request slot */
379    i = find_arg_with_value(ua, "slot");
380    if (i >= 0) {
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): "))) {
385          return 1;
386       }
387       mr.Slot = ua->pint32_val;
388       mr.InChanger = 1;               /* assumed if we are labeling it */
389    }
390    mr.StorageId = store->StorageId;
391
392    bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
393
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)) {
398          return 1;
399       }
400    }
401
402    ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists, drive);
403
404    if (ok) {
405       sd = ua->jcr->store_bsock;
406       if (relabel) {
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));
411          } else {
412             bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
413                omr.VolumeName);
414             /* Update the number of Volumes in the pool */
415             pr.NumVols--;
416             if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
417                bsendmsg(ua, "%s", db_strerror(ua->db));
418             }
419          }
420       }
421       if (ua->automount) {
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);
429             /* Here we can get
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
435              */
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;
440             }
441          }
442       }
443    }
444    if (print_reminder) {
445       bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
446    }
447    close_sd_bsock(ua);
448
449    return 1;
450 }
451
452 /*
453  * Request SD to send us the slot:barcodes, then wiffle
454  *  through them all labeling them.
455  */
456 static void label_from_barcodes(UAContext *ua, int drive)
457 {
458    STORE *store = ua->jcr->store;
459    POOL_DBR pr;
460    MEDIA_DBR mr, omr;
461    vol_list_t *vl, *vol_list = NULL;
462    bool media_record_exists;
463    char *slot_list;
464    int max_slots;
465
466   
467    max_slots = get_num_slots_from_SD(ua);
468    if (max_slots <= 0) {
469       bsendmsg(ua, _("No slots in changer to scan.\n"));
470       return;
471    }
472    slot_list = (char *)malloc(max_slots+1);
473    if (!get_user_slot_list(ua, slot_list, max_slots)) {
474       goto bail_out;
475    }
476
477    vol_list = get_vol_list_from_SD(ua, false /*no scan*/);
478
479    if (!vol_list) {
480       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
481       goto bail_out;
482    }
483
484    /* Display list of Volumes and ask if he really wants to proceed */
485    bsendmsg(ua, _("The following Volumes will be labeled:\n"
486                   "Slot  Volume\n"
487                   "==============\n"));
488    for (vl=vol_list; vl; vl=vl->next) {
489       if (!vl->VolName || !slot_list[vl->Slot]) {
490          continue;
491       }
492       bsendmsg(ua, "%4d  %s\n", vl->Slot, vl->VolName);
493    }
494    if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
495        (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
496       goto bail_out;
497    }
498    /* Select a pool */
499    memset(&pr, 0, sizeof(pr));
500    if (!select_pool_dbr(ua, &pr)) {
501       goto bail_out;
502    }
503    memset(&omr, 0, sizeof(omr));
504
505    /* Fire off the label requests */
506    for (vl=vol_list; vl; vl=vl->next) {
507       if (!vl->VolName || !slot_list[vl->Slot]) {
508          continue;
509       }
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);
517              mr.Slot = vl->Slot;
518              mr.InChanger = 1;
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));
522              }
523              continue;
524           }
525           media_record_exists = true;
526       }
527       mr.InChanger = 1;
528       mr.StorageId = store->StorageId;
529       /*
530        * Deal with creating cleaning tape here. Normal tapes created in
531        *  send_label_request() below
532        */
533       if (is_cleaning_tape(ua, &mr, &pr)) {
534          if (media_record_exists) {      /* we update it */
535             mr.VolBytes = 1;
536             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
537             mr.MediaType[0] = 0;
538             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
539                 bsendmsg(ua, "%s", db_strerror(ua->db));
540             }
541          } else {                        /* create the media record */
542             set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
543             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
544             mr.MediaType[0] = 0;
545             if (db_create_media_record(ua->jcr, ua->db, &mr)) {
546                bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
547                   mr.VolumeName);
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));
551                }
552             } else {
553                bsendmsg(ua, _("Catalog error on cleaning tape: %s"), db_strerror(ua->db));
554             }
555          }
556          continue;                    /* done, go handle next volume */
557       }
558       bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
559
560       mr.Slot = vl->Slot;
561       send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists, drive);
562    }
563
564
565 bail_out:
566    free(slot_list);
567    free_vol_list(vol_list);
568    close_sd_bsock(ua);
569
570    return;
571 }
572
573 /*
574  * Check if the Volume name has legal characters
575  * If ua is non-NULL send the message
576  */
577 bool is_volume_name_legal(UAContext *ua, const char *name)
578 {
579    int len;
580    const char *p;
581    const char *accept = ":.-_";
582
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))) {
586          continue;
587       }
588       if (ua) {
589          bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p);
590       }
591       return 0;
592    }
593    len = strlen(name);
594    if (len >= MAX_NAME_LENGTH) {
595       if (ua) {
596          bsendmsg(ua, _("Volume name too long.\n"));
597       }
598       return 0;
599    }
600    if (len == 0) {
601       if (ua) {
602          bsendmsg(ua, _("Volume name must be at least one character long.\n"));
603       }
604       return 0;
605    }
606    return 1;
607 }
608
609 /*
610  * NOTE! This routine opens the SD socket but leaves it open
611  */
612 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
613                                POOL_DBR *pr, int relabel, bool media_record_exists,
614                                int drive)
615 {
616    BSOCK *sd;
617    char dev_name[MAX_NAME_LENGTH];
618    bool ok = false;
619
620    if (!(sd=open_sd_bsock(ua))) {
621       return false;
622    }
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);
628    if (relabel) {
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);
636    } else {
637       bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s "
638                      "Slot=%d drive=%d",
639                  dev_name, mr->VolumeName, pr->Name, mr->MediaType, 
640                  mr->Slot, drive);
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);
645    }
646
647    while (bnet_recv(sd) >= 0) {
648       bsendmsg(ua, "%s", sd->msg);
649       if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
650          ok = true;
651       }
652    }
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;
658    if (ok) {
659       if (media_record_exists) {      /* we update it */
660          mr->VolBytes = 1;
661          mr->InChanger = 1;
662          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
663              bsendmsg(ua, "%s", db_strerror(ua->db));
664              ok = false;
665          }
666       } else {                        /* create the media record */
667          set_pool_dbr_defaults_in_media_dbr(mr, pr);
668          mr->VolBytes = 1;               /* flag indicating Volume labeled */
669          mr->InChanger = 1;
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 */
674             pr->NumVols++;
675             if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
676                bsendmsg(ua, "%s", db_strerror(ua->db));
677             }
678          } else {
679             bsendmsg(ua, "%s", db_strerror(ua->db));
680             ok = false;
681          }
682       }
683    } else {
684       bsendmsg(ua, _("Label command failed for Volume %s.\n"), mr->VolumeName);
685    }
686    return ok;
687 }
688
689 static BSOCK *open_sd_bsock(UAContext *ua)
690 {
691    STORE *store = ua->jcr->store;
692
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"));
698          return NULL;
699       }
700    }
701    return ua->jcr->store_bsock;
702 }
703
704 static void close_sd_bsock(UAContext *ua)
705 {
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;
710    }
711 }
712
713 static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive)
714 {
715    STORE *store = ua->jcr->store;
716    BSOCK *sd;
717    char dev_name[MAX_NAME_LENGTH];
718    char *VolName = NULL;
719    int rtn_slot;
720
721    if (!(sd=open_sd_bsock(ua))) {
722       bsendmsg(ua, _("Could not open SD socket.\n"));
723       return NULL;
724    }
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);
730
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) {
738             break;
739          }
740          free(VolName);
741          VolName = NULL;
742       }
743    }
744    close_sd_bsock(ua);
745    Dmsg1(100, "get_vol_name=%s\n", NPRT(VolName));
746    return VolName;
747 }
748
749 /*
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)
753  */
754 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
755 {
756    STORE *store = ua->jcr->store;
757    char dev_name[MAX_NAME_LENGTH];
758    BSOCK *sd;
759    vol_list_t *vl;
760    vol_list_t *vol_list = NULL;
761
762
763    if (!(sd=open_sd_bsock(ua))) {
764       return NULL;
765    }
766
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);
771
772    /* Read and organize list of Volumes */
773    while (bnet_recv(sd) >= 0) {
774       char *p;
775       int Slot;
776       strip_trailing_junk(sd->msg);
777
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]) &&
781           sd->msg[4] == ' ') {
782          bsendmsg(ua, "%s\n", sd->msg);   /* pass them on to user */
783          continue;
784       }
785
786       /* Validate Slot: if scanning, otherwise  Slot:Barcode */
787       p = strchr(sd->msg, ':');
788       if (scan && p) {
789          /* Scanning -- require only valid slot */
790          Slot = atoi(sd->msg);
791          if (Slot <= 0) {
792             p--;
793             *p = ':';
794             bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
795             continue;
796          }
797       } else {
798          /* Not scanning */
799          if (p && strlen(p) > 1) {
800             *p++ = 0;
801             if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
802                p--;
803                *p = ':';
804                bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
805                continue;
806             }
807          } else {
808             continue;
809          }
810          if (!is_volume_name_legal(ua, p)) {
811             p--;
812             *p = ':';
813             bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
814             continue;
815          }
816       }
817
818       /* Add Slot and VolumeName to list */
819       vl = (vol_list_t *)malloc(sizeof(vol_list_t));
820       vl->Slot = Slot;
821       if (p) {
822          if (*p == ':') {
823             p++;                      /* skip separator */
824          }
825          vl->VolName = bstrdup(p);
826       } else {
827          vl->VolName = NULL;
828       }
829       Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
830       if (!vol_list) {
831          vl->next = vol_list;
832          vol_list = vl;
833       } else {
834          /* Add new entry to end of list */
835          for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
836             if (!tvl->next) {
837                tvl->next = vl;
838                vl->next = NULL;
839                break;
840             }
841          }
842       }
843    }
844    close_sd_bsock(ua);
845    return vol_list;
846 }
847
848 static void free_vol_list(vol_list_t *vol_list)
849 {
850    vol_list_t *vl;
851
852    /* Free list */
853    for (vl=vol_list; vl; ) {
854       vol_list_t *ovl;
855       if (vl->VolName) {
856          free(vl->VolName);
857       }
858       ovl = vl;
859       vl = vl->next;
860       free(ovl);
861    }
862 }
863
864 /*
865  * We get the number of slots in the changer from the SD
866  */
867 static int get_num_slots_from_SD(UAContext *ua)
868 {
869    STORE *store = ua->jcr->store;
870    char dev_name[MAX_NAME_LENGTH];
871    BSOCK *sd;
872    int slots = 0;
873
874
875    if (!(sd=open_sd_bsock(ua))) {
876       return 0;
877    }
878
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);
883
884    while (bnet_recv(sd) >= 0) {
885       if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
886          break;
887       } else {
888          bsendmsg(ua, "%s", sd->msg);
889       }
890    }
891    close_sd_bsock(ua);
892    bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
893    return slots;
894 }
895
896 /*
897  * We get the number of drives in the changer from the SD
898  */
899 int get_num_drives_from_SD(UAContext *ua)
900 {
901    STORE *store = ua->jcr->store;
902    char dev_name[MAX_NAME_LENGTH];
903    BSOCK *sd;
904    int drives = 0;
905
906
907    if (!(sd=open_sd_bsock(ua))) {
908       return 0;
909    }
910
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);
915
916    while (bnet_recv(sd) >= 0) {
917       if (sscanf(sd->msg, "drives=%d\n", &drives) == 1) {
918          break;
919       } else {
920          bsendmsg(ua, "%s", sd->msg);
921       }
922    }
923    close_sd_bsock(ua);
924 //   bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives);
925    return drives;
926 }
927
928
929
930
931 /*
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
934  *  tape.
935  */
936 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
937 {
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);
942       return true;
943    }
944    if (ua->jcr->pool->cleaning_prefix == NULL) {
945       return false;
946    }
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;
954 }