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