From cc939b3ed89f6ad6ea2d9d9af5b904d16f52785e Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Fri, 4 Apr 2003 12:31:18 +0000 Subject: [PATCH] First cut of relabel command git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@418 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 2 + bacula/src/cats/drop_mysql_tables.in | 2 +- bacula/src/dird/ua_cmds.c | 86 ++++++++++++++++++++++------ bacula/src/stored/dircmd.c | 82 +++++++++++++++++++------- 4 files changed, 133 insertions(+), 39 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 4d6d5afe17..1125308619 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -20,6 +20,8 @@ Testing to do: (painful) - multiple simultaneous Volumes For 1.30 release: +- Pool requested twice in "relabel" command. + Must delete old volume from catalog. - Make non-zero status from RunJobBefore/After error the job. - Remove kern and kelvin from mysql_grant... - Install grant_mysql... diff --git a/bacula/src/cats/drop_mysql_tables.in b/bacula/src/cats/drop_mysql_tables.in index 19b1c3fa45..e538d2ed13 100644 --- a/bacula/src/cats/drop_mysql_tables.in +++ b/bacula/src/cats/drop_mysql_tables.in @@ -4,7 +4,7 @@ bindir=@SQL_BINDIR@ -if $bindir/mysql *$ < | media volume=]")}, { N_("help"), helpcmd, _("print this command")}, { N_("label"), labelcmd, _("label a tape")}, + { N_("relabel"), relabelcmd, _("relabel a tape")}, { N_("list"), listcmd, _("list [pools | jobs | jobtotals | media | files job=]; from catalog")}, { N_("llist"), llistcmd, _("full or long list like list command")}, { N_("messages"), messagescmd, _("messages")}, @@ -1273,20 +1276,39 @@ static int delete_pool(UAContext *ua) * label storage=xxx volume=vvv */ static int labelcmd(UAContext *ua, char *cmd) +{ + return do_label(ua, cmd, 0); /* standard label */ +} + +static int relabelcmd(UAContext *ua, char *cmd) +{ + return do_label(ua, cmd, 1); /* relabel tape */ +} + + +/* + * Common routine for both label and relabel + */ +static int do_label(UAContext *ua, char *cmd, int relabel) { STORE *store; BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; - MEDIA_DBR mr; + MEDIA_DBR mr, omr; POOL_DBR pr; int ok = FALSE; int mounted = FALSE; int i; int slot = 0; - static char *keyword[] = { + static char *name_keyword[] = { + "name", + NULL}; + + static char *vol_keyword[] = { "volume", NULL}; + if (!open_db(ua)) { return 1; } @@ -1295,20 +1317,46 @@ static int labelcmd(UAContext *ua, char *cmd) return 1; } - i = find_arg_keyword(ua, keyword); + /* If relabel get name of Volume to relabel */ + if (relabel) { + i = find_arg_keyword(ua, vol_keyword); + if (i >= 0 && ua->argv[i]) { + memset(&omr, 0, sizeof(omr)); + bstrncpy(omr.VolumeName, ua->argv[i], sizeof(omr.VolumeName)); + if (!db_get_media_record(ua->jcr, ua->db, &omr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + goto getVol; + } + goto gotVol; + } +getVol: + if (!select_pool_and_media_dbr(ua, &pr, &omr)) { + return 1; + } + +gotVol: + if (strcmp(omr.VolStatus, "Purged") != 0) { + bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be purged before relabeling.\n"), + omr.VolumeName, omr.VolStatus); + return 1; + } + } + + i = find_arg_keyword(ua, name_keyword); if (i >=0 && ua->argv[i]) { strcpy(ua->cmd, ua->argv[i]); - goto gotVol; + goto gotName; } -getVol: +getName: if (!get_cmd(ua, _("Enter new Volume name: "))) { return 1; } -gotVol: - if (strchr(ua->cmd, '|')) { +gotName: + /* ****FIXME*** be much more restrictive in the name */ + if (strpbrk(ua->cmd, "`~!@#$%^&*()[]{}|\\;'\"<>?,/")) { bsendmsg(ua, _("Illegal character | in a volume name.\n")); - goto getVol; + goto getName; } if (strlen(ua->cmd) >= MAX_NAME_LENGTH) { bsendmsg(ua, _("Volume name too long.\n")); @@ -1316,16 +1364,15 @@ gotVol: } if (strlen(ua->cmd) == 0) { bsendmsg(ua, _("Volume name must be at least one character long.\n")); - goto getVol; + goto getName; } - memset(&mr, 0, sizeof(mr)); strcpy(mr.VolumeName, ua->cmd); if (db_get_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Media record for Volume %s already exists.\n"), + bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), mr.VolumeName); - return 1; + goto getName; } /* Do some more checking on slot ****FIXME**** */ @@ -1356,9 +1403,16 @@ gotVol: bash_spaces(mr.VolumeName); bash_spaces(mr.MediaType); bash_spaces(pr.Name); - bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d"), - dev_name, mr.VolumeName, pr.Name, mr.MediaType, mr.Slot); - bsendmsg(ua, _("Sending label command ...\n")); + if (relabel) { + bash_spaces(omr.VolumeName); + bnet_fsend(sd, _("relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d"), + dev_name, omr.VolumeName, mr.VolumeName, pr.Name, mr.MediaType, mr.Slot); + bsendmsg(ua, _("Sending relabel command ...\n")); + } else { + bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d"), + dev_name, mr.VolumeName, pr.Name, mr.MediaType, mr.Slot); + bsendmsg(ua, _("Sending label command ...\n")); + } while (bget_msg(sd, 0) >= 0) { bsendmsg(ua, "%s", sd->msg); if (strncmp(sd->msg, "3000 OK label.", 14) == 0) { @@ -1376,7 +1430,7 @@ gotVol: if (ok) { set_pool_dbr_defaults_in_media_dbr(&mr, &pr); if (db_create_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Media record for Volume=%s successfully created.\n"), + bsendmsg(ua, _("Media record for Volume \"%s\" successfully created.\n"), mr.VolumeName); if (ua->automount) { bsendmsg(ua, _("Requesting mount %s ...\n"), dev_name); diff --git a/bacula/src/stored/dircmd.c b/bacula/src/stored/dircmd.c index de421646e7..016bd440aa 100644 --- a/bacula/src/stored/dircmd.c +++ b/bacula/src/stored/dircmd.c @@ -62,13 +62,16 @@ extern int job_cmd(JCR *jcr); /* Forward referenced functions */ static int label_cmd(JCR *jcr); +static int relabel_cmd(JCR *jcr); static int setdebug_cmd(JCR *jcr); static int cancel_cmd(JCR *cjcr); static int mount_cmd(JCR *jcr); static int unmount_cmd(JCR *jcr); static int status_cmd(JCR *sjcr); -static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname, - int Slot); +static int do_label(JCR *jcr, int relabel); +static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, + char *newname, char *poolname, + int Slot, int relabel); static void send_blocked_status(JCR *jcr, DEVICE *dev); struct s_cmds { @@ -84,6 +87,7 @@ static struct s_cmds cmds[] = { {"setdebug=", setdebug_cmd}, /* set debug level */ {"cancel", cancel_cmd}, {"label", label_cmd}, /* label a tape */ + {"relabel", relabel_cmd}, /* relabel a tape */ {"mount", mount_cmd}, {"unmount", unmount_cmd}, {"status", status_cmd}, @@ -239,21 +243,44 @@ static int cancel_cmd(JCR *cjcr) */ static int label_cmd(JCR *jcr) { - POOLMEM *dname, *volname, *poolname, *mtype; + return do_label(jcr, 0); +} + +static int relabel_cmd(JCR *jcr) +{ + return do_label(jcr, 1); +} + +static int do_label(JCR *jcr, int relabel) +{ + POOLMEM *dname, *newname, *oldname, *poolname, *mtype; BSOCK *dir = jcr->dir_bsock; DEVRES *device; DEVICE *dev; - int found = 0; + int found = 0, ok = 0; int slot; dname = get_memory(dir->msglen+1); - volname = get_memory(dir->msglen+1); + newname = get_memory(dir->msglen+1); + oldname = get_memory(dir->msglen+1); poolname = get_memory(dir->msglen+1); mtype = get_memory(dir->msglen+1); - if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d", - dname, volname, poolname, mtype, &slot) == 5) { + if (relabel) { + if (sscanf(dir->msg, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d", + dname, oldname, newname, poolname, mtype, &slot) == 6) { + ok = 1; + } + } else { + *oldname = 0; + if (sscanf(dir->msg, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d", + dname, newname, poolname, mtype, &slot) == 5) { + ok = 1; + } + } + if (ok) { unbash_spaces(dname); - unbash_spaces(volname); + unbash_spaces(newname); + unbash_spaces(oldname); unbash_spaces(poolname); unbash_spaces(mtype); device = NULL; @@ -274,10 +301,10 @@ static int label_cmd(JCR *jcr) P(dev->mutex); /* Use P to avoid indefinite block */ if (!(dev->state & ST_OPENED)) { - if (open_dev(dev, volname, READ_WRITE) < 0) { + if (open_dev(dev, newname, READ_WRITE) < 0) { bnet_fsend(dir, _("3994 Connot open device: %s\n"), strerror_dev(dev)); } else { - label_volume_if_ok(jcr, dev, volname, poolname, slot); + label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); force_close_dev(dev); } /* Under certain "safe" conditions, we can steal the lock */ @@ -285,7 +312,7 @@ static int label_cmd(JCR *jcr) (dev->dev_blocked == BST_UNMOUNTED || dev->dev_blocked == BST_WAITING_FOR_SYSOP || dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) { - label_volume_if_ok(jcr, dev, volname, poolname, slot); + label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); } else if (dev->state & ST_READ || dev->num_writers) { if (dev->state & ST_READ) { bnet_fsend(dir, _("3901 Device %s is busy with 1 reader.\n"), @@ -295,7 +322,7 @@ static int label_cmd(JCR *jcr) dev_name(dev), dev->num_writers); } } else { /* device not being used */ - label_volume_if_ok(jcr, dev, volname, poolname, slot); + label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel); } V(dev->mutex); } else { @@ -307,7 +334,8 @@ static int label_cmd(JCR *jcr) bnet_fsend(dir, _("3903 Error scanning label command: %s\n"), dname); } free_memory(dname); - free_memory(volname); + free_memory(oldname); + free_memory(newname); free_memory(poolname); free_memory(mtype); bnet_sig(dir, BNET_EOD); @@ -320,8 +348,9 @@ static int label_cmd(JCR *jcr) * * Enter with the mutex set */ -static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolname, - int slot) +static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname, + char *newname, char *poolname, + int slot, int relabel) { BSOCK *dir = jcr->dir_bsock; DEV_BLOCK *block; @@ -329,7 +358,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolnam steal_device_lock(dev, &hold, BST_WRITING_LABEL); - strcpy(jcr->VolumeName, vname); + strcpy(jcr->VolumeName, newname); jcr->VolCatInfo.Slot = slot; autoload_device(jcr, dev, 0, dir); /* autoload if possible */ block = new_block(dev); @@ -352,18 +381,27 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *vname, char *poolnam case VOL_VERSION_ERROR: case VOL_LABEL_ERROR: case VOL_OK: - bnet_fsend(dir, _("3901 Cannot label Volume because it is \ -already labeled: %s\n"), dev->VolHdr.VolName); - break; + if (!relabel) { + bnet_fsend(dir, _( + "3901 Cannot label Volume because it is already labeled: %s\n"), + dev->VolHdr.VolName); + break; + } + /* Relabel request. If oldname matches, continue */ + if (strcmp(oldname, dev->VolHdr.VolName) != 0) { + bnet_fsend(dir, _("Wrong volume mounted.\n")); + break; + } + /* Fall through wanted! */ case VOL_IO_ERROR: case VOL_NO_LABEL: - if (!write_volume_label_to_dev(jcr, jcr->device, vname, poolname)) { + if (!write_volume_label_to_dev(jcr, jcr->device, newname, poolname)) { bnet_fsend(dir, _("3903 Failed to label Volume: ERR=%s\n"), strerror_dev(dev)); break; } - strcpy(jcr->VolumeName, vname); + strcpy(jcr->VolumeName, newname); bnet_fsend(dir, _("3000 OK label. Volume=%s Device=%s\n"), - vname, dev->dev_name); + newname, dev->dev_name); break; default: bnet_fsend(dir, _("3902 Cannot label Volume. \ -- 2.39.5