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