]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_label.c
Fix couple of g++ warnings
[bacula/bacula] / bacula / src / dird / ua_label.c
index 077675c01b7b0d9c7fdf80d158623fb4b64b78bf..df9578fd55a04c31961e767cb15e6292dc0e9184 100644 (file)
@@ -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.
 
    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.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of Kern Sibbald.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
@@ -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;
@@ -154,6 +157,7 @@ static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots)
    return true;
 
 bail_out:
+   Dmsg1(100, "Problem with user selection ERR=%s\n", msg);
    return false;
 }
 
@@ -535,7 +539,7 @@ static void label_from_barcodes(UAContext *ua, int drive)
       }
       ua->send_msg("%4d  %s\n", vl->Slot, vl->VolName);
    }
-   if (!get_yesno(ua, _("Do you want to continue? (yes|no): ")) ||
+   if (!get_yesno(ua, _("Do you want to label these Volumes? (yes|no): ")) ||
        (ua->pint32_val == 0)) {
       goto bail_out;
    }
@@ -678,14 +682,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 +699,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 +791,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 +897,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 +960,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 +992,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 +1006,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
@@ -1015,3 +1031,284 @@ static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr)
    return strncmp(mr->VolumeName, ua->jcr->pool->cleaning_prefix,
                   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
+ */
+void status_slots(UAContext *ua, STORE *store_r)
+{
+   USTORE store;
+   POOL_DBR pr;
+   vol_list_t *vl, *vol_list = NULL;
+   MEDIA_DBR mr;
+   char *slot_list;
+   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;
+   }
+   store.store = store_r;
+
+   pm_strcpy(store.store_source, _("command line"));
+   set_wstorage(ua->jcr, &store);
+   drive = get_storage_drive(ua, store.store);
+
+   max_slots = get_num_slots_from_SD(ua);
+
+   if (max_slots <= 0) {
+      ua->warning_msg(_("No slots in changer to scan.\n"));
+      return;
+   }
+   slot_list = (char *)malloc(max_slots+1);
+   if (!get_user_slot_list(ua, slot_list, max_slots)) {
+      free(slot_list);
+      return;
+   }
+
+   vol_list = get_vol_list_from_SD(ua, true /* want to see all slots */);
+
+   if (!vol_list) {
+      ua->warning_msg(_("No Volumes found, or no barcodes.\n"));
+      goto bail_out;
+   }
+   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) {
+         ua->warning_msg(_("Slot %d greater than max %d ignored.\n"),
+            vl->Slot, max_slots);
+         continue;
+      }
+      /* Check if user wants us to look at this slot */
+      if (!slot_list[vl->Slot]) {
+         Dmsg1(100, "Skipping slot=%d\n", vl->Slot);
+         continue;
+      }
+
+      slot_list[vl->Slot] = 0;        /* clear Slot */
+
+      if (!vl->VolName) {
+         Dmsg1(100, "No VolName for Slot=%d.\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]) {
+            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, "?");
+         }
+         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->send_msg(slot_hformat,
+                      vl->Slot, '*',
+                      mr.VolumeName, "?", "?", "?");
+      }
+      db_unlock(ua->db);
+   }
+
+   /* Display the rest of the autochanger
+    */
+   for (; i <= max_slots; i++) {
+      if (slot_list[i]) {
+         ua->send_msg(slot_hformat,
+                      i, ' ', "", "", "", "");
+         slot_list[i]=0;
+      }
+   }
+
+bail_out:
+
+   free_vol_list(vol_list);
+   free(slot_list);
+   close_sd_bsock(ua);
+
+   return;
+}