]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_label.c
- Tweak license to include Microsoft restrictions.
[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-2006 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 void 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;
163    }
164    store = get_storage_resource(ua, true/*arg is storage*/);
165    if (!store) {
166       return;
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    Dmsg1(100, "max_slots=%d\n", max_slots);
175    if (max_slots <= 0) {
176       bsendmsg(ua, _("No slots in changer to scan.\n"));
177       return;
178    }
179    slot_list = (char *)malloc(max_slots+1);
180    if (!get_user_slot_list(ua, slot_list, max_slots)) {
181       free(slot_list);
182       return;
183    }
184
185    vol_list = get_vol_list_from_SD(ua, scan);
186
187    if (!vol_list) {
188       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
189       goto bail_out;
190    }
191
192    /* First zap out any InChanger with StorageId=0 */
193    db_sql_query(ua->db, "UPDATE Media SET InChanger=0 WHERE StorageId=0", NULL, NULL);
194
195    /* Walk through the list updating the media records */
196    for (vl=vol_list; vl; vl=vl->next) {
197       if (vl->Slot > max_slots) {
198          bsendmsg(ua, _("Slot %d greater than max %d ignored.\n"),
199             vl->Slot, max_slots);
200          continue;
201       }
202       /* Check if user wants us to look at this slot */
203       if (!slot_list[vl->Slot]) {
204          Dmsg1(100, "Skipping slot=%d\n", vl->Slot);
205          continue;
206       }
207       /* If scanning, we read the label rather than the barcode */
208       if (scan) {
209          if (vl->VolName) {
210             free(vl->VolName);
211             vl->VolName = NULL;
212          }
213          vl->VolName = get_volume_name_from_SD(ua, vl->Slot, drive);
214          Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot);
215       }
216       slot_list[vl->Slot] = 0;        /* clear Slot */
217       memset(&mr, 0, sizeof(mr));
218       mr.Slot = vl->Slot;
219       mr.InChanger = 1;
220       mr.StorageId = store->StorageId;
221       /* Set InChanger to zero for this Slot */
222       db_lock(ua->db);
223       db_make_inchanger_unique(ua->jcr, ua->db, &mr);
224       db_unlock(ua->db);
225       if (!vl->VolName) {
226          Dmsg1(000, "No VolName for Slot=%d setting InChanger to zero.\n", vl->Slot);
227          bsendmsg(ua, _("No VolName for Slot=%d InChanger set to zero.\n"), vl->Slot);
228          continue;
229       }
230       memset(&mr, 0, sizeof(mr));
231       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
232       db_lock(ua->db);
233       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
234          if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) {
235             mr.Slot = vl->Slot;
236             mr.InChanger = 1;
237             mr.StorageId = store->StorageId;
238             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
239                bsendmsg(ua, "%s", db_strerror(ua->db));
240             } else {
241                bsendmsg(ua, _(
242                  "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
243                  mr.VolumeName, mr.Slot);
244             }
245          } else {
246             bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
247                mr.VolumeName);
248          }
249          db_unlock(ua->db);
250          continue;
251       } else {
252          bsendmsg(ua, _("Volume \"%s\" not found in catalog. Slot=%d InChanger set to zero.\n"),
253              mr.VolumeName, vl->Slot);
254       }
255       db_unlock(ua->db);
256    }
257    memset(&mr, 0, sizeof(mr));
258    mr.InChanger = 1;
259    mr.StorageId = store->StorageId;
260    db_lock(ua->db);
261    for (int i=1; i <= max_slots; i++) {
262       if (slot_list[i]) {
263          mr.Slot = i;
264          /* Set InChanger to zero for this Slot */
265          db_make_inchanger_unique(ua->jcr, ua->db, &mr);
266       }
267    }
268    db_unlock(ua->db);
269
270 bail_out:
271
272    free_vol_list(vol_list);
273    free(slot_list);
274    close_sd_bsock(ua);
275
276    return;
277 }
278
279
280 /*
281  * Common routine for both label and relabel
282  */
283 static int do_label(UAContext *ua, const char *cmd, int relabel)
284 {
285    STORE *store;
286    BSOCK *sd;
287    char dev_name[MAX_NAME_LENGTH];
288    MEDIA_DBR mr, omr;
289    POOL_DBR pr;
290    bool print_reminder = true;
291    bool label_barcodes = false;
292    int ok = FALSE;
293    int i;
294    int drive;
295    bool media_record_exists = false;
296    static const char *barcode_keyword[] = {
297       "barcode",
298       "barcodes",
299       NULL};
300
301
302    memset(&pr, 0, sizeof(pr));
303    if (!open_db(ua)) {
304       return 1;
305    }
306
307    if (!relabel && (i=find_arg_keyword(ua, barcode_keyword)) >= 0) {
308       *ua->argk[i] = 0;      /* zap barcode keyword */
309       label_barcodes = true;
310    }
311
312    store = get_storage_resource(ua, true/*use default*/);
313    if (!store) {
314       return 1;
315    }
316    set_storage(ua->jcr, store);
317    drive = get_storage_drive(ua, store);
318
319    if (label_barcodes) {
320       label_from_barcodes(ua, drive);
321       return 1;
322    }
323
324    /* If relabel get name of Volume to relabel */
325    if (relabel) {
326       /* Check for oldvolume=name */
327       i = find_arg_with_value(ua, "oldvolume");
328       if (i >= 0) {
329          memset(&omr, 0, sizeof(omr));
330          bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
331          if (db_get_media_record(ua->jcr, ua->db, &omr)) {
332             goto checkVol;
333          }
334          bsendmsg(ua, "%s", db_strerror(ua->db));
335       }
336       /* No keyword or Vol not found, ask user to select */
337       if (!select_media_dbr(ua, &omr)) {
338          return 1;
339       }
340
341       /* Require Volume to be Purged or Recycled */
342 checkVol:
343       if (strcmp(omr.VolStatus, "Purged") != 0 && strcmp(omr.VolStatus, "Recycle") != 0) {
344          bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"),
345             omr.VolumeName, omr.VolStatus);
346          return 1;
347       }
348    }
349
350    /* Check for volume=NewVolume */
351    i = find_arg_with_value(ua, "volume");
352    if (i >= 0) {
353       pm_strcpy(ua->cmd, ua->argv[i]);
354       goto checkName;
355    }
356
357    /* Get a new Volume name */
358    for ( ;; ) {
359       media_record_exists = false;
360       if (!get_cmd(ua, _("Enter new Volume name: "))) {
361          return 1;
362       }
363 checkName:
364       if (!is_volume_name_legal(ua, ua->cmd)) {
365          continue;
366       }
367
368       memset(&mr, 0, sizeof(mr));
369       bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));
370       /* If VolBytes are zero the Volume is not labeled */
371       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
372          if (mr.VolBytes != 0) {
373              bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
374                 mr.VolumeName);
375              continue;
376           }
377           media_record_exists = true;
378       }
379       break;                          /* Got it */
380    }
381
382    /* If autochanger, request slot */
383    i = find_arg_with_value(ua, "slot");
384    if (i >= 0) {
385       mr.Slot = atoi(ua->argv[i]);
386       mr.InChanger = 1;               /* assumed if we are labeling it */
387    } else if (store->autochanger) {
388       if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
389          return 1;
390       }
391       mr.Slot = ua->pint32_val;
392       mr.InChanger = 1;               /* assumed if we are labeling it */
393    }
394    mr.StorageId = store->StorageId;
395
396    bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
397
398    /* Must select Pool if not already done */
399    if (pr.PoolId == 0) {
400       memset(&pr, 0, sizeof(pr));
401       if (!select_pool_dbr(ua, &pr)) {
402          return 1;
403       }
404    }
405
406    ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists, drive);
407
408    if (ok) {
409       sd = ua->jcr->store_bsock;
410       if (relabel) {
411          /* Delete the old media record */
412          if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
413             bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"),
414                omr.VolumeName, db_strerror(ua->db));
415          } else {
416             bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
417                omr.VolumeName);
418             /* Update the number of Volumes in the pool */
419             pr.NumVols--;
420             if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
421                bsendmsg(ua, "%s", db_strerror(ua->db));
422             }
423          }
424       }
425       if (ua->automount) {
426          bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
427          bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name);
428          bash_spaces(dev_name);
429          bnet_fsend(sd, "mount %s drive=%d", dev_name, drive);
430          unbash_spaces(dev_name);
431          while (bnet_recv(sd) >= 0) {
432             bsendmsg(ua, "%s", sd->msg);
433             /* Here we can get
434              *  3001 OK mount. Device=xxx      or
435              *  3001 Mounted Volume vvvv
436              *  3002 Device "DVD-Writer" (/dev/hdc) is mounted.
437              *  3906 is cannot mount non-tape
438              * So for those, no need to print a reminder
439              */
440             if (strncmp(sd->msg, "3001 ", 5) == 0 ||
441                 strncmp(sd->msg, "3002 ", 5) == 0 ||
442                 strncmp(sd->msg, "3906 ", 5) == 0) {
443                print_reminder = false;
444             }
445          }
446       }
447    }
448    if (print_reminder) {
449       bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
450    }
451    close_sd_bsock(ua);
452
453    return 1;
454 }
455
456 /*
457  * Request SD to send us the slot:barcodes, then wiffle
458  *  through them all labeling them.
459  */
460 static void label_from_barcodes(UAContext *ua, int drive)
461 {
462    STORE *store = ua->jcr->store;
463    POOL_DBR pr;
464    MEDIA_DBR mr, omr;
465    vol_list_t *vl, *vol_list = NULL;
466    bool media_record_exists;
467    char *slot_list;
468    int max_slots;
469
470   
471    max_slots = get_num_slots_from_SD(ua);
472    if (max_slots <= 0) {
473       bsendmsg(ua, _("No slots in changer to scan.\n"));
474       return;
475    }
476    slot_list = (char *)malloc(max_slots+1);
477    if (!get_user_slot_list(ua, slot_list, max_slots)) {
478       goto bail_out;
479    }
480
481    vol_list = get_vol_list_from_SD(ua, false /*no scan*/);
482
483    if (!vol_list) {
484       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
485       goto bail_out;
486    }
487
488    /* Display list of Volumes and ask if he really wants to proceed */
489    bsendmsg(ua, _("The following Volumes will be labeled:\n"
490                   "Slot  Volume\n"
491                   "==============\n"));
492    for (vl=vol_list; vl; vl=vl->next) {
493       if (!vl->VolName || !slot_list[vl->Slot]) {
494          continue;
495       }
496       bsendmsg(ua, "%4d  %s\n", vl->Slot, vl->VolName);
497    }
498    if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
499        (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
500       goto bail_out;
501    }
502    /* Select a pool */
503    memset(&pr, 0, sizeof(pr));
504    if (!select_pool_dbr(ua, &pr)) {
505       goto bail_out;
506    }
507    memset(&omr, 0, sizeof(omr));
508
509    /* Fire off the label requests */
510    for (vl=vol_list; vl; vl=vl->next) {
511       if (!vl->VolName || !slot_list[vl->Slot]) {
512          continue;
513       }
514       memset(&mr, 0, sizeof(mr));
515       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
516       media_record_exists = false;
517       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
518           if (mr.VolBytes != 0) {
519              bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"),
520                 vl->Slot, mr.VolumeName);
521              mr.Slot = vl->Slot;
522              mr.InChanger = 1;
523              mr.StorageId = store->StorageId;
524              if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
525                 bsendmsg(ua, _("Error setting InChanger: ERR=%s"), db_strerror(ua->db));
526              }
527              continue;
528           }
529           media_record_exists = true;
530       }
531       mr.InChanger = 1;
532       mr.StorageId = store->StorageId;
533       /*
534        * Deal with creating cleaning tape here. Normal tapes created in
535        *  send_label_request() below
536        */
537       if (is_cleaning_tape(ua, &mr, &pr)) {
538          if (media_record_exists) {      /* we update it */
539             mr.VolBytes = 1;
540             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
541             mr.MediaType[0] = 0;
542             mr.StorageId = store->StorageId;
543             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
544                 bsendmsg(ua, "%s", db_strerror(ua->db));
545             }
546          } else {                        /* create the media record */
547             if (pr.MaxVols > 0 && pr.NumVols >= pr.MaxVols) {
548                bsendmsg(ua, _("Maximum pool Volumes=%d reached.\n"), pr.MaxVols);
549                goto bail_out;
550             }
551             set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
552             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
553             mr.MediaType[0] = 0;
554             if (db_create_media_record(ua->jcr, ua->db, &mr)) {
555                bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
556                   mr.VolumeName);
557                pr.NumVols++;          /* this is a bit suspect */
558                if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
559                   bsendmsg(ua, "%s", db_strerror(ua->db));
560                }
561             } else {
562                bsendmsg(ua, _("Catalog error on cleaning tape: %s"), db_strerror(ua->db));
563             }
564          }
565          continue;                    /* done, go handle next volume */
566       }
567       bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
568
569       mr.Slot = vl->Slot;
570       send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists, drive);
571    }
572
573
574 bail_out:
575    free(slot_list);
576    free_vol_list(vol_list);
577    close_sd_bsock(ua);
578
579    return;
580 }
581
582 /*
583  * Check if the Volume name has legal characters
584  * If ua is non-NULL send the message
585  */
586 bool is_volume_name_legal(UAContext *ua, const char *name)
587 {
588    int len;
589    const char *p;
590    const char *accept = ":.-_";
591
592    /* Restrict the characters permitted in the Volume name */
593    for (p=name; *p; p++) {
594       if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) {
595          continue;
596       }
597       if (ua) {
598          bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p);
599       }
600       return 0;
601    }
602    len = strlen(name);
603    if (len >= MAX_NAME_LENGTH) {
604       if (ua) {
605          bsendmsg(ua, _("Volume name too long.\n"));
606       }
607       return 0;
608    }
609    if (len == 0) {
610       if (ua) {
611          bsendmsg(ua, _("Volume name must be at least one character long.\n"));
612       }
613       return 0;
614    }
615    return 1;
616 }
617
618 /*
619  * NOTE! This routine opens the SD socket but leaves it open
620  */
621 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
622                                POOL_DBR *pr, int relabel, bool media_record_exists,
623                                int drive)
624 {
625    BSOCK *sd;
626    char dev_name[MAX_NAME_LENGTH];
627    bool ok = false;
628
629    if (!(sd=open_sd_bsock(ua))) {
630       return false;
631    }
632    bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name));
633    bash_spaces(dev_name);
634    bash_spaces(mr->VolumeName);
635    bash_spaces(mr->MediaType);
636    bash_spaces(pr->Name);
637    if (relabel) {
638       bash_spaces(omr->VolumeName);
639       bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s "
640                      "MediaType=%s Slot=%d drive=%d",
641                  dev_name, omr->VolumeName, mr->VolumeName, pr->Name, 
642                  mr->MediaType, mr->Slot, drive);
643       bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
644          omr->VolumeName, mr->VolumeName);
645    } else {
646       bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s "
647                      "Slot=%d drive=%d",
648                  dev_name, mr->VolumeName, pr->Name, mr->MediaType, 
649                  mr->Slot, drive);
650       bsendmsg(ua, _("Sending label command for Volume \"%s\" Slot %d ...\n"),
651          mr->VolumeName, mr->Slot);
652       Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n",
653          dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive);
654    }
655
656    while (bnet_recv(sd) >= 0) {
657       bsendmsg(ua, "%s", sd->msg);
658       if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
659          ok = true;
660       }
661    }
662    unbash_spaces(mr->VolumeName);
663    unbash_spaces(mr->MediaType);
664    unbash_spaces(pr->Name);
665    mr->LabelDate = time(NULL);
666    mr->set_label_date = true;
667    if (ok) {
668       if (media_record_exists) {      /* we update it */
669          mr->VolBytes = 1;
670          mr->InChanger = 1;
671          mr->StorageId = ua->jcr->store->StorageId;
672          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
673              bsendmsg(ua, "%s", db_strerror(ua->db));
674              ok = false;
675          }
676       } else {                        /* create the media record */
677          set_pool_dbr_defaults_in_media_dbr(mr, pr);
678          mr->VolBytes = 1;               /* flag indicating Volume labeled */
679          mr->InChanger = 1;
680          mr->StorageId = ua->jcr->store->StorageId;
681          if (db_create_media_record(ua->jcr, ua->db, mr)) {
682             bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
683             mr->VolumeName, mr->Slot);
684             /* Update number of volumes in pool */
685             pr->NumVols++;
686             if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
687                bsendmsg(ua, "%s", db_strerror(ua->db));
688             }
689          } else {
690             bsendmsg(ua, "%s", db_strerror(ua->db));
691             ok = false;
692          }
693       }
694    } else {
695       bsendmsg(ua, _("Label command failed for Volume %s.\n"), mr->VolumeName);
696    }
697    return ok;
698 }
699
700 static BSOCK *open_sd_bsock(UAContext *ua)
701 {
702    STORE *store = ua->jcr->store;
703
704    if (!ua->jcr->store_bsock) {
705       bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
706          store->hdr.name, store->address, store->SDport);
707       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
708          bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
709          return NULL;
710       }
711    }
712    return ua->jcr->store_bsock;
713 }
714
715 static void close_sd_bsock(UAContext *ua)
716 {
717    if (ua->jcr->store_bsock) {
718       bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
719       bnet_close(ua->jcr->store_bsock);
720       ua->jcr->store_bsock = NULL;
721    }
722 }
723
724 static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive)
725 {
726    STORE *store = ua->jcr->store;
727    BSOCK *sd;
728    char dev_name[MAX_NAME_LENGTH];
729    char *VolName = NULL;
730    int rtn_slot;
731
732    if (!(sd=open_sd_bsock(ua))) {
733       bsendmsg(ua, _("Could not open SD socket.\n"));
734       return NULL;
735    }
736    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
737    bash_spaces(dev_name);
738    /* Ask for autochanger list of volumes */
739    bnet_fsend(sd, NT_("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive);
740    Dmsg1(100, "Sent: %s", sd->msg);
741
742    /* Get Volume name in this Slot */
743    while (bnet_recv(sd) >= 0) {
744       bsendmsg(ua, "%s", sd->msg);
745       Dmsg1(100, "Got: %s", sd->msg);
746       if (strncmp(sd->msg, NT_("3001 Volume="), 12) == 0) {
747          VolName = (char *)malloc(sd->msglen);
748          if (sscanf(sd->msg, NT_("3001 Volume=%s Slot=%d"), VolName, &rtn_slot) == 2) {
749             break;
750          }
751          free(VolName);
752          VolName = NULL;
753       }
754    }
755    close_sd_bsock(ua);
756    Dmsg1(100, "get_vol_name=%s\n", NPRT(VolName));
757    return VolName;
758 }
759
760 /*
761  * We get the slot list from the Storage daemon.
762  *  If scan is set, we return all slots found,
763  *  otherwise, we return only slots with valid barcodes (Volume names)
764  */
765 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
766 {
767    STORE *store = ua->jcr->store;
768    char dev_name[MAX_NAME_LENGTH];
769    BSOCK *sd;
770    vol_list_t *vl;
771    vol_list_t *vol_list = NULL;
772
773
774    if (!(sd=open_sd_bsock(ua))) {
775       return NULL;
776    }
777
778    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
779    bash_spaces(dev_name);
780    /* Ask for autochanger list of volumes */
781    bnet_fsend(sd, NT_("autochanger list %s \n"), dev_name);
782
783    /* Read and organize list of Volumes */
784    while (bnet_recv(sd) >= 0) {
785       char *p;
786       int Slot;
787       strip_trailing_junk(sd->msg);
788
789       /* Check for returned SD messages */
790       if (sd->msg[0] == '3'     && B_ISDIGIT(sd->msg[1]) &&
791           B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
792           sd->msg[4] == ' ') {
793          bsendmsg(ua, "%s\n", sd->msg);   /* pass them on to user */
794          continue;
795       }
796
797       /* Validate Slot: if scanning, otherwise  Slot:Barcode */
798       p = strchr(sd->msg, ':');
799       if (scan && p) {
800          /* Scanning -- require only valid slot */
801          Slot = atoi(sd->msg);
802          if (Slot <= 0) {
803             p--;
804             *p = ':';
805             bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
806             continue;
807          }
808       } else {
809          /* Not scanning */
810          if (p && strlen(p) > 1) {
811             *p++ = 0;
812             if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
813                p--;
814                *p = ':';
815                bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
816                continue;
817             }
818          } else {
819             continue;
820          }
821          if (!is_volume_name_legal(ua, p)) {
822             p--;
823             *p = ':';
824             bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
825             continue;
826          }
827       }
828
829       /* Add Slot and VolumeName to list */
830       vl = (vol_list_t *)malloc(sizeof(vol_list_t));
831       vl->Slot = Slot;
832       if (p) {
833          if (*p == ':') {
834             p++;                      /* skip separator */
835          }
836          vl->VolName = bstrdup(p);
837       } else {
838          vl->VolName = NULL;
839       }
840       Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
841       if (!vol_list) {
842          vl->next = vol_list;
843          vol_list = vl;
844       } else {
845          /* Add new entry to end of list */
846          for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
847             if (!tvl->next) {
848                tvl->next = vl;
849                vl->next = NULL;
850                break;
851             }
852          }
853       }
854    }
855    close_sd_bsock(ua);
856    return vol_list;
857 }
858
859 static void free_vol_list(vol_list_t *vol_list)
860 {
861    vol_list_t *vl;
862
863    /* Free list */
864    for (vl=vol_list; vl; ) {
865       vol_list_t *ovl;
866       if (vl->VolName) {
867          free(vl->VolName);
868       }
869       ovl = vl;
870       vl = vl->next;
871       free(ovl);
872    }
873 }
874
875 /*
876  * We get the number of slots in the changer from the SD
877  */
878 static int get_num_slots_from_SD(UAContext *ua)
879 {
880    STORE *store = ua->jcr->store;
881    char dev_name[MAX_NAME_LENGTH];
882    BSOCK *sd;
883    int slots = 0;
884
885
886    if (!(sd=open_sd_bsock(ua))) {
887       return 0;
888    }
889
890    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
891    bash_spaces(dev_name);
892    /* Ask for autochanger number of slots */
893    bnet_fsend(sd, NT_("autochanger slots %s\n"), dev_name);
894
895    while (bnet_recv(sd) >= 0) {
896       if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
897          break;
898       } else {
899          bsendmsg(ua, "%s", sd->msg);
900       }
901    }
902    close_sd_bsock(ua);
903    bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
904    return slots;
905 }
906
907 /*
908  * We get the number of drives in the changer from the SD
909  */
910 int get_num_drives_from_SD(UAContext *ua)
911 {
912    STORE *store = ua->jcr->store;
913    char dev_name[MAX_NAME_LENGTH];
914    BSOCK *sd;
915    int drives = 0;
916
917
918    if (!(sd=open_sd_bsock(ua))) {
919       return 0;
920    }
921
922    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
923    bash_spaces(dev_name);
924    /* Ask for autochanger number of slots */
925    bnet_fsend(sd, NT_("autochanger drives %s\n"), dev_name);
926
927    while (bnet_recv(sd) >= 0) {
928       if (sscanf(sd->msg, NT_("drives=%d\n"), &drives) == 1) {
929          break;
930       } else {
931          bsendmsg(ua, "%s", sd->msg);
932       }
933    }
934    close_sd_bsock(ua);
935 //   bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives);
936    return drives;
937 }
938
939
940
941
942 /*
943  * Check if this is a cleaning tape by comparing the Volume name
944  *  with the Cleaning Prefix. If they match, this is a cleaning
945  *  tape.
946  */
947 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
948 {
949    /* Find Pool resource */
950    ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
951    if (!ua->jcr->pool) {
952       bsendmsg(ua, _("Pool \"%s\" resource not found!\n"), pr->Name);
953       return true;
954    }
955    if (ua->jcr->pool->cleaning_prefix == NULL) {
956       return false;
957    }
958    Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
959       ua->jcr->pool->cleaning_prefix, mr->VolumeName,
960       strlen(ua->jcr->pool->cleaning_prefix),
961       strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
962                   strlen(ua->jcr->pool->cleaning_prefix)));
963    return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
964                   strlen(ua->jcr->pool->cleaning_prefix)) == 0;
965 }