]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_label.c
- Start removing #ifdef HAVE_TLS by sneaky tricks.
[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 ammended 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);
38 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
39                POOL_DBR *pr, int relabel, bool media_record_exits);
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);
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 #ifdef xxx_debug
135    printf("Slots turned on:\n");
136    for (i=1; i <= num_slots; i++) {
137       if (slot_list[i]) {
138          printf("%d\n", i);
139       }
140    }
141 #endif
142    return true;
143
144 bail_out:
145    return false;
146 }
147
148 /*
149  * Update Slots corresponding to Volumes in autochanger
150  */
151 int update_slots(UAContext *ua)
152 {
153    STORE *store;
154    vol_list_t *vl, *vol_list = NULL;
155    MEDIA_DBR mr;
156    char *slot_list;
157    bool scan;
158    int max_slots;
159
160
161    if (!open_db(ua)) {
162       return 1;
163    }
164    store = get_storage_resource(ua, 1);
165    if (!store) {
166       return 1;
167    }
168    set_storage(ua->jcr, store);
169
170    scan = find_arg(ua, _("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);
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    int ok = FALSE;
287    int i;
288    bool media_record_exists = false;
289    static const char *barcode_keyword[] = {
290       "barcode",
291       "barcodes",
292       NULL};
293
294
295    memset(&pr, 0, sizeof(pr));
296    if (!open_db(ua)) {
297       return 1;
298    }
299    store = get_storage_resource(ua, 1);
300    if (!store) {
301       return 1;
302    }
303    set_storage(ua->jcr, store);
304
305    if (!relabel && find_arg_keyword(ua, barcode_keyword) >= 0) {
306       label_from_barcodes(ua);
307       return 1;
308    }
309
310    /* If relabel get name of Volume to relabel */
311    if (relabel) {
312       /* Check for oldvolume=name */
313       i = find_arg_with_value(ua, "oldvolume");
314       if (i >= 0) {
315          memset(&omr, 0, sizeof(omr));
316          bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
317          if (db_get_media_record(ua->jcr, ua->db, &omr)) {
318             goto checkVol;
319          }
320          bsendmsg(ua, "%s", db_strerror(ua->db));
321       }
322       /* No keyword or Vol not found, ask user to select */
323       if (!select_media_dbr(ua, &omr)) {
324          return 1;
325       }
326
327       /* Require Volume to be Purged or Recycled */
328 checkVol:
329       if (strcmp(omr.VolStatus, "Purged") != 0 && strcmp(omr.VolStatus, "Recycle") != 0) {
330          bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"),
331             omr.VolumeName, omr.VolStatus);
332          return 1;
333       }
334    }
335
336    /* Check for volume=NewVolume */
337    i = find_arg_with_value(ua, "volume");
338    if (i >= 0) {
339       pm_strcpy(ua->cmd, ua->argv[i]);
340       goto checkName;
341    }
342
343    /* Get a new Volume name */
344    for ( ;; ) {
345       media_record_exists = false;
346       if (!get_cmd(ua, _("Enter new Volume name: "))) {
347          return 1;
348       }
349 checkName:
350       if (!is_volume_name_legal(ua, ua->cmd)) {
351          continue;
352       }
353
354       memset(&mr, 0, sizeof(mr));
355       bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));
356       /* If VolBytes are zero the Volume is not labeled */
357       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
358          if (mr.VolBytes != 0) {
359              bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
360                 mr.VolumeName);
361              continue;
362           }
363           media_record_exists = true;
364       }
365       break;                          /* Got it */
366    }
367
368    /* If autochanger, request slot */
369    if (store->autochanger) {
370       i = find_arg_with_value(ua, "slot");
371       if (i >= 0) {
372          mr.Slot = atoi(ua->argv[i]);
373       } else if (!get_pint(ua, _("Enter slot (0 or Enter for none): "))) {
374          return 1;
375       } else {
376          mr.Slot = ua->pint32_val;
377       }
378       mr.InChanger = 1;               /* assumed if we are labeling it */
379    }
380    mr.StorageId = store->StorageId;
381
382    bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
383
384    /* Must select Pool if not already done */
385    if (pr.PoolId == 0) {
386       memset(&pr, 0, sizeof(pr));
387       if (!select_pool_dbr(ua, &pr)) {
388          return 1;
389       }
390    }
391
392    ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists);
393
394    if (ok) {
395       sd = ua->jcr->store_bsock;
396       if (relabel) {
397          /* Delete the old media record */
398          if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
399             bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"),
400                omr.VolumeName, db_strerror(ua->db));
401          } else {
402             bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
403                omr.VolumeName);
404             /* Update the number of Volumes in the pool */
405             pr.NumVols--;
406             if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
407                bsendmsg(ua, "%s", db_strerror(ua->db));
408             }
409          }
410       }
411       if (ua->automount) {
412          bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
413          bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name);
414          bash_spaces(dev_name);
415          bnet_fsend(sd, "mount %s", dev_name);
416          unbash_spaces(dev_name);
417          while (bnet_recv(sd) >= 0) {
418             bsendmsg(ua, "%s", sd->msg);
419             /* Here we can get
420              *  3001 OK mount. Device=xxx      or
421              *  3001 Mounted Volume vvvv
422              *  3906 is cannot mount non-tape
423              * So for those, no need to print a reminder
424              */
425             if (strncmp(sd->msg, "3001 ", 5) == 0 ||
426                 strncmp(sd->msg, "3906 ", 5) == 0) {
427                print_reminder = false;
428             }
429          }
430       }
431    }
432    if (print_reminder) {
433       bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
434    }
435    close_sd_bsock(ua);
436
437    return 1;
438 }
439
440 /*
441  * Request SD to send us the slot:barcodes, then wiffle
442  *  through them all labeling them.
443  */
444 static void label_from_barcodes(UAContext *ua)
445 {
446    STORE *store = ua->jcr->store;
447    POOL_DBR pr;
448    MEDIA_DBR mr, omr;
449    vol_list_t *vl, *vol_list = NULL;
450    bool media_record_exists;
451    char *slot_list;
452    int max_slots;
453
454   
455    max_slots = get_num_slots_from_SD(ua);
456    if (max_slots <= 0) {
457       bsendmsg(ua, _("No slots in changer to scan.\n"));
458       return;
459    }
460    slot_list = (char *)malloc(max_slots+1);
461    if (!get_user_slot_list(ua, slot_list, max_slots)) {
462       goto bail_out;
463    }
464
465    vol_list = get_vol_list_from_SD(ua, false /*no scan*/);
466
467    if (!vol_list) {
468       bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
469       goto bail_out;
470    }
471
472    /* Display list of Volumes and ask if he really wants to proceed */
473    bsendmsg(ua, _("The following Volumes will be labeled:\n"
474                   "Slot  Volume\n"
475                   "==============\n"));
476    for (vl=vol_list; vl; vl=vl->next) {
477       if (!vl->VolName || !slot_list[vl->Slot]) {
478          continue;
479       }
480       bsendmsg(ua, "%4d  %s\n", vl->Slot, vl->VolName);
481    }
482    if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
483        (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
484       goto bail_out;
485    }
486    /* Select a pool */
487    memset(&pr, 0, sizeof(pr));
488    if (!select_pool_dbr(ua, &pr)) {
489       goto bail_out;
490    }
491    memset(&omr, 0, sizeof(omr));
492
493    /* Fire off the label requests */
494    for (vl=vol_list; vl; vl=vl->next) {
495       if (!vl->VolName || !slot_list[vl->Slot]) {
496          continue;
497       }
498       memset(&mr, 0, sizeof(mr));
499       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
500       media_record_exists = false;
501       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
502           if (mr.VolBytes != 0) {
503              bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"),
504                 vl->Slot, mr.VolumeName);
505              mr.Slot = vl->Slot;
506              mr.InChanger = 1;
507              mr.StorageId = store->StorageId;
508              if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
509                 bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db));
510              }
511              continue;
512           }
513           media_record_exists = true;
514       }
515       mr.InChanger = 1;
516       mr.StorageId = store->StorageId;
517       /*
518        * Deal with creating cleaning tape here. Normal tapes created in
519        *  send_label_request() below
520        */
521       if (is_cleaning_tape(ua, &mr, &pr)) {
522          if (media_record_exists) {      /* we update it */
523             mr.VolBytes = 1;
524             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
525                 bsendmsg(ua, "%s", db_strerror(ua->db));
526             }
527          } else {                        /* create the media record */
528             set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
529             if (db_create_media_record(ua->jcr, ua->db, &mr)) {
530                bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
531                   mr.VolumeName);
532                pr.NumVols++;          /* this is a bit suspect */
533                if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
534                   bsendmsg(ua, "%s", db_strerror(ua->db));
535                }
536             } else {
537                bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db));
538             }
539          }
540          continue;                    /* done, go handle next volume */
541       }
542       bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
543
544       mr.Slot = vl->Slot;
545       send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists);
546    }
547
548
549 bail_out:
550    free(slot_list);
551    free_vol_list(vol_list);
552    close_sd_bsock(ua);
553
554    return;
555 }
556
557 /*
558  * Check if the Volume name has legal characters
559  * If ua is non-NULL send the message
560  */
561 bool is_volume_name_legal(UAContext *ua, const char *name)
562 {
563    int len;
564    const char *p;
565    const char *accept = ":.-_";
566
567    /* Restrict the characters permitted in the Volume name */
568    for (p=name; *p; p++) {
569       if (B_ISALPHA(*p) || B_ISDIGIT(*p) || strchr(accept, (int)(*p))) {
570          continue;
571       }
572       if (ua) {
573          bsendmsg(ua, _("Illegal character \"%c\" in a volume name.\n"), *p);
574       }
575       return 0;
576    }
577    len = strlen(name);
578    if (len >= MAX_NAME_LENGTH) {
579       if (ua) {
580          bsendmsg(ua, _("Volume name too long.\n"));
581       }
582       return 0;
583    }
584    if (len == 0) {
585       if (ua) {
586          bsendmsg(ua, _("Volume name must be at least one character long.\n"));
587       }
588       return 0;
589    }
590    return 1;
591 }
592
593 /*
594  * NOTE! This routine opens the SD socket but leaves it open
595  */
596 static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
597                                POOL_DBR *pr, int relabel, bool media_record_exists)
598 {
599    BSOCK *sd;
600    char dev_name[MAX_NAME_LENGTH];
601    bool ok = false;
602
603    if (!(sd=open_sd_bsock(ua))) {
604       return false;
605    }
606    bstrncpy(dev_name, ua->jcr->store->dev_name(), sizeof(dev_name));
607    bash_spaces(dev_name);
608    bash_spaces(mr->VolumeName);
609    bash_spaces(mr->MediaType);
610    bash_spaces(pr->Name);
611    if (relabel) {
612       bash_spaces(omr->VolumeName);
613       bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d",
614          dev_name, omr->VolumeName, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
615       bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
616          omr->VolumeName, mr->VolumeName);
617    } else {
618       bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d",
619          dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
620       bsendmsg(ua, _("Sending label command for Volume \"%s\" Slot %d ...\n"),
621          mr->VolumeName, mr->Slot);
622       Dmsg5(200, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d\n",
623          dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
624    }
625
626    while (bnet_recv(sd) >= 0) {
627       bsendmsg(ua, "%s", sd->msg);
628       if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
629          ok = true;
630       }
631    }
632    unbash_spaces(mr->VolumeName);
633    unbash_spaces(mr->MediaType);
634    unbash_spaces(pr->Name);
635    mr->LabelDate = time(NULL);
636    mr->set_label_date = true;
637    if (ok) {
638       if (media_record_exists) {      /* we update it */
639          mr->VolBytes = 1;
640          mr->InChanger = 1;
641          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
642              bsendmsg(ua, "%s", db_strerror(ua->db));
643              ok = false;
644          }
645       } else {                        /* create the media record */
646          set_pool_dbr_defaults_in_media_dbr(mr, pr);
647          mr->VolBytes = 1;               /* flag indicating Volume labeled */
648          mr->InChanger = 1;
649          if (db_create_media_record(ua->jcr, ua->db, mr)) {
650             bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
651             mr->VolumeName, mr->Slot);
652             /* Update number of volumes in pool */
653             pr->NumVols++;
654             if (!db_update_pool_record(ua->jcr, ua->db, pr)) {
655                bsendmsg(ua, "%s", db_strerror(ua->db));
656             }
657          } else {
658             bsendmsg(ua, "%s", db_strerror(ua->db));
659             ok = false;
660          }
661       }
662    } else {
663       bsendmsg(ua, _("Label command failed for Volume %s.\n"), mr->VolumeName);
664    }
665    return ok;
666 }
667
668 static BSOCK *open_sd_bsock(UAContext *ua)
669 {
670    STORE *store = ua->jcr->store;
671
672    if (!ua->jcr->store_bsock) {
673       bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
674          store->hdr.name, store->address, store->SDport);
675       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
676          bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
677          return NULL;
678       }
679    }
680    return ua->jcr->store_bsock;
681 }
682
683 static void close_sd_bsock(UAContext *ua)
684 {
685    if (ua->jcr->store_bsock) {
686       bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
687       bnet_close(ua->jcr->store_bsock);
688       ua->jcr->store_bsock = NULL;
689    }
690 }
691
692 static char *get_volume_name_from_SD(UAContext *ua, int Slot)
693 {
694    STORE *store = ua->jcr->store;
695    BSOCK *sd;
696    char dev_name[MAX_NAME_LENGTH];
697    char *VolName = NULL;
698    int rtn_slot;
699
700    if (!(sd=open_sd_bsock(ua))) {
701       bsendmsg(ua, _("Could not open SD socket.\n"));
702       return NULL;
703    }
704    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
705    bash_spaces(dev_name);
706    /* Ask for autochanger list of volumes */
707    bnet_fsend(sd, _("readlabel %s Slot=%d\n"), dev_name, Slot);
708    Dmsg1(100, "Sent: %s", sd->msg);
709
710    /* Get Volume name in this Slot */
711    while (bnet_recv(sd) >= 0) {
712       bsendmsg(ua, "%s", sd->msg);
713       Dmsg1(100, "Got: %s", sd->msg);
714       if (strncmp(sd->msg, "3001 Volume=", 12) == 0) {
715          VolName = (char *)malloc(sd->msglen);
716          if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) {
717             break;
718          }
719          free(VolName);
720          VolName = NULL;
721       }
722    }
723    close_sd_bsock(ua);
724    Dmsg1(200, "get_vol_name=%s\n", NPRT(VolName));
725    return VolName;
726 }
727
728 /*
729  * We get the slot list from the Storage daemon.
730  *  If scan is set, we return all slots found,
731  *  otherwise, we return only slots with valid barcodes (Volume names)
732  */
733 static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan)
734 {
735    STORE *store = ua->jcr->store;
736    char dev_name[MAX_NAME_LENGTH];
737    BSOCK *sd;
738    vol_list_t *vl;
739    vol_list_t *vol_list = NULL;
740
741
742    if (!(sd=open_sd_bsock(ua))) {
743       return NULL;
744    }
745
746    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
747    bash_spaces(dev_name);
748    /* Ask for autochanger list of volumes */
749    bnet_fsend(sd, _("autochanger list %s \n"), dev_name);
750
751    /* Read and organize list of Volumes */
752    while (bnet_recv(sd) >= 0) {
753       char *p;
754       int Slot;
755       strip_trailing_junk(sd->msg);
756
757       /* Check for returned SD messages */
758       if (sd->msg[0] == '3'     && B_ISDIGIT(sd->msg[1]) &&
759           B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
760           sd->msg[4] == ' ') {
761          bsendmsg(ua, "%s\n", sd->msg);   /* pass them on to user */
762          continue;
763       }
764
765       /* Validate Slot: if scanning, otherwise  Slot:Barcode */
766       p = strchr(sd->msg, ':');
767       if (scan && p) {
768          /* Scanning -- require only valid slot */
769          Slot = atoi(sd->msg);
770          if (Slot <= 0) {
771             p--;
772             *p = ':';
773             bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
774             continue;
775          }
776       } else {
777          /* Not scanning */
778          if (p && strlen(p) > 1) {
779             *p++ = 0;
780             if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) {
781                p--;
782                *p = ':';
783                bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg);
784                continue;
785             }
786          } else {
787             continue;
788          }
789          if (!is_volume_name_legal(ua, p)) {
790             p--;
791             *p = ':';
792             bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg);
793             continue;
794          }
795       }
796
797       /* Add Slot and VolumeName to list */
798       vl = (vol_list_t *)malloc(sizeof(vol_list_t));
799       vl->Slot = Slot;
800       if (p) {
801          if (*p == ':') {
802             p++;                      /* skip separator */
803          }
804          vl->VolName = bstrdup(p);
805       } else {
806          vl->VolName = NULL;
807       }
808       Dmsg2(100, "Add slot=%d Vol=%s to SD list.\n", vl->Slot, NPRT(vl->VolName));
809       if (!vol_list) {
810          vl->next = vol_list;
811          vol_list = vl;
812       } else {
813          /* Add new entry to end of list */
814          for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {
815             if (!tvl->next) {
816                tvl->next = vl;
817                vl->next = NULL;
818                break;
819             }
820          }
821       }
822    }
823    close_sd_bsock(ua);
824    return vol_list;
825 }
826
827 static void free_vol_list(vol_list_t *vol_list)
828 {
829    vol_list_t *vl;
830
831    /* Free list */
832    for (vl=vol_list; vl; ) {
833       vol_list_t *ovl;
834       if (vl->VolName) {
835          free(vl->VolName);
836       }
837       ovl = vl;
838       vl = vl->next;
839       free(ovl);
840    }
841 }
842
843 /*
844  * We get the number of slots in the changer from the SD
845  */
846 static int get_num_slots_from_SD(UAContext *ua)
847 {
848    STORE *store = ua->jcr->store;
849    char dev_name[MAX_NAME_LENGTH];
850    BSOCK *sd;
851    int slots = 0;
852
853
854    if (!(sd=open_sd_bsock(ua))) {
855       return 0;
856    }
857
858    bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
859    bash_spaces(dev_name);
860    /* Ask for autochanger list of volumes */
861    bnet_fsend(sd, _("autochanger slots %s \n"), dev_name);
862
863    while (bnet_recv(sd) >= 0) {
864       if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
865          break;
866       } else {
867          bsendmsg(ua, "%s", sd->msg);
868       }
869    }
870    close_sd_bsock(ua);
871    bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
872    return slots;
873 }
874
875
876
877 /*
878  * Check if this is a cleaning tape by comparing the Volume name
879  *  with the Cleaning Prefix. If they match, this is a cleaning
880  *  tape.
881  */
882 static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
883 {
884    /* Find Pool resource */
885    ua->jcr->pool = (POOL *)GetResWithName(R_POOL, pr->Name);
886    if (!ua->jcr->pool) {
887       bsendmsg(ua, _("Pool \"%s\" resource not found!\n"), pr->Name);
888       return true;
889    }
890    if (ua->jcr->pool->cleaning_prefix == NULL) {
891       return false;
892    }
893    Dmsg4(100, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n",
894       ua->jcr->pool->cleaning_prefix, mr->VolumeName,
895       strlen(ua->jcr->pool->cleaning_prefix),
896       strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
897                   strlen(ua->jcr->pool->cleaning_prefix)));
898    return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
899                   strlen(ua->jcr->pool->cleaning_prefix)) == 0;
900 }