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