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