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