X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fua_label.c;h=09cffcfdc94043b2d21b2192d06c8015d6ba7736;hb=dc83bbe56442776be31442bba5438cefb3f50a52;hp=1e1a5822beb91bb880f820d2988d4735316c3b7f;hpb=002127fa1d728384beb2d4ad447e892b63abb73e;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 1e1a5822be..09cffcfdc9 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -42,9 +42,13 @@ typedef struct s_vol_list { static int do_label(UAContext *ua, char *cmd, int relabel); static void label_from_barcodes(UAContext *ua); static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, - POOL_DBR *pr, int relabel); -static vol_list_t *get_slot_list_from_SD(UAContext *ua); + POOL_DBR *pr, int relabel, bool media_record_exits); +static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan); +static void free_vol_list(vol_list_t *vol_list); static int is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr); +static BSOCK *open_sd_bsock(UAContext *ua); +static void close_sd_bsock(UAContext *ua); +static char *get_volume_name_from_SD(UAContext *ua, int Slot); /* @@ -62,6 +66,91 @@ int relabel_cmd(UAContext *ua, char *cmd) return do_label(ua, cmd, 1); /* relabel tape */ } +#define MAX_SLOTS 5000 + +static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) +{ + int i; + char *msg; + + for (int i=0; i= 0) { + /* scan slot list in ua->argv[i] */ + char *p, *e, *h; + int beg, end; + + strip_trailing_junk(ua->argv[i]); + for (p=ua->argv[i]; p && *p; p=e) { + /* Check for list */ + e = strchr(p, ','); + if (e) { + *e++ = 0; + } + /* Check for range */ + h = strchr(p, '-'); /* range? */ + if (h == p) { + msg = _("Negative numbers not permitted\n"); + goto bail_out; + } + if (h) { + *h++ = 0; + if (!is_an_integer(h)) { + msg = _("Range end is not integer.\n"); + goto bail_out; + } + skip_spaces(&p); + if (!is_an_integer(p)) { + msg = _("Range start is not an integer.\n"); + goto bail_out; + } + beg = atoi(p); + end = atoi(h); + if (end < beg) { + msg = _("Range end not bigger than start.\n"); + goto bail_out; + } + } else { + skip_spaces(&p); + if (!is_an_integer(p)) { + msg = _("Input value is not an integer.\n"); + goto bail_out; + } + beg = end = atoi(p); + } + if (beg <= 0 || end <= 0) { + msg = _("Values must be be greater than zero.\n"); + goto bail_out; + } + if (end >= num_slots) { + msg = _("Slot too large.\n"); + goto bail_out; + } + for (i=beg; i<=end; i++) { + slot_list[i] = 1; /* Turn on specified range */ + } + } + } else { + /* Turn everything on */ + for (i=0; ijcr->store = store; - vol_list = get_slot_list_from_SD(ua); + scan = find_arg(ua, _("scan")) >= 0; + slot_list = (char *)malloc(MAX_SLOTS); + if (!get_user_slot_list(ua, slot_list, MAX_SLOTS)) { + free(slot_list); + return 1; + } + + vol_list = get_vol_list_from_SD(ua, scan); if (!vol_list) { bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n")); @@ -91,13 +189,28 @@ int update_slots(UAContext *ua) /* Walk through the list updating the media records */ for (vl=vol_list; vl; vl=vl->next) { - + /* Check if user wants us to look at this slot */ + if (!slot_list[vl->Slot]) { + continue; + } + /* If scanning, we read the label rather than the barcode */ + if (scan) { + if (vl->VolName) { + free(vl->VolName); + vl->VolName = NULL; + } + vl->VolName = get_volume_name_from_SD(ua, vl->Slot); + } + if (!vl->VolName) { + continue; + } memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); db_lock(ua->db); if (db_get_media_record(ua->jcr, ua->db, &mr)) { - if (mr.Slot != vl->Slot) { + if (mr.Slot != vl->Slot || !mr.InChanger) { mr.Slot = vl->Slot; + mr.InChanger = 1; if (!db_update_media_record(ua->jcr, ua->db, &mr)) { bsendmsg(ua, _("%s\n"), db_strerror(ua->db)); } else { @@ -120,23 +233,15 @@ int update_slots(UAContext *ua) bail_out: - /* Free list */ - for (vl=vol_list; vl; ) { - vol_list_t *ovl; - free(vl->VolName); - ovl = vl; - vl = vl->next; - free(ovl); - } - if (ua->jcr->store_bsock) { - bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); - bnet_close(ua->jcr->store_bsock); - ua->jcr->store_bsock = NULL; - } + free_vol_list(vol_list); + free(slot_list); + close_sd_bsock(ua); + return 1; } + /* * Common routine for both label and relabel */ @@ -144,13 +249,13 @@ static int do_label(UAContext *ua, char *cmd, int relabel) { STORE *store; BSOCK *sd; - sd = ua->jcr->store_bsock; char dev_name[MAX_NAME_LENGTH]; MEDIA_DBR mr, omr; POOL_DBR pr; + bool print_reminder = true; int ok = FALSE; - int mounted = FALSE; int i; + bool media_record_exists = false; static char *barcode_keyword[] = { "barcode", "barcodes", @@ -189,10 +294,10 @@ static int do_label(UAContext *ua, char *cmd, int relabel) return 1; } - /* Require Volume to be Purged */ + /* Require Volume to be Purged or Recycled */ checkVol: - if (strcmp(omr.VolStatus, "Purged") != 0) { - bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be purged before relabeling.\n"), + if (strcmp(omr.VolStatus, "Purged") != 0 || strcmp(omr.VolStatus, "Recycle") != 0) { + bsendmsg(ua, _("Volume \"%s\" has VolStatus %s. It must be Purged or Recycled before relabeling.\n"), omr.VolumeName, omr.VolStatus); return 1; } @@ -207,6 +312,7 @@ checkVol: /* Get a new Volume name */ for ( ;; ) { + media_record_exists = false; if (!get_cmd(ua, _("Enter new Volume name: "))) { return 1; } @@ -217,10 +323,14 @@ checkName: memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, ua->cmd, sizeof(mr.VolumeName)); + /* If VolBytes are zero the Volume is not labeled */ if (db_get_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), - mr.VolumeName); - continue; + if (mr.VolBytes != 0) { + bsendmsg(ua, _("Media record for new Volume \"%s\" already exists.\n"), + mr.VolumeName); + continue; + } + media_record_exists = true; } break; /* Got it */ } @@ -235,6 +345,7 @@ checkName: } else { mr.Slot = ua->pint32_val; } + mr.InChanger = 1; /* assumed if we are labeling it */ } bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); @@ -247,17 +358,11 @@ checkName: } } - bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); - return 1; - } - sd = ua->jcr->store_bsock; - ok = send_label_request(ua, &mr, &omr, &pr, relabel); + ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists); if (ok) { + sd = ua->jcr->store_bsock; if (relabel) { if (!db_delete_media_record(ua->jcr, ua->db, &omr)) { bsendmsg(ua, _("Delete of Volume \"%s\" failed. ERR=%s"), @@ -268,8 +373,8 @@ checkName: } } if (ua->automount) { - strcpy(dev_name, store->dev_name); - bsendmsg(ua, _("Requesting mount %s ...\n"), dev_name); + bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); + bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name); bash_spaces(dev_name); bnet_fsend(sd, "mount %s", dev_name); unbash_spaces(dev_name); @@ -278,17 +383,20 @@ checkName: /* Here we can get * 3001 OK mount. Device=xxx or * 3001 Mounted Volume vvvv + * 3906 is cannot mount non-tape + * So for those, no need to print a reminder */ - mounted = strncmp(sd->msg, "3001 ", 5) == 0; + if (strncmp(sd->msg, "3001 ", 5) == 0 || + strncmp(sd->msg, "3906 ", 5) == 0) { + print_reminder = false; + } } } } - if (!mounted) { + if (print_reminder) { bsendmsg(ua, _("Do not forget to mount the drive!!!\n")); } - bnet_sig(sd, BNET_TERMINATE); - bnet_close(sd); - ua->jcr->store_bsock = NULL; + close_sd_bsock(ua); return 1; } @@ -303,8 +411,16 @@ static void label_from_barcodes(UAContext *ua) POOL_DBR pr; MEDIA_DBR mr, omr; vol_list_t *vl, *vol_list = NULL; + bool media_record_exists; + char *slot_list; + + slot_list = (char *)malloc(MAX_SLOTS); + if (!get_user_slot_list(ua, slot_list, MAX_SLOTS)) { + free(slot_list); + return; + } - vol_list = get_slot_list_from_SD(ua); + vol_list = get_vol_list_from_SD(ua, false /*no scan*/); if (!vol_list) { bsendmsg(ua, _("No Volumes found to label, or no barcodes.\n")); @@ -316,6 +432,9 @@ static void label_from_barcodes(UAContext *ua) "Slot Volume\n" "==============\n")); for (vl=vol_list; vl; vl=vl->next) { + if (!vl->VolName || !slot_list[vl->Slot]) { + continue; + } bsendmsg(ua, "%4d %s\n", vl->Slot, vl->VolName); } if (!get_cmd(ua, _("Do you want to continue? (y/n): ")) || @@ -331,61 +450,60 @@ static void label_from_barcodes(UAContext *ua) /* Fire off the label requests */ for (vl=vol_list; vl; vl=vl->next) { - + if (!vl->VolName || !slot_list[vl->Slot]) { + continue; + } memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); + media_record_exists = false; if (db_get_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), - vl->Slot, mr.VolumeName); - continue; + if (mr.VolBytes != 0) { + bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"), + vl->Slot, mr.VolumeName); + if (!mr.InChanger) { + mr.InChanger = 1; + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db)); + } + } + continue; + } + media_record_exists = true; } + mr.InChanger = 1; /* * Deal with creating cleaning tape here. Normal tapes created in * send_label_request() below */ if (is_cleaning_tape(ua, &mr, &pr)) { - set_pool_dbr_defaults_in_media_dbr(&mr, &pr); - if (db_create_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"), - mr.VolumeName); - } else { - bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db)); + if (media_record_exists) { /* we update it */ + mr.VolBytes = 1; + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } + } else { /* create the media record */ + set_pool_dbr_defaults_in_media_dbr(&mr, &pr); + if (db_create_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"), + mr.VolumeName); + } else { + bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db)); + } } - continue; + continue; /* done, go handle next volume */ } bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); - if (ua->jcr->store_bsock) { - bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); - bnet_close(ua->jcr->store_bsock); - ua->jcr->store_bsock = NULL; - } - bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); - goto bail_out; - } mr.Slot = vl->Slot; - send_label_request(ua, &mr, &omr, &pr, 0); + if (!send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists)) { + goto bail_out; + } } bail_out: - /* Free list */ - for (vl=vol_list; vl; ) { - vol_list_t *ovl; - free(vl->VolName); - ovl = vl; - vl = vl->next; - free(ovl); - } - - if (ua->jcr->store_bsock) { - bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); - bnet_close(ua->jcr->store_bsock); - ua->jcr->store_bsock = NULL; - } + free_vol_list(vol_list); + close_sd_bsock(ua); return; } @@ -427,13 +545,15 @@ int is_volume_name_legal(UAContext *ua, char *name) } static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, - POOL_DBR *pr, int relabel) + POOL_DBR *pr, int relabel, bool media_record_exists) { BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; int ok = FALSE; - sd = ua->jcr->store_bsock; + if (!(sd=open_sd_bsock(ua))) { + return 0; + } bstrncpy(dev_name, ua->jcr->store->dev_name, sizeof(dev_name)); bash_spaces(dev_name); bash_spaces(mr->VolumeName); @@ -441,12 +561,12 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, bash_spaces(pr->Name); if (relabel) { bash_spaces(omr->VolumeName); - bnet_fsend(sd, _("relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d"), + 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 from \"%s\" to \"%s\" ...\n"), omr->VolumeName, mr->VolumeName); } else { - bnet_fsend(sd, _("label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d"), + 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 for Volume \"%s\" Slot %d ...\n"), mr->VolumeName, mr->Slot); @@ -465,13 +585,24 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, unbash_spaces(pr->Name); mr->LabelDate = time(NULL); if (ok) { - set_pool_dbr_defaults_in_media_dbr(mr, pr); - if (db_create_media_record(ua->jcr, ua->db, mr)) { - bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), + if (media_record_exists) { /* we update it */ + mr->VolBytes = 1; + mr->InChanger = 1; + if (!db_update_media_record(ua->jcr, ua->db, mr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + ok = FALSE; + } + } else { /* create the media record */ + set_pool_dbr_defaults_in_media_dbr(mr, pr); + mr->VolBytes = 1; /* flag indicating Volume labeled */ + mr->InChanger = 1; + if (db_create_media_record(ua->jcr, ua->db, mr)) { + bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d successfully created.\n"), mr->VolumeName, mr->Slot); - } else { - bsendmsg(ua, "%s", db_strerror(ua->db)); - ok = FALSE; + } else { + bsendmsg(ua, "%s", db_strerror(ua->db)); + ok = FALSE; + } } } else { bsendmsg(ua, _("Label command failed.\n")); @@ -479,7 +610,69 @@ static int send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, return ok; } -static vol_list_t *get_slot_list_from_SD(UAContext *ua) +static BSOCK *open_sd_bsock(UAContext *ua) +{ + STORE *store = ua->jcr->store; + + if (!ua->jcr->store_bsock) { + bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), + store->hdr.name, store->address, store->SDport); + if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { + bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); + return NULL; + } + } + return ua->jcr->store_bsock; +} + +static void close_sd_bsock(UAContext *ua) +{ + if (ua->jcr->store_bsock) { + bnet_sig(ua->jcr->store_bsock, BNET_TERMINATE); + bnet_close(ua->jcr->store_bsock); + ua->jcr->store_bsock = NULL; + } +} + +static char *get_volume_name_from_SD(UAContext *ua, int Slot) +{ + STORE *store = ua->jcr->store; + BSOCK *sd; + char dev_name[MAX_NAME_LENGTH]; + char *VolName = NULL; + int rtn_slot; + + if (!(sd=open_sd_bsock(ua))) { + return NULL; + } + bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); + bash_spaces(dev_name); + /* Ask for autochanger list of volumes */ + bnet_fsend(sd, _("readlabel %s Slot=%d\n"), dev_name, Slot); + Dmsg1(100, "Sent: %s", sd->msg); + + /* Get Volume name in this Slot */ + while (bnet_recv(sd) >= 0) { + bsendmsg(ua, "%s", sd->msg); + if (strncmp(sd->msg, "3001 Volume=", 12) == 0) { + VolName = (char *)malloc(sd->msglen); + if (sscanf(sd->msg, "3001 Volume=%s Slot=%d", VolName, &rtn_slot) == 2) { + break; + } + free(VolName); + VolName = NULL; + } + } + Dmsg1(200, "get_vol_name=%s\n", NPRT(VolName)); + return VolName; +} + +/* + * We get the slot list from the Storage daemon. + * If scan is set, we return all slots found, + * otherwise, we return only slots with valid barcodes (Volume names) + */ +static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) { STORE *store = ua->jcr->store; char dev_name[MAX_NAME_LENGTH]; @@ -488,13 +681,9 @@ static vol_list_t *get_slot_list_from_SD(UAContext *ua) vol_list_t *vol_list = NULL; - bsendmsg(ua, _("Connecting to Storage daemon %s at %s:%d ...\n"), - store->hdr.name, store->address, store->SDport); - if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) { - bsendmsg(ua, _("Failed to connect to Storage daemon.\n")); + if (!(sd=open_sd_bsock(ua))) { return NULL; } - sd = ua->jcr->store_bsock; bstrncpy(dev_name, store->dev_name, sizeof(dev_name)); bash_spaces(dev_name); @@ -515,25 +704,46 @@ static vol_list_t *get_slot_list_from_SD(UAContext *ua) continue; } - /* Validate Slot:Barcode */ + /* Validate Slot: if scanning, otherwise Slot:Barcode */ p = strchr(sd->msg, ':'); - if (p && strlen(p) > 1) { - *p++ = 0; - if (!is_an_integer(sd->msg)) { + if (scan && p) { + /* Scanning -- require only valid slot */ + Slot = atoi(sd->msg); + if (Slot <= 0) { + p--; + *p = ':'; + bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); continue; } } else { - continue; - } - Slot = atoi(sd->msg); - if (Slot <= 0 || !is_volume_name_legal(ua, p)) { - continue; + /* Not scanning */ + if (p && strlen(p) > 1) { + *p++ = 0; + if (!is_an_integer(sd->msg) || (Slot=atoi(sd->msg)) <= 0) { + p--; + *p = ':'; + bsendmsg(ua, _("Invalid Slot number: %s\n"), sd->msg); + continue; + } + } else { + continue; + } + if (!is_volume_name_legal(ua, p)) { + p--; + *p = ':'; + bsendmsg(ua, _("Invalid Volume name: %s\n"), sd->msg); + continue; + } } /* Add Slot and VolumeName to list */ vl = (vol_list_t *)malloc(sizeof(vol_list_t)); vl->Slot = Slot; - vl->VolName = bstrdup(p); + if (p) { + vl->VolName = bstrdup(p); + } else { + vl->VolName = NULL; + } if (!vol_list) { vl->next = vol_list; vol_list = vl; @@ -548,9 +758,26 @@ static vol_list_t *get_slot_list_from_SD(UAContext *ua) } } } + close_sd_bsock(ua); return vol_list; } +static void free_vol_list(vol_list_t *vol_list) +{ + vol_list_t *vl; + /* Free list */ + for (vl=vol_list; vl; ) { + vol_list_t *ovl; + if (vl->VolName) { + free(vl->VolName); + } + ovl = vl; + vl = vl->next; + free(ovl); + } +} + + /* * Check if this is a cleaning tape by comparing the Volume name * with the Cleaning Prefix. If they match, this is a cleaning @@ -569,6 +796,11 @@ static int is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr) if (ua->jcr->pool->cleaning_prefix == NULL) { return 0; } + Dmsg4(200, "CLNprefix=%s: Vol=%s: len=%d strncmp=%d\n", + ua->jcr->pool->cleaning_prefix, mr->VolumeName, + strlen(ua->jcr->pool->cleaning_prefix), + strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix, + strlen(ua->jcr->pool->cleaning_prefix))); return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix, strlen(ua->jcr->pool->cleaning_prefix)) == 0; }