X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fua_label.c;h=319a8e7a95abd0b1f03f952a8dc40fb83501e83c;hb=c5f4a68937116a768e6d85bc576a5fd41a56e93a;hp=b14452d55dc6554441a6f3f0676476a1a2abbfd7;hpb=908d0c5a7c352c4473409fd01cab16d968c41b43;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index b14452d55d..319a8e7a95 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -1,12 +1,12 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2003-2007 Free Software Foundation Europe e.V. + Copyright (C) 2003-2008 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. This program is Free Software; you can redistribute it and/or - modify it under the terms of version two of the GNU General Public + modify it under the terms of version three of the GNU Affero General Public License as published by the Free Software Foundation and included in the file LICENSE. @@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Affero General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -84,6 +84,9 @@ static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots) slot_list[i] = 0; } i = find_arg_with_value(ua, "slots"); + if (i == -1) { /* not found */ + i = find_arg_with_value(ua, "slot"); + } if (i > 0) { /* scan slot list in ua->argv[i] */ char *p, *e, *h; @@ -678,14 +681,14 @@ static bool 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 " + sd->fsend("relabel %s OldName=%s NewName=%s PoolName=%s " "MediaType=%s Slot=%d drive=%d", dev_name, omr->VolumeName, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive); ua->send_msg(_("Sending relabel command from \"%s\" to \"%s\" ...\n"), omr->VolumeName, mr->VolumeName); } else { - bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s " + sd->fsend("label %s VolumeName=%s PoolName=%s MediaType=%s " "Slot=%d drive=%d", dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive); @@ -695,7 +698,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr, dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive); } - while (bnet_recv(sd) >= 0) { + while (sd->recv() >= 0) { int dvd; ua->send_msg("%s", sd->msg); if (sscanf(sd->msg, "3000 OK label. VolBytes=%llu DVD=%d ", &VolBytes, @@ -787,11 +790,11 @@ static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive) bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger list of volumes */ - bnet_fsend(sd, NT_("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive); + sd->fsend(NT_("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive); Dmsg1(100, "Sent: %s", sd->msg); /* Get Volume name in this Slot */ - while (bnet_recv(sd) >= 0) { + while (sd->recv() >= 0) { ua->send_msg("%s", sd->msg); Dmsg1(100, "Got: %s", sd->msg); if (strncmp(sd->msg, NT_("3001 Volume="), 12) == 0) { @@ -893,13 +896,28 @@ static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan) vl->next = vol_list; vol_list = vl; } else { - /* Add new entry to end of list */ + vol_list_t *prev=vol_list; + /* Add new entry to the right place in the list */ for (vol_list_t *tvl=vol_list; tvl; tvl=tvl->next) { + if (tvl->Slot > vl->Slot) { + /* no previous item, update vol_list directly */ + if (prev == vol_list) { + vl->next = vol_list; + vol_list = vl; + + } else { /* replace the previous pointer */ + prev->next = vl; + vl->next = tvl; + } + break; + } + /* we are at the end */ if (!tvl->next) { tvl->next = vl; vl->next = NULL; break; } + prev = tvl; } } } @@ -941,9 +959,9 @@ static int get_num_slots_from_SD(UAContext *ua) bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger number of slots */ - bnet_fsend(sd, NT_("autochanger slots %s\n"), dev_name); + sd->fsend(NT_("autochanger slots %s\n"), dev_name); - while (bnet_recv(sd) >= 0) { + while (sd->recv() >= 0) { if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) { break; } else { @@ -973,9 +991,9 @@ int get_num_drives_from_SD(UAContext *ua) bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger number of slots */ - bnet_fsend(sd, NT_("autochanger drives %s\n"), dev_name); + sd->fsend(NT_("autochanger drives %s\n"), dev_name); - while (bnet_recv(sd) >= 0) { + while (sd->recv() >= 0) { if (sscanf(sd->msg, NT_("drives=%d\n"), &drives) == 1) { break; } else { @@ -987,9 +1005,6 @@ int get_num_drives_from_SD(UAContext *ua) return drives; } - - - /* * Check if this is a cleaning tape by comparing the Volume name * with the Cleaning Prefix. If they match, this is a cleaning @@ -1016,6 +1031,160 @@ static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr) strlen(ua->jcr->pool->cleaning_prefix)) == 0; } +static void content_send_info(UAContext *ua, char type, int Slot, char *vol_name) +{ + char ed1[50], ed2[50], ed3[50]; + POOL_DBR pr; + MEDIA_DBR mr; + /* Type|Slot|RealSlot|Volume|Bytes|Status|MediaType|Pool|LastW|Expire */ + const char *slot_api_full_format="%c|%i|%i|%s|%s|%s|%s|%s|%s|%s\n"; + const char *slot_api_empty_format="%c|%i||||||||\n"; + + if (is_volume_name_legal(NULL, vol_name)) { + memset(&mr, 0, sizeof(mr)); + bstrncpy(mr.VolumeName, vol_name, sizeof(mr.VolumeName)); + if (db_get_media_record(ua->jcr, ua->db, &mr)) { + memset(&pr, 0, sizeof(POOL_DBR)); + pr.PoolId = mr.PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { + strcpy(pr.Name, "?"); + } + ua->send_msg(slot_api_full_format, type, + Slot, mr.Slot, mr.VolumeName, + edit_uint64(mr.VolBytes, ed1), + mr.VolStatus, mr.MediaType, pr.Name, + edit_uint64(mr.LastWritten, ed2), + edit_uint64(mr.LastWritten+mr.VolRetention, ed3)); + + } else { /* Media unknown */ + ua->send_msg(slot_api_full_format, + type, Slot, 0, mr.VolumeName, "?", "?", "?", "?", + "0", "0"); + + } + } else { + ua->send_msg(slot_api_empty_format, type, Slot); + } +} + +/* + * Input (output of mxt-changer listall): + * + * Drive content: D:Drive num:F:Slot loaded:Volume Name + * D:0:F:2:vol2 or D:Drive num:E + * D:1:F:42:vol42 + * D:3:E + * + * Slot content: + * S:1:F:vol1 S:Slot num:F:Volume Name + * S:2:E or S:Slot num:E + * S:3:F:vol4 + * + * Import/Export tray slots: + * I:10:F:vol10 I:Slot num:F:Volume Name + * I:11:E or I:Slot num:E + * I:12:F:vol40 + * + * If a drive is loaded, the slot *should* be empty + * + * Output: + * + * Drive list: D|Drive num|Slot loaded|Volume Name + * D|0|45|vol45 + * D|1|42|vol42 + * D|3|| + * + * Slot list: Type|Slot|RealSlot|Volume|Bytes|Status|MediaType|Pool|LastW|Expire + * + * S|1|1|vol1|31417344|Full|LTO1-ANSI|Inc|1250858902|1282394902 + * S|2|||||||| + * S|3|3|vol4|15869952|Append|LTO1-ANSI|Inc|1250858907|1282394907 + * + * TODO: need to merge with status_slots() + */ +void status_content(UAContext *ua, STORE *store) +{ + int Slot, Drive; + char type; + char dev_name[MAX_NAME_LENGTH]; + char vol_name[MAX_NAME_LENGTH]; + BSOCK *sd; + vol_list_t *vl=NULL, *vol_list = NULL; + + if (!(sd=open_sd_bsock(ua))) { + return; + } + + if (!open_client_db(ua)) { + return; + } + + bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); + bash_spaces(dev_name); + /* Ask for autochanger list of volumes */ + bnet_fsend(sd, NT_("autochanger listall %s \n"), dev_name); + + /* Read and organize list of Drive, Slots and I/O Slots */ + while (bnet_recv(sd) >= 0) { + strip_trailing_junk(sd->msg); + + /* Check for returned SD messages */ + if (sd->msg[0] == '3' && B_ISDIGIT(sd->msg[1]) && + B_ISDIGIT(sd->msg[2]) && B_ISDIGIT(sd->msg[3]) && + sd->msg[4] == ' ') { + ua->send_msg("%s\n", sd->msg); /* pass them on to user */ + continue; + } + + Drive = Slot = -1; + *vol_name = 0; + + if (sscanf(sd->msg, "D:%d:F:%d:%127s", &Drive, &Slot, vol_name) == 3) { + ua->send_msg("D|%d|%d|%s\n", Drive, Slot, vol_name); + + /* we print information on the slot if we have a volume name */ + if (*vol_name) { + /* Add Slot and VolumeName to list */ + vl = (vol_list_t *)malloc(sizeof(vol_list_t)); + vl->Slot = Slot; + vl->VolName = bstrdup(vol_name); + vl->next = vol_list; + vol_list = vl; + } + + } else if (sscanf(sd->msg, "D:%d:E", &Drive) == 1) { + ua->send_msg("D|%d||\n", Drive); + + } else if (sscanf(sd->msg, "%c:%d:F:%127s", &type, &Slot, vol_name)== 3) { + content_send_info(ua, type, Slot, vol_name); + + } else if (sscanf(sd->msg, "%c:%d:E", &type, &Slot) == 2) { + /* type can be S (slot) or I (Import/Export slot) */ + vol_list_t *prev=NULL; + for (vl = vol_list; vl; vl = vl->next) { + if (vl->Slot == Slot) { + bstrncpy(vol_name, vl->VolName, MAX_NAME_LENGTH); + + /* remove the node */ + if (prev) { + prev->next = vl->next; + } else { + vol_list = vl->next; + } + free(vl->VolName); + free(vl); + break; + } + prev = vl; + } + content_send_info(ua, type, Slot, vol_name); + + } else { + Dmsg1(10, "Discarding msg=%s\n", sd->msg); + } + } + close_sd_bsock(ua); +} /* * Print slots from AutoChanger @@ -1030,6 +1199,13 @@ void status_slots(UAContext *ua, STORE *store_r) int max_slots; int drive; int i=1; + /* Slot | Volume | Status | MediaType | Pool */ + const char *slot_hformat=" %4i%c| %16s | %9s | %20s | %18s |\n"; + + if (ua->api) { + status_content(ua, store_r); + return; + } if (!open_client_db(ua)) { return; @@ -1058,10 +1234,9 @@ void status_slots(UAContext *ua, STORE *store_r) ua->warning_msg(_("No Volumes found, or no barcodes.\n")); goto bail_out; } - if (!ua->api) { - ua->info_msg(_(" Slot | Volume Name | Status | Type | Pool | Loaded |\n")); - ua->info_msg(_("------+------------------+-----------+------------+--------------------+---------|\n")); - } + ua->send_msg(_(" Slot | Volume Name | Status | Media Type | Pool |\n")); + ua->send_msg(_("------+------------------+-----------+----------------------+--------------------|\n")); + /* Walk through the list getting the media records */ for (vl=vol_list; vl; vl=vl->next) { if (vl->Slot > max_slots) { @@ -1079,55 +1254,41 @@ void status_slots(UAContext *ua, STORE *store_r) if (!vl->VolName) { Dmsg1(100, "No VolName for Slot=%d.\n", vl->Slot); - if (!ua->api) { - ua->info_msg(_(" %4i%c| %16s | %9s | %10s | %18s | %i |\n"), - vl->Slot, '*', - "?", "?", "?", "?", 0); - } else { - ua->info_msg(_("%i||||||\n"), vl->Slot); - } + ua->send_msg(slot_hformat, + vl->Slot, '*', + "?", "?", "?", "?"); continue; } /* Hope that slots are ordered */ for (; i < vl->Slot; i++) { - if (slot_list[i]) { - if (!ua->api) { - ua->info_msg(_(" %4i | %16s | %9s | %10s | %18s | %i |\n"), - i, "", "", "", "", 0); - } else { - ua->info_msg(_("%i||||||\n"), i); - } - slot_list[i]=0; - } + if (slot_list[i]) { + ua->send_msg(slot_hformat, + i, ' ', "", "", "", ""); + slot_list[i]=0; + } } memset(&mr, 0, sizeof(mr)); bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); db_lock(ua->db); if (mr.VolumeName[0] && db_get_media_record(ua->jcr, ua->db, &mr)) { - memset(&pr, 0, sizeof(POOL_DBR)); - pr.PoolId = mr.PoolId; - if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { - strcpy(pr.Name, "?"); - } - - if (!ua->api) { - /* Print information */ - ua->info_msg(_(" %4i%c| %16s | %9s | %10s | %18s | %i |\n"), - vl->Slot, ((vl->Slot==mr.Slot)?' ':'*'), - mr.VolumeName, mr.VolStatus, mr.MediaType, pr.Name, 0); - } else { - ua->info_msg(_("%i|%i|%s|%s|%s|%s|%i|\n"), - vl->Slot, mr.Slot, mr.VolumeName, mr.VolStatus, mr.MediaType, pr.Name, 0); - } - + memset(&pr, 0, sizeof(POOL_DBR)); + pr.PoolId = mr.PoolId; + if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { + strcpy(pr.Name, "?"); + } db_unlock(ua->db); + + /* Print information */ + ua->send_msg(slot_hformat, + vl->Slot, ((vl->Slot==mr.Slot)?' ':'*'), + mr.VolumeName, mr.VolStatus, mr.MediaType, pr.Name); continue; - } else { /* TODO: get information from catalog */ - ua->info_msg(_(" %4i%c| %16s | %9s | %10s | %18s | %i |\n"), - vl->Slot, '*', - mr.VolumeName, "?", "?", "?", 0); + } else { /* TODO: get information from catalog */ + ua->send_msg(slot_hformat, + vl->Slot, '*', + mr.VolumeName, "?", "?", "?"); } db_unlock(ua->db); } @@ -1136,13 +1297,9 @@ void status_slots(UAContext *ua, STORE *store_r) */ for (; i <= max_slots; i++) { if (slot_list[i]) { - if (!ua->api) { - ua->info_msg(_(" %4i | %16s | %9s | %10s | %18s | %i |\n"), - i, "", "", "", "", 0); - } else { - ua->info_msg(_("%i||||||\n"), i); - } - slot_list[i]=0; + ua->send_msg(slot_hformat, + i, ' ', "", "", "", ""); + slot_list[i]=0; } }