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