static int deletecmd(UAContext *ua, char *cmd);
static int usecmd(UAContext *ua, char *cmd), unmountcmd(UAContext *ua, char *cmd);
static int labelcmd(UAContext *ua, char *cmd), mountcmd(UAContext *ua, char *cmd), updatecmd(UAContext *ua, char *cmd);
+static int relabelcmd(UAContext *ua, char *cmd), mountcmd(UAContext *ua, char *cmd), updatecmd(UAContext *ua, char *cmd);
static int versioncmd(UAContext *ua, char *cmd), automountcmd(UAContext *ua, char *cmd);
static int timecmd(UAContext *ua, char *cmd);
static int update_volume(UAContext *ua);
static int update_pool(UAContext *ua);
static int delete_volume(UAContext *ua);
static int delete_pool(UAContext *ua);
+static int do_label(UAContext *ua, char *cmd, int relabel);
int quitcmd(UAContext *ua, char *cmd);
{ N_("delete"), deletecmd, _("delete [pool=<pool-name> | media volume=<volume-name>]")},
{ 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 <pool> | files job=<nn>]; from catalog")},
{ N_("llist"), llistcmd, _("full or long list like list command")},
{ N_("messages"), messagescmd, _("messages")},
* 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;
}
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"));
}
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**** */
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) {
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);
/* 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 {
{"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},
*/
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;
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 */
(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"),
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 {
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);
*
* 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;
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);
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. \