]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_label.c
03Dec05
[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             mr.StorageId = store->StorageId;
539             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
540                 bsendmsg(ua, "%s", db_strerror(ua->db));
541             }
542          } else {                        /* create the media record */
543             set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
544             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
545             mr.MediaType[0] = 0;
546             if (db_create_media_record(ua->jcr, ua->db, &mr)) {
547                bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
548                   mr.VolumeName);
549                pr.NumVols++;          /* this is a bit suspect */
550                if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
551                   bsendmsg(ua, "%s", db_strerror(ua->db));
552                }
553             } else {
554                bsendmsg(ua, _("Catalog error on cleaning tape: %s"), db_strerror(ua->db));
555             }
556          }
557          continue;                    /* done, go handle next volume */
558       }
559       bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
560
561       mr.Slot = vl->Slot;
562       send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists, drive);
563    }
564
565
566 bail_out:
567    free(slot_list);
568    free_vol_list(vol_list);
569    close_sd_bsock(ua);
570
571    return;
572 }
573
574 /*
575  * Check if the Volume name has legal characters
576  * If ua is non-NULL send the message
577  */
578 bool is_volume_name_legal(UAContext *ua, const char *name)
579 {
580    int len;
581    const char *p;
582    const char *accept = ":.-_";
583
584    /* Restrict the characters permitted in the Volume name */
585    for (p=name; *p; p++) {
586       if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) {
587          continue;
588       }
589       if (ua) {
590          bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p);
591       }
592       return 0;
593    }
594    len = strlen(name);
595    if (len >= MAX_NAME_LENGTH) {
596       if (ua) {
597          bsendmsg(ua, _("Volume name too long.\n"));
598       }
599       return 0;
600    }
601    if (len == 0) {
602       if (ua) {
603          bsendmsg(ua, _("Volume name must be at least one character long.\n"));
604       }
605       return 0;
606    }
607    return 1;
608 }
609
610 /*
611  * NOTE! This routine opens the SD socket but leaves it open
612  */
613 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
614                                POOL_DBR *pr, int relabel, bool media_record_exists,
615                                int drive)
616 {
617    BSOCK *sd;
618    char dev_name[MAX_NAME_LENGTH];
619    bool ok = false;
620
621    if (!(sd=open_sd_bsock(ua))) {
622       return false;
623    }
624    bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name));
625    bash_spaces(dev_name);
626    bash_spaces(mr->VolumeName);
627    bash_spaces(mr->MediaType);
628    bash_spaces(pr->Name);
629    if (relabel) {
630       bash_spaces(omr->VolumeName);
631       bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s "
632                      "MediaType=%s Slot=%d drive=%d",
633                  dev_name, omr->VolumeName, mr->VolumeName, pr->Name, 
634                  mr->MediaType, mr->Slot, drive);
635       bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
636          omr->VolumeName, mr->VolumeName);
637    } else {
638       bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s "
639                      "Slot=%d drive=%d",
640                  dev_name, mr->VolumeName, pr->Name, mr->MediaType, 
641                  mr->Slot, drive);
642       bsendmsg(ua, _("Sending label command for Volume \"%s\" Slot %d ...\n"),
643          mr->VolumeName, mr->Slot);
644       Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n",
645          dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive);
646    }
647
648    while (bnet_recv(sd) >= 0) {
649       bsendmsg(ua, "%s", sd->msg);
650       if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
651          ok = true;
652       }
653    }
654    unbash_spaces(mr->VolumeName);
655    unbash_spaces(mr->MediaType);
656    unbash_spaces(pr->Name);
657    mr->LabelDate = time(NULL);
658    mr->set_label_date = true;
659    if (ok) {
660       if (media_record_exists) {      /* we update it */
661          mr->VolBytes = 1;
662          mr->InChanger = 1;
663          mr->StorageId = ua->jcr->store->StorageId;
664          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
665              bsendmsg(ua, "%s", db_strerror(ua->db));
666              ok = false;
667          }
668       } else {                        /* create the media record */
669          set_pool_dbr_defaults_in_media_dbr(mr, pr);
670          mr->VolBytes = 1;               /* flag indicating Volume labeled */
671          mr->InChanger = 1;
672          mr->StorageId = ua->jcr->store->StorageId;
673          if (db_create_media_record(ua->jcr, ua->db, mr)) {
674             bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
675             mr->VolumeName, mr->Slot);
676             /* Update number of volumes in pool */
677             pr->NumVols++;
678             if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
679                bsendmsg(ua, "%s", db_strerror(ua->db));
680             }
681          } else {
682             bsendmsg(ua, "%s", db_strerror(ua->db));
683             ok = false;
684          }
685       }
686    } else {
687       bsendmsg(ua, _("Label command failed for Volume %s.\n"), mr->VolumeName);
688    }
689    return ok;
690 }
691
692 static BSOCK *open_sd_bsock(UAContext *ua)
693 {
694    STORE *store = ua->jcr->store;
695
696    if (!ua->jcr->store_bsock) {
697       bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
698          store->hdr.name, store->address, store->SDport);
699       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
700          bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
701          return NULL;
702       }
703    }
704    return ua->jcr->store_bsock;
705 }
706
707 static void close_sd_bsock(UAContext *ua)
708 {
709    if (ua->jcr->store_bsock) {
710       bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
711       bnet_close(ua->jcr->store_bsock);
712       ua->jcr->store_bsock = NULL;
713    }
714 }
715
716 static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive)
717 {
718    STORE *store = ua->jcr->store;
719    BSOCK *sd;
720    char dev_name[MAX_NAME_LENGTH];
721    char *VolName = NULL;
722    int rtn_slot;
723
724    if (!(sd=open_sd_bsock(ua))) {
725       bsendmsg(ua, _("Could not open SD socket.\n"));
726       return NULL;
727    }
728    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
729    bash_spaces(dev_name);
730    /* Ask for autochanger list of volumes */
731    bnet_fsend(sd, _("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive);
732    Dmsg1(100, "Sent: %s", sd->msg);
733
734    /* Get Volume name in this Slot */
735    while (bnet_recv(sd) >= 0) {
736       bsendmsg(ua, "%s", sd->msg);
737       Dmsg1(100, "Got: %s", sd->msg);
738       if (strncmp(sd->msg, "3001 Volume=", 12) == 0) {
739          VolName = (char *)malloc(sd->msglen);
740          if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) {
741             break;
742          }
743          free(VolName);
744          VolName = NULL;
745       }
746    }
747    close_sd_bsock(ua);
748    Dmsg1(100, "get_vol_name=%s\n", NPRT(VolName));
749    return VolName;
750 }
751
752 /*
753  * We get the slot list from the Storage daemon.
754  *  If scan is set, we return all slots found,
755  *  otherwise, we return only slots with valid barcodes (Volume names)
756  */
757 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
758 {
759    STORE *store = ua->jcr->store;
760    char dev_name[MAX_NAME_LENGTH];
761    BSOCK *sd;
762    vol_list_t *vl;
763    vol_list_t *vol_list = NULL;
764
765
766    if (!(sd=open_sd_bsock(ua))) {
767       return NULL;
768    }
769
770    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
771    bash_spaces(dev_name);
772    /* Ask for autochanger list of volumes */
773    bnet_fsend(sd, _("autochanger list %s \n"), dev_name);
774
775    /* Read and organize list of Volumes */
776    while (bnet_recv(sd) >= 0) {
777       char *p;
778       int Slot;
779       strip_trailing_junk(sd->msg);
780
781       /* Check for returned SD messages */
782       if (sd->msg[0] == '3'     && B_ISDIGIT(sd->msg[1]) &&
783           B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
784           sd->msg[4] == ' ') {
785          bsendmsg(ua, "%s\n", sd->msg);   /* pass them on to user */
786          continue;
787       }
788
789       /* Validate Slot: if scanning, otherwise  Slot:Barcode */
790       p = strchr(sd->msg, ':');
791       if (scan && p) {
792          /* Scanning -- require only valid slot */
793          Slot = atoi(sd->msg);
794          if (Slot <= 0) {
795             p--;
796             *p = ':';
797             bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
798             continue;
799          }
800       } else {
801          /* Not scanning */
802          if (p && strlen(p) > 1) {
803             *p++ = 0;
804             if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
805                p--;
806                *p = ':';
807                bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
808                continue;
809             }
810          } else {
811             continue;
812          }
813          if (!is_volume_name_legal(ua, p)) {
814             p--;
815             *p = ':';
816             bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
817             continue;
818          }
819       }
820
821       /* Add Slot and VolumeName to list */
822       vl = (vol_list_t *)malloc(sizeof(vol_list_t));
823       vl->Slot = Slot;
824       if (p) {
825          if (*p == ':') {
826             p++;                      /* skip separator */
827          }
828          vl->VolName = bstrdup(p);
829       } else {
830          vl->VolName = NULL;
831       }
832       Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
833       if (!vol_list) {
834          vl->next = vol_list;
835          vol_list = vl;
836       } else {
837          /* Add new entry to end of list */
838          for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
839             if (!tvl->next) {
840                tvl->next = vl;
841                vl->next = NULL;
842                break;
843             }
844          }
845       }
846    }
847    close_sd_bsock(ua);
848    return vol_list;
849 }
850
851 static void free_vol_list(vol_list_t *vol_list)
852 {
853    vol_list_t *vl;
854
855    /* Free list */
856    for (vl=vol_list; vl; ) {
857       vol_list_t *ovl;
858       if (vl->VolName) {
859          free(vl->VolName);
860       }
861       ovl = vl;
862       vl = vl->next;
863       free(ovl);
864    }
865 }
866
867 /*
868  * We get the number of slots in the changer from the SD
869  */
870 static int get_num_slots_from_SD(UAContext *ua)
871 {
872    STORE *store = ua->jcr->store;
873    char dev_name[MAX_NAME_LENGTH];
874    BSOCK *sd;
875    int slots = 0;
876
877
878    if (!(sd=open_sd_bsock(ua))) {
879       return 0;
880    }
881
882    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
883    bash_spaces(dev_name);
884    /* Ask for autochanger number of slots */
885    bnet_fsend(sd, _("autochanger slots %s\n"), dev_name);
886
887    while (bnet_recv(sd) >= 0) {
888       if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
889          break;
890       } else {
891          bsendmsg(ua, "%s", sd->msg);
892       }
893    }
894    close_sd_bsock(ua);
895    bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
896    return slots;
897 }
898
899 /*
900  * We get the number of drives in the changer from the SD
901  */
902 int get_num_drives_from_SD(UAContext *ua)
903 {
904    STORE *store = ua->jcr->store;
905    char dev_name[MAX_NAME_LENGTH];
906    BSOCK *sd;
907    int drives = 0;
908
909
910    if (!(sd=open_sd_bsock(ua))) {
911       return 0;
912    }
913
914    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
915    bash_spaces(dev_name);
916    /* Ask for autochanger number of slots */
917    bnet_fsend(sd, _("autochanger drives %s\n"), dev_name);
918
919    while (bnet_recv(sd) >= 0) {
920       if (sscanf(sd->msg, "drives=%d\n", &drives) == 1) {
921          break;
922       } else {
923          bsendmsg(ua, "%s", sd->msg);
924       }
925    }
926    close_sd_bsock(ua);
927 //   bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives);
928    return drives;
929 }
930
931
932
933
934 /*
935  * Check if this is a cleaning tape by comparing the Volume name
936  *  with the Cleaning Prefix. If they match, this is a cleaning
937  *  tape.
938  */
939 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
940 {
941    /* Find Pool resource */
942    ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
943    if (!ua->jcr->pool) {
944       bsendmsg(ua, _("Pool \"%s\" resource not found!\n"), pr->Name);
945       return true;
946    }
947    if (ua->jcr->pool->cleaning_prefix == NULL) {
948       return false;
949    }
950    Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
951       ua->jcr->pool->cleaning_prefix, mr->VolumeName,
952       strlen(ua->jcr->pool->cleaning_prefix),
953       strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
954                   strlen(ua->jcr->pool->cleaning_prefix)));
955    return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
956                   strlen(ua->jcr->pool->cleaning_prefix)) == 0;
957 }