3 * Bacula Director -- Tape labeling commands
5 * Kern Sibbald, April MMIII
11 Copyright (C) 2000-2003 Kern Sibbald and John Walker
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.
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.
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,
33 /* Slot list definition */
34 typedef struct s_vol_list {
35 struct s_vol_list *next;
41 /* Forward referenced functions */
42 static int do_label(UAContext *ua, char *cmd, int relabel);
43 static void label_from_barcodes(UAContext *ua);
44 static int is_legal_volume_name(UAContext *ua, char *name);
45 static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
46 POOL_DBR *pr, int relabel);
47 static vol_list_t *get_slot_list_from_SD(UAContext *ua);
53 * label storage=xxx volume=vvv
55 int labelcmd(UAContext *ua, char *cmd)
57 return do_label(ua, cmd, 0); /* standard label */
60 int relabelcmd(UAContext *ua, char *cmd)
62 return do_label(ua, cmd, 1); /* relabel tape */
67 * Update Slots corresponding to Volumes in autochanger
69 int update_slots(UAContext *ua)
72 vol_list_t *vl, *vol_list = NULL;
78 store = get_storage_resource(ua, 1);
82 ua->jcr->store = store;
84 vol_list = get_slot_list_from_SD(ua);
88 bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
92 /* Walk through the list updating the media records */
93 for (vl=vol_list; vl; vl=vl->next) {
95 memset(&mr, 0, sizeof(mr));
96 bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
97 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
98 if (mr.Slot != vl->Slot) {
100 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
101 bsendmsg(ua, _("%s\n"), db_strerror(ua->db));
104 "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
108 bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
113 bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"),
121 for (vl=vol_list; vl; ) {
129 if (ua->jcr->store_bsock) {
130 bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
131 bnet_close(ua->jcr->store_bsock);
132 ua->jcr->store_bsock = NULL;
138 * Common routine for both label and relabel
140 static int do_label(UAContext *ua, char *cmd, int relabel)
144 sd = ua->jcr->store_bsock;
145 char dev_name[MAX_NAME_LENGTH];
151 static char *name_keyword[] = {
154 static char *vol_keyword[] = {
157 static char *barcode_keyword[] = {
163 memset(&pr, 0, sizeof(pr));
167 store = get_storage_resource(ua, 1);
171 ua->jcr->store = store;
173 if (!relabel && find_arg_keyword(ua, barcode_keyword) >= 0) {
174 label_from_barcodes(ua);
178 /* If relabel get name of Volume to relabel */
180 /* Check for volume=OldVolume */
181 i = find_arg_keyword(ua, vol_keyword);
182 if (i >= 0 && ua->argv[i]) {
183 memset(&omr, 0, sizeof(omr));
184 bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
185 if (db_get_media_record(ua->jcr, ua->db, &omr)) {
188 bsendmsg(ua, "%s", db_strerror(ua->db));
190 /* No keyword or Vol not found, ask user to select */
191 if (!select_pool_and_media_dbr(ua, &pr, &omr)) {
195 /* Require Volume to be Purged */
197 if (strcmp(omr.VolStatus, "Purged") != 0) {
198 bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be purged before relabeling.\n"),
199 omr.VolumeName, omr.VolStatus);
204 /* Check for name=NewVolume */
205 i = find_arg_keyword(ua, name_keyword);
206 if (i >=0 && ua->argv[i]) {
207 pm_strcpy(&ua->cmd, ua->argv[i]);
211 /* Get a new Volume name */
213 if (!get_cmd(ua, _("Enter new Volume name: "))) {
217 if (!is_legal_volume_name(ua, ua->cmd)) {
221 memset(&mr, 0, sizeof(mr));
222 bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName));
223 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
224 bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
231 /* If autochanger, request slot */
232 if (store->autochanger) {
234 if (!get_cmd(ua, _("Enter slot (0 for none): "))) {
237 mr.Slot = atoi(ua->cmd);
238 if (mr.Slot >= 0) { /* OK */
241 bsendmsg(ua, _("Slot numbers must be positive.\n"));
244 bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
246 /* Must select Pool if not already done */
247 if (pr.PoolId == 0) {
248 memset(&pr, 0, sizeof(pr));
249 if (!select_pool_dbr(ua, &pr)) {
254 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
255 store->hdr.name, store->address, store->SDport);
256 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
257 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
260 sd = ua->jcr->store_bsock;
262 ok = send_label_request(ua, &mr, &omr, &pr, relabel);
266 if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
267 bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"),
268 omr.VolumeName, db_strerror(ua->db));
270 bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
275 strcpy(dev_name, store->dev_name);
276 bsendmsg(ua, _("Requesting mount %s ...\n"), dev_name);
277 bash_spaces(dev_name);
278 bnet_fsend(sd, "mount %s", dev_name);
279 unbash_spaces(dev_name);
280 while (bnet_recv(sd) >= 0) {
281 bsendmsg(ua, "%s", sd->msg);
283 * 3001 OK mount. Device=xxx or
284 * 3001 Mounted Volume vvvv
286 mounted = strncmp(sd->msg, "3001 ", 5) == 0;
291 bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
293 bnet_sig(sd, BNET_TERMINATE);
295 ua->jcr->store_bsock = NULL;
301 * Request SD to send us the slot:barcodes, then wiffle
302 * through them all labeling them.
304 static void label_from_barcodes(UAContext *ua)
306 STORE *store = ua->jcr->store;
309 vol_list_t *vl, *vol_list = NULL;
311 vol_list = get_slot_list_from_SD(ua);
315 bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
319 /* Display list of Volumes and ask if he really wants to proceed */
320 bsendmsg(ua, _("The following Volumes will be labeled:\n"
322 "==============\n"));
323 for (vl=vol_list; vl; vl=vl->next) {
324 bsendmsg(ua, "%4d %s\n", vl->Slot, vl->VolName);
326 if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
327 (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
331 memset(&pr, 0, sizeof(pr));
332 if (!select_pool_dbr(ua, &pr)) {
335 memset(&omr, 0, sizeof(omr));
337 /* Fire off the label requests */
338 for (vl=vol_list; vl; vl=vl->next) {
340 memset(&mr, 0, sizeof(mr));
341 bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
342 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
343 bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"),
344 vl->Slot, mr.VolumeName);
347 bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
348 if (ua->jcr->store_bsock) {
349 bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
350 bnet_close(ua->jcr->store_bsock);
351 ua->jcr->store_bsock = NULL;
353 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
354 store->hdr.name, store->address, store->SDport);
355 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
356 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
361 send_label_request(ua, &mr, &omr, &pr, 0);
367 for (vl=vol_list; vl; ) {
375 if (ua->jcr->store_bsock) {
376 bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE);
377 bnet_close(ua->jcr->store_bsock);
378 ua->jcr->store_bsock = NULL;
384 static int is_legal_volume_name(UAContext *ua, char *name)
387 /* Restrict the characters permitted in the Volume name */
388 if (strpbrk(name, "`~!@#$%^&*()[]{}|\\;'\"<>?,/")) {
389 bsendmsg(ua, _("Illegal character | in a volume name.\n"));
393 if (len >= MAX_NAME_LENGTH) {
394 bsendmsg(ua, _("Volume name too long.\n"));
398 bsendmsg(ua, _("Volume name must be at least one character long.\n"));
404 static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
405 POOL_DBR *pr, int relabel)
408 char dev_name[MAX_NAME_LENGTH];
411 sd = ua->jcr->store_bsock;
412 bstrncpy(dev_name, ua->jcr->store->dev_name, sizeof(dev_name));
413 bash_spaces(dev_name);
414 bash_spaces(mr->VolumeName);
415 bash_spaces(mr->MediaType);
416 bash_spaces(pr->Name);
418 bash_spaces(omr->VolumeName);
419 bnet_fsend(sd, _("relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d"),
420 dev_name, omr->VolumeName, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
421 bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
422 omr->VolumeName, mr->VolumeName);
424 bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d"),
425 dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
426 bsendmsg(ua, _("Sending label command for Volume \"%s\" ...\n"), mr->VolumeName);
427 Dmsg5(200, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d\n",
428 dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
431 while (bget_msg(sd, 0) >= 0) {
432 bsendmsg(ua, "%s", sd->msg);
433 if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
437 unbash_spaces(mr->VolumeName);
438 unbash_spaces(mr->MediaType);
439 unbash_spaces(pr->Name);
440 mr->LabelDate = time(NULL);
442 set_pool_dbr_defaults_in_media_dbr(mr, pr);
443 if (db_create_media_record(ua->jcr, ua->db, mr)) {
444 bsendmsg(ua, _("Media record for Volume \"%s\" successfully created.\n"),
447 bsendmsg(ua, "%s", db_strerror(ua->db));
451 bsendmsg(ua, _("Label command failed.\n"));
456 static vol_list_t *get_slot_list_from_SD(UAContext *ua)
458 STORE *store = ua->jcr->store;
459 char dev_name[MAX_NAME_LENGTH];
462 vol_list_t *vol_list = NULL;
465 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
466 store->hdr.name, store->address, store->SDport);
467 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
468 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
471 sd = ua->jcr->store_bsock;
473 bstrncpy(dev_name, store->dev_name, sizeof(dev_name));
474 bash_spaces(dev_name);
475 /* Ask for autochanger list of volumes */
476 bnet_fsend(sd, _("autochanger list %s \n"), dev_name);
478 /* Read and organize list of Volumes */
479 while (bget_msg(sd, 0) >= 0) {
482 strip_trailing_junk(sd->msg);
484 /* Check for returned SD messages */
485 if (sd->msg[0] == '3' && sd->msg[1] == '9' &&
486 B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
488 bsendmsg(ua, "%s\n", sd->msg); /* pass them on to user */
492 /* Validate Slot:Barcode */
493 p = strchr(sd->msg, ':');
494 if (p && strlen(p) > 1) {
496 if (!is_an_integer(sd->msg)) {
502 Slot = atoi(sd->msg);
503 if (Slot <= 0 || !is_legal_volume_name(ua, p)) {
507 /* Add Slot and VolumeName to list */
508 vl = (vol_list_t *)malloc(sizeof(vol_list_t));
510 vl->VolName = bstrdup(p);
515 /* Add new entry to end of list */
516 for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) {