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 /* Forward referenced functions */
34 static int do_label(UAContext *ua, char *cmd, int relabel);
35 static void label_from_barcodes(UAContext *ua);
36 static int is_legal_volume_name(UAContext *ua, char *name);
37 static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
38 POOL_DBR *pr, int relabel);
44 * label storage=xxx volume=vvv
46 int labelcmd(UAContext *ua, char *cmd)
48 return do_label(ua, cmd, 0); /* standard label */
51 int relabelcmd(UAContext *ua, char *cmd)
53 return do_label(ua, cmd, 1); /* relabel tape */
58 * Common routine for both label and relabel
60 static int do_label(UAContext *ua, char *cmd, int relabel)
64 sd = ua->jcr->store_bsock;
65 char dev_name[MAX_NAME_LENGTH];
71 static char *name_keyword[] = {
74 static char *vol_keyword[] = {
77 static char *barcode_keyword[] = {
83 memset(&pr, 0, sizeof(pr));
87 store = get_storage_resource(ua, cmd);
91 ua->jcr->store = store;
93 if (!relabel && find_arg_keyword(ua, barcode_keyword) >= 0) {
94 label_from_barcodes(ua);
98 /* If relabel get name of Volume to relabel */
100 /* Check for volume=OldVolume */
101 i = find_arg_keyword(ua, vol_keyword);
102 if (i >= 0 && ua->argv[i]) {
103 memset(&omr, 0, sizeof(omr));
104 bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName));
105 if (db_get_media_record(ua->jcr, ua->db, &omr)) {
108 bsendmsg(ua, "%s", db_strerror(ua->db));
110 /* No keyword or Vol not found, ask user to select */
111 if (!select_pool_and_media_dbr(ua, &pr, &omr)) {
115 /* Require Volume to be Purged */
117 if (strcmp(omr.VolStatus, "Purged") != 0) {
118 bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be purged before relabeling.\n"),
119 omr.VolumeName, omr.VolStatus);
124 /* Check for name=NewVolume */
125 i = find_arg_keyword(ua, name_keyword);
126 if (i >=0 && ua->argv[i]) {
127 strcpy(ua->cmd, ua->argv[i]);
131 /* Get a new Volume name */
133 if (!get_cmd(ua, _("Enter new Volume name: "))) {
137 if (!is_legal_volume_name(ua, ua->cmd)) {
141 memset(&mr, 0, sizeof(mr));
142 strcpy(mr.VolumeName, ua->cmd);
143 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
144 bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
151 /* If autochanger, request slot */
152 if (store->autochanger) {
154 if (!get_cmd(ua, _("Enter slot (0 for none): "))) {
157 mr.Slot = atoi(ua->cmd);
158 if (mr.Slot >= 0) { /* OK */
161 bsendmsg(ua, _("Slot numbers must be positive.\n"));
164 strcpy(mr.MediaType, store->media_type);
166 /* Must select Pool if not already done */
167 if (pr.PoolId == 0) {
168 memset(&pr, 0, sizeof(pr));
169 if (!select_pool_dbr(ua, &pr)) {
174 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
175 store->hdr.name, store->address, store->SDport);
176 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
177 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
180 sd = ua->jcr->store_bsock;
182 ok = send_label_request(ua, &mr, &omr, &pr, relabel);
186 if (!db_delete_media_record(ua->jcr, ua->db, &omr)) {
187 bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"),
188 omr.VolumeName, db_strerror(ua->db));
190 bsendmsg(ua, _("Old volume \"%s\" deleted from catalog.\n"),
195 strcpy(dev_name, store->dev_name);
196 bsendmsg(ua, _("Requesting mount %s ...\n"), dev_name);
197 bash_spaces(dev_name);
198 bnet_fsend(sd, "mount %s", dev_name);
199 unbash_spaces(dev_name);
200 while (bnet_recv(sd) >= 0) {
201 bsendmsg(ua, "%s", sd->msg);
203 * 3001 OK mount. Device=xxx or
204 * 3001 Mounted Volume vvvv
206 mounted = strncmp(sd->msg, "3001 ", 5) == 0;
211 bsendmsg(ua, _("Do not forget to mount the drive!!!\n"));
213 bnet_sig(sd, BNET_TERMINATE);
215 ua->jcr->store_bsock = NULL;
221 * Request SD to send us the slot:barcodes, then wiffle
222 * through them all labeling them.
224 static void label_from_barcodes(UAContext *ua)
226 STORE *store = ua->jcr->store;
229 char dev_name[MAX_NAME_LENGTH];
230 // MEDIA_DBR mr, omr;
231 typedef struct s_vol_list {
232 struct s_vol_list *next;
236 vol_list_t *vol_list = NULL;
239 bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"),
240 store->hdr.name, store->address, store->SDport);
241 if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
242 bsendmsg(ua, _("Failed to connect to Storage daemon.\n"));
245 sd = ua->jcr->store_bsock;
247 bstrncpy(dev_name, store->dev_name, sizeof(dev_name));
248 bash_spaces(dev_name);
249 bnet_fsend(sd, _("autochanger list %s \n"), dev_name);
250 while (bget_msg(sd, 0) >= 0) {
252 strip_trailing_junk(sd->msg);
253 /* Check for returned SD messages */
254 if (sd->msg[0] == '3' && sd->msg[1] == '9' &&
255 B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) &&
257 bsendmsg(ua, "%s\n", sd->msg); /* pass them on to user */
260 p = strchr(sd->msg, ':');
261 if (p && strlen(p) > 1) {
263 if (!is_an_integer(sd->msg)) {
269 vl = (vol_list_t *)malloc(sizeof(vol_list_t));
270 vl->Slot = atoi(sd->msg);
271 vl->VolName = bstrdup(p);
277 bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n"));
280 bsendmsg(ua, _("The following Volumes will be labeled:\n"
282 "==============\n"));
283 for (vl=vol_list; vl; vl=vl->next) {
284 bsendmsg(ua, "%4d %s\n", vl->Slot, vl->VolName);
286 if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) ||
287 (ua->cmd[0] != 'y' && ua->cmd[0] != 'Y')) {
294 memset(&mr, 0, sizeof(mr));
295 strcpy(mr.VolumeName, ua->cmd);
296 if (db_get_media_record(ua->jcr, ua->db, &mr)) {
297 bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"),
305 for (vl=vol_list; vl; ) {
313 bnet_sig(sd, BNET_TERMINATE);
315 ua->jcr->store_bsock = NULL;
319 memset(&pr, 0, sizeof(pr));
320 if (!select_pool_dbr(ua, &pr)) {
327 static int is_legal_volume_name(UAContext *ua, char *name)
330 /* Restrict the characters permitted in the Volume name */
331 if (strpbrk(name, "`~!@#$%^&*()[]{}|\\;'\"<>?,/")) {
332 bsendmsg(ua, _("Illegal character | in a volume name.\n"));
336 if (len >= MAX_NAME_LENGTH) {
337 bsendmsg(ua, _("Volume name too long.\n"));
341 bsendmsg(ua, _("Volume name must be at least one character long.\n"));
347 static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
348 POOL_DBR *pr, int relabel)
351 char dev_name[MAX_NAME_LENGTH];
354 sd = ua->jcr->store_bsock;
355 strcpy(dev_name, ua->jcr->store->dev_name);
356 bash_spaces(dev_name);
357 bash_spaces(mr->VolumeName);
358 bash_spaces(mr->MediaType);
359 bash_spaces(pr->Name);
361 bash_spaces(omr->VolumeName);
362 bnet_fsend(sd, _("relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d"),
363 dev_name, omr->VolumeName, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
364 bsendmsg(ua, _("Sending relabel command ...\n"));
366 bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d"),
367 dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
368 bsendmsg(ua, _("Sending label command ...\n"));
370 while (bget_msg(sd, 0) >= 0) {
371 bsendmsg(ua, "%s", sd->msg);
372 if (strncmp(sd->msg, "3000 OK label.", 14) == 0) {
375 bsendmsg(ua, _("Label command failed.\n"));
378 ua->jcr->store_bsock = NULL;
379 unbash_spaces(dev_name);
380 unbash_spaces(mr->VolumeName);
381 unbash_spaces(mr->MediaType);
382 unbash_spaces(pr->Name);
383 mr->LabelDate = time(NULL);
385 set_pool_dbr_defaults_in_media_dbr(mr, pr);
386 if (db_create_media_record(ua->jcr, ua->db, mr)) {
387 bsendmsg(ua, _("Media record for Volume \"%s\" successfully created.\n"),
390 bsendmsg(ua, "%s", db_strerror(ua->db));