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