Imported Upstream version 2.5.1p3
[debian/amanda] / server-src / amtape.c
index 9c0f7f5a960e969aa64495335cbf0948b7e160bf..8f3cee1a4839292b229b4b8e4117f3358a99a201 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: amtape.c,v 1.22.2.6.4.5.2.4 2003/11/25 12:21:08 martinea Exp $
+ * $Id: amtape.c,v 1.47.2.2 2006/10/30 12:00:19 martinea Exp $
  *
  * tape changer interface program
  */
 #include "amanda.h"
 #include "conffile.h"
 #include "tapefile.h"
+#include "taperscan.h"
 #include "tapeio.h"
 #include "clock.h"
 #include "changer.h"
 #include "version.h"
 
 /* local functions */
-void usage P((void));
-int main P((int argc, char **argv));
-void reset_changer P((int argc, char **argv));
-void eject_tape P((int argc, char **argv));
-void clean_tape P((int argc, char **argv));
-void load_slot P((int argc, char **argv));
-void load_label P((int argc, char **argv));
-void show_slots P((int argc, char **argv));
-void show_current P((int argc, char **argv));
-void taper_scan P((int argc, char **argv));
-void show_device P((int argc, char **argv));
-int scan_init P((int rc, int ns, int bk));
-int loadlabel_slot P((int rc, char *slotstr, char *device));
-int show_init P((int rc, int ns, int bk));
-int show_init_all P((int rc, int ns, int bk));
-int show_init_current P((int rc, int ns, int bk));
-int show_slot P((int rc, char *slotstr, char *device));
-int taperscan_slot P((int rc, char *slotstr, char *device));
-int update_one_slot P((int rc, char *slotstr, char *device));
-void update_labeldb P((int argc, char **argv));
-
-void usage()
+void usage(void);
+int main(int argc, char **argv);
+void reset_changer(int argc, char **argv);
+void eject_tape(int argc, char **argv);
+void clean_tape(int argc, char **argv);
+void load_slot(int argc, char **argv);
+void load_label(int argc, char **argv);
+void show_slots(int argc, char **argv);
+void show_current(int argc, char **argv);
+void update_labeldb (int argc, char **argv);
+void amtape_taper_scan(int argc, char **argv);
+void show_device(int argc, char **argv);
+int update_one_slot (void *ud, int rc, char *slotstr, char *device);
+int loadlabel_slot(void *ud, int rc, char *slotstr, char *device);
+int show_init(void *ud, int rc, int ns, int bk, int s);
+int show_init_all(void *ud, int rc, int ns, int bk, int s);
+int show_init_current(void *ud, int rc, int ns, int bk, int s);
+int show_slot(void *ud, int rc, char *slotstr, char *device);
+
+static const struct {
+    const char *name;
+    void (*fn)(int, char **);
+    const char *usage;
+} cmdtab[] = {
+    { "reset", reset_changer,
+       "reset                Reset changer to known state" },
+    { "eject", eject_tape,
+       "eject                Eject current tape from drive" },
+    { "clean", clean_tape,
+       "clean                Clean the drive" },
+    { "show", show_slots,
+       "show                 Show contents of all slots" },
+    { "current", show_current,
+       "current              Show contents of current slot" },
+    { "slot" , load_slot,
+       "slot <slot #>        load tape from slot <slot #>" },
+    { "slot" , load_slot,
+       "slot current         load tape from current slot" },
+    { "slot" , load_slot,
+       "slot prev            load tape from previous slot" },
+    { "slot" , load_slot,
+       "slot next            load tape from next slot" },
+    { "slot" , load_slot,
+       "slot advance         advance to next slot but do not load" },
+    { "slot" , load_slot,
+       "slot first           load tape from first slot" },
+    { "slot" , load_slot,
+       "slot last            load tape from last slot" },
+    { "label", load_label,
+       "label <label>        find and load labeled tape" },
+    { "taper", amtape_taper_scan,
+       "taper                perform taper's scan alg." },
+    { "device", show_device,
+       "device               show current tape device" },
+    { "update", update_labeldb,
+       "update               update the label matchingdatabase"},
+};
+#define        NCMDS   (int)(sizeof(cmdtab) / sizeof(cmdtab[0]))
+
+void
+usage(void)
 {
-    fprintf(stderr, "Usage: amtape%s <conf> <command>\n", versionsuffix());
-    fprintf(stderr, "\tValid commands are:\n");
-    fprintf(stderr, "\t\treset                Reset changer to known state\n");
-    fprintf(stderr, "\t\teject                Eject current tape from drive\n");
-    fprintf(stderr, "\t\tclean                Clean the drive\n");
-    fprintf(stderr, "\t\tshow                 Show contents of all slots\n");
-    fprintf(stderr, "\t\tcurrent              Show contents of current slot\n");
-    fprintf(stderr, "\t\tslot <slot #>        load tape from slot <slot #>\n");
-    fprintf(stderr, "\t\tslot current         load tape from current slot\n");
-    fprintf(stderr, "\t\tslot prev            load tape from previous slot\n");
-    fprintf(stderr, "\t\tslot next            load tape from next slot\n");
-    fprintf(stderr, "\t\tslot advance         advance to next slot but do not load\n");
-    fprintf(stderr, "\t\tslot first           load tape from first slot\n");
-    fprintf(stderr, "\t\tslot last            load tape from last slot\n");
-    fprintf(stderr, "\t\tlabel <label>        find and load labeled tape\n");
-    fprintf(stderr, "\t\ttaper                perform taper's scan alg.\n");
-    fprintf(stderr, "\t\tdevice               show current tape device\n");
-    fprintf(stderr, "\t\tupdate               update the label matchingdatabase\n");
+    int i;
 
+    fprintf(stderr, "Usage: amtape%s <conf> <command> {<args>} [-o configoption]*\n", versionsuffix());
+    fprintf(stderr, "\tValid commands are:\n");
+    for (i = 0; i < NCMDS; i++)
+       fprintf(stderr, "\t\t%s\n", cmdtab[i].usage);
     exit(1);
 }
 
-int main(argc, argv)
-int argc;
-char **argv;
+int
+main(
+    int                argc,
+    char **    argv)
 {
     char *conffile;
     char *conf_tapelist;
     char *argv0 = argv[0];
     unsigned long malloc_hist_1, malloc_size_1;
     unsigned long malloc_hist_2, malloc_size_2;
-    int fd;
+    int i;
     int have_changer;
     uid_t uid_me;
     uid_t uid_dumpuser;
     char *dumpuser;
     struct passwd *pw;
+    int new_argc;
+    char **new_argv;
 
-    for(fd = 3; fd < FD_SETSIZE; fd++) {
-       /*
-        * Make sure nobody spoofs us with a lot of extra open files
-        * that would cause an open we do to get a very high file
-        * descriptor, which in turn might be used as an index into
-        * an array (e.g. an fd_set).
-        */
-       close(fd);
-    }
-
+    safe_fd(-1, 0);
     safe_cd();
 
     set_pname("amtape");
-    dbopen();
+
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+    dbopen(DBG_SUBDIR_SERVER);
 
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
     erroutput_type = ERR_INTERACTIVE;
 
-    if(argc < 3) usage();
+    parse_server_conf(argc, argv, &new_argc, &new_argv);
+    if(new_argc < 3) usage();
 
-    config_name = argv[1];
+    config_name = new_argv[1];
 
     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
     conffile = stralloc2(config_dir, CONFFILE_NAME);
     if (read_conffile(conffile)) {
        error("errors processing config file \"%s\"", conffile);
+       /*NOTREACHED*/
     }
+
+    dbrename(config_name, DBG_SUBDIR_SERVER);
+
     conf_tapelist = getconf_str(CNF_TAPELIST);
     if (*conf_tapelist == '/') {
        conf_tapelist = stralloc(conf_tapelist);
@@ -134,6 +164,7 @@ char **argv;
     }
     if (read_tapelist(conf_tapelist)) {
        error("could not load tapelist \"%s\"", conf_tapelist);
+       /*NOTREACHED*/
     }
     amfree(conf_tapelist);
 
@@ -143,40 +174,37 @@ char **argv;
 
     if ((pw = getpwnam(dumpuser)) == NULL) {
        error("cannot look up dump user \"%s\"", dumpuser);
-       /* NOTREACHED */
+       /*NOTREACHED*/
     }
     uid_dumpuser = pw->pw_uid;
     if ((pw = getpwuid(uid_me)) == NULL) {
        error("cannot look up my own uid %ld", (long)uid_me);
-       /* NOTREACHED */
+       /*NOTREACHED*/
     }
     if (uid_me != uid_dumpuser) {
        error("running as user \"%s\" instead of \"%s\"",
              pw->pw_name, dumpuser);
-       /* NOTREACHED */
+       /*NOTREACHED*/
     }
 
     if((have_changer = changer_init()) == 0) {
        error("no tpchanger specified in \"%s\"", conffile);
+       /*NOTREACHED*/
     } else if (have_changer != 1) {
        error("changer initialization failed: %s", strerror(errno));
+       /*NOTREACHED*/
     }
 
     /* switch on command name */
 
-    argc -= 2; argv += 2;
-    if(strcmp(argv[0], "reset") == 0) reset_changer(argc, argv);
-    else if(strcmp(argv[0], "clean") == 0) clean_tape(argc, argv);
-    else if(strcmp(argv[0], "eject") == 0) eject_tape(argc, argv);
-    else if(strcmp(argv[0], "slot") == 0) load_slot(argc, argv);
-    else if(strcmp(argv[0], "label") == 0) load_label(argc, argv);
-    else if(strcmp(argv[0], "current") == 0)  show_current(argc, argv);
-    else if(strcmp(argv[0], "show") == 0)  show_slots(argc, argv);
-    else if(strcmp(argv[0], "taper") == 0) taper_scan(argc, argv);
-    else if(strcmp(argv[0], "device") == 0) show_device(argc, argv);
-    else if(strcmp(argv[0], "update") == 0) update_labeldb(argc, argv);
-    else {
-       fprintf(stderr, "%s: unknown command \"%s\"\n", argv0, argv[0]);
+    new_argc -= 2; new_argv += 2;
+    for (i = 0; i < NCMDS; i++)
+       if (strcmp(new_argv[0], cmdtab[i].name) == 0) {
+           (*cmdtab[i].fn)(new_argc, new_argv);
+           break;
+       }
+    if (i == NCMDS) {
+       fprintf(stderr, "%s: unknown command \"%s\"\n", argv0, new_argv[0]);
        usage();
     }
 
@@ -196,12 +224,16 @@ char **argv;
 
 /* ---------------------------- */
 
-void reset_changer(argc, argv)
-int argc;
-char **argv;
+void
+reset_changer(
+    int                argc,
+    char **    argv)
 {
     char *slotstr = NULL;
 
+    (void)argc;        /* Quiet unused parameter warning */
+    (void)argv;        /* Quiet unused parameter warning */
+
     switch(changer_reset(&slotstr)) {
     case 0:
        fprintf(stderr, "%s: changer is reset, slot %s is loaded.\n",
@@ -213,18 +245,23 @@ char **argv;
        break;
     default:
        error("could not reset changer: %s", changer_resultstr);
+       /*NOTREACHED*/
     }
     amfree(slotstr);
 }
 
 
 /* ---------------------------- */
-void clean_tape(argc, argv)
-int argc;
-char **argv;
+void
+clean_tape(
+    int                argc,
+    char **    argv)
 {
     char *devstr = NULL;
 
+    (void)argc;        /* Quiet unused parameter warning */
+    (void)argv;        /* Quiet unused parameter warning */
+
     if(changer_clean(&devstr) == 0) {
        fprintf(stderr, "%s: device %s is clean.\n", get_pname(), devstr);
     } else {
@@ -236,12 +273,16 @@ char **argv;
 
 
 /* ---------------------------- */
-void eject_tape(argc, argv)
-int argc;
-char **argv;
+void
+eject_tape(
+    int                argc,
+    char **    argv)
 {
     char *slotstr = NULL;
 
+    (void)argc;        /* Quiet unused parameter warning */
+    (void)argv;        /* Quiet unused parameter warning */
+
     if(changer_eject(&slotstr) == 0) {
        fprintf(stderr, "%s: slot %s is ejected.\n", get_pname(), slotstr);
     } else {
@@ -254,9 +295,10 @@ char **argv;
 
 /* ---------------------------- */
 
-void load_slot(argc, argv)
-int argc;
-char **argv;
+void
+load_slot(
+    int                argc,
+    char **    argv)
 {
     char *slotstr = NULL, *devicename = NULL;
     char *errstr;
@@ -268,6 +310,7 @@ char **argv;
     is_advance = (strcmp(argv[1], "advance") == 0);
     if(changer_loadslot(argv[1], &slotstr, &devicename)) {
        error("could not load slot %s: %s", slotstr, changer_resultstr);
+       /*NOTREACHED*/
     }
     if(! is_advance && (errstr = tape_rewind(devicename)) != NULL) {
        fprintf(stderr,
@@ -292,12 +335,23 @@ char *datestamp;
 char *label = NULL, *first_match_label = NULL, *first_match = NULL;
 char *searchlabel, *labelstr;
 tape_t *tp;
-
-int scan_init(rc, ns, bk)
-int rc, ns, bk;
+static int scan_init(void *ud, int rc, int ns, int bk, int s);
+
+static int 
+scan_init(
+    void *     ud,
+    int                rc,
+    int                ns,
+    int                bk,
+    int                s)
 {
-    if(rc)
+    (void)ud;  /* Quiet unused parameter warning */
+    (void)s;   /* Quiet unused parameter warning */
+
+    if(rc) {
        error("could not get changer info: %s", changer_resultstr);
+       /*NOTREACHED*/
+    }
 
     nslots = ns;
     backwards = bk;
@@ -305,15 +359,21 @@ int rc, ns, bk;
     return 0;
 }
 
-int loadlabel_slot(rc, slotstr, device)
-int rc;
-char *slotstr;
-char *device;
+int
+loadlabel_slot(
+    void *     ud,
+    int                rc,
+    char *     slotstr,
+    char *     device)
 {
     char *errstr;
 
-    if(rc > 1)
+    (void)ud;  /* Quiet unused parameter warning */
+
+    if(rc > 1) {
        error("could not load slot %s: %s", slotstr, changer_resultstr);
+       /*NOTREACHED*/
+    }
     else if(rc == 1)
        fprintf(stderr, "%s: slot %s: %s\n",
                get_pname(), slotstr, changer_resultstr);
@@ -344,9 +404,10 @@ char *device;
     return 0;
 }
 
-void load_label(argc, argv)
-int argc;
-char **argv;
+void
+load_label(
+    int                argc,
+    char **    argv)
 {
     if(argc != 2)
        usage();
@@ -358,7 +419,7 @@ char **argv;
 
     found = 0;
 
-    changer_find(scan_init, loadlabel_slot, searchlabel);
+    changer_find(NULL, scan_init, loadlabel_slot, searchlabel);
 
     if(found)
        fprintf(stderr, "%s: label %s is now loaded.\n",
@@ -371,70 +432,83 @@ char **argv;
 
 /* ---------------------------- */
 
-int show_init(rc, ns, bk)
-int rc, ns, bk;
+int
+show_init(
+    void *     ud,
+    int                rc,
+    int                ns,
+    int                bk,
+    int                s)
 {
-    if(rc)
+    (void)ud;  /* Quiet unused parameter warning */
+    (void)s;   /* Quiet unused parameter warning */
+
+    if(rc) {
        error("could not get changer info: %s", changer_resultstr);
+       /*NOTREACHED*/
+    }
 
     nslots = ns;
     backwards = bk;
     return 0;
 }
 
-int show_init_all(rc, ns, bk)
-int rc, ns, bk;
+int
+show_init_all(
+    void *     ud,
+    int                rc,
+    int                ns,
+    int                bk,
+    int                s)
 {
-    int ret = show_init(rc, ns, bk);
+    int ret = show_init(NULL, rc, ns, bk, s);
+
+    (void)ud;  /* Quiet unused parameter warning */
+
     fprintf(stderr, "%s: scanning all %d slots in tape-changer rack:\n",
            get_pname(), nslots);
     return ret;
 }
 
-int show_init_current(rc, ns, bk)
-int rc, ns, bk;
+int
+show_init_current(
+    void *     ud,
+    int                rc,
+    int                ns,
+    int                bk,
+    int                s)
 {
-    int ret = show_init(rc, ns, bk);
+    int ret = show_init(NULL, rc, ns, bk, s);
+
+    (void)ud;  /* Quiet unused parameter warning */
+
     fprintf(stderr, "%s: scanning current slot in tape-changer rack:\n",
            get_pname());
     return ret;
 }
 
-int update_one_slot(rc, slotstr, device)
-int rc;
-char *slotstr, *device;
+int
+show_slot(
+    void *     ud,
+    int                rc,
+    char *     slotstr,
+    char *     device)
 {
     char *errstr;
 
-    if(rc > 1)
-       error("could not load slot %s: %s", slotstr, changer_resultstr);
-    else if(rc == 1)
-       fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
-    else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
-       fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
-    else {
-       fprintf(stderr, "slot %s: date %-8s label %s\n",
-               slotstr, datestamp, label);
-       changer_label(slotstr,label);
-    }
-    amfree(datestamp);
-    amfree(label);
-    return 0;
-}
-
-int show_slot(rc, slotstr, device)
-int rc;
-char *slotstr, *device;
-{
-    char *errstr;
+    (void)ud;  /* Quiet unused parameter warning */
 
-    if(rc > 1)
+    if(rc > 1) {
        error("could not load slot %s: %s", slotstr, changer_resultstr);
-    else if(rc == 1)
+       /*NOTREACHED*/
+    }
+    else if(rc == 1) {
        fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
-    else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
+    }
+    else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
        fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
-    else {
+       amfree(errstr);
+    } else {
        fprintf(stderr, "slot %s: date %-8s label %s\n",
                slotstr, datestamp, label);
     }
@@ -443,115 +517,45 @@ char *slotstr, *device;
     return 0;
 }
 
-void show_current(argc, argv)
-int argc;
-char **argv;
+void
+show_current(
+    int                argc,
+    char **    argv)
 {
-    if(argc != 1)
-       usage();
-
-    changer_current(show_init_current, show_slot);
-}
+    (void)argv;        /* Quiet unused parameter warning */
 
-void update_labeldb(argc, argv)
-int argc;
-char **argv;
-{
     if(argc != 1)
        usage();
 
-    changer_scan(show_init_all, update_one_slot);
+    changer_current(NULL, show_init_current, show_slot);
 }
 
-void show_slots(argc, argv)
-int argc;
-char **argv;
+void
+show_slots(
+    int                argc,
+    char **    argv)
 {
+    (void)argv;        /* Quiet unused parameter warning */
+
     if(argc != 1)
        usage();
 
-    changer_scan(show_init_all, show_slot);
+    changer_find(NULL, show_init_all, show_slot, NULL);
 }
 
 
 /* ---------------------------- */
 
-int taperscan_slot(rc, slotstr, device)
-int rc;
-char *slotstr;
-char *device;
+void
+amtape_taper_scan(
+    int                argc,
+    char **    argv)
 {
-    char *errstr;
-
-    if(rc == 2)
-       error("could not load slot %s: %s", slotstr, changer_resultstr);
-    else if(rc == 1)
-       fprintf(stderr, "%s: slot %s: %s\n",
-               get_pname(), slotstr, changer_resultstr);
-    else {
-       if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
-           fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
-       } else {
-           /* got an amanda tape */
-           fprintf(stderr, "%s: slot %s: date %-8s label %s",
-                   get_pname(), slotstr, datestamp, label);
-           if(searchlabel != NULL
-              && (strcmp(label, FAKE_LABEL) == 0
-                  || strcmp(label, searchlabel) == 0)) {
-               /* it's the one we are looking for, stop here */
-               fprintf(stderr, " (exact label match)\n");
-               found = 1;
-               amfree(datestamp);
-               amfree(label);
-               return 1;
-           }
-           else if(!match(labelstr, label))
-               fprintf(stderr, " (no match)\n");
-           else {
-               /* not an exact label match, but a labelstr match */
-               /* check against tape list */
-               tp = lookup_tapelabel(label);
-               if(tp == NULL)
-                   fprintf(stderr, " (not in tapelist)\n");
-               else if(!reusable_tape(tp))
-                   fprintf(stderr, " (active tape)\n");
-               else if(got_match == 0 && tp->datestamp == 0) {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(stderr, " (new tape)\n");
-                   found = 3;
-                   amfree(datestamp);
-                   amfree(label);
-                   return 1;
-               }
-               else if(got_match)
-                   fprintf(stderr, " (labelstr match)\n");
-               else {
-                   got_match = 1;
-                   first_match = newstralloc(first_match, slotstr);
-                   first_match_label = newstralloc(first_match_label, label);
-                   fprintf(stderr, " (first labelstr match)\n");
-                   if(!backwards || !searchlabel) {
-                       found = 2;
-                       amfree(datestamp);
-                       amfree(label);
-                       return 1;
-                   }
-               }
-           }
-       }
-    }
-    amfree(datestamp);
-    amfree(label);
-    return 0;
-}
+    char *device = NULL;
+    char *label = NULL;
 
-void taper_scan(argc, argv)
-int argc;
-char **argv;
-{
-    char *slotstr = NULL, *device = NULL;
+    (void)argc;        /* Quiet unused parameter warning */
+    (void)argv;        /* Quiet unused parameter warning */
 
     if((tp = lookup_last_reusable_tape(0)) == NULL)
        searchlabel = NULL;
@@ -567,62 +571,79 @@ char **argv;
     if(searchlabel) fprintf(stderr, "tape label %s or ", searchlabel);
     fprintf(stderr, "a new tape.\n");
 
-    if (searchlabel != NULL)
-      changer_find(scan_init, taperscan_slot, searchlabel);
-    else
-      changer_scan(scan_init, taperscan_slot);
+    taper_scan(searchlabel, &label, &datestamp,&device, FILE_taperscan_output_callback, stderr);
 
-    if(found == 3) {
-       fprintf(stderr, "%s: settling for new tape\n", get_pname());
-       searchlabel = newstralloc(searchlabel, first_match_label);
-    }
-    else if(found == 2) {
-       fprintf(stderr, "%s: %s: settling for first labelstr match\n",
-               get_pname(),
-               searchlabel? "gravity stacker": "looking only for new tape");
-       searchlabel = newstralloc(searchlabel, first_match_label);
-    }
-    else if(!found && got_match) {
-       fprintf(stderr,
-               "%s: %s not found, going back to first labelstr match %s\n",
-               get_pname(), searchlabel, first_match_label);
-       searchlabel = newstralloc(searchlabel, first_match_label);
-       if(changer_loadslot(first_match, &slotstr, &device) == 0) {
-           found = 1;
-       } else {
-           fprintf(stderr, "%s: could not load labelstr match in slot %s: %s\n",
-                   get_pname(), first_match, changer_resultstr);
-       }
-       amfree(device);
-       amfree(slotstr);
-    }
-    else if(!found) {
-       fprintf(stderr, "%s: could not find ", get_pname());
-       if(searchlabel) fprintf(stderr, "tape %s or ", searchlabel);
-       fprintf(stderr, "a new tape in the tape rack.\n");
-    }
+    fprintf(stderr, "%s: label %s is now loaded.\n",
+            get_pname(), label);
 
-    if(found)
-       fprintf(stderr, "%s: label %s is now loaded.\n",
-               get_pname(), searchlabel);
-
-    amfree(searchlabel);
-    amfree(first_match);
-    amfree(first_match_label);
+    amfree(label);
+    amfree(datestamp);
+    amfree(device);
 }
 
 /* ---------------------------- */
 
-void show_device(argc, argv)
-int argc;
-char **argv;
+void
+show_device(
+    int                argc,
+    char **    argv)
 {
     char *slot = NULL, *device = NULL;
 
-    if(changer_loadslot("current", &slot, &device))
+    (void)argc;        /* Quiet unused parameter warning */
+    (void)argv;        /* Quiet unused parameter warning */
+
+    if(changer_loadslot("current", &slot, &device)) {
        error("Could not load current slot.\n");
+       /*NOTREACHED*/
+    }
 
     printf("%s\n", device);
     amfree(slot);
     amfree(device);
 }
+
+/* ---------------------------- */
+
+int
+update_one_slot(
+    void *     ud,
+    int                rc,
+    char *     slotstr,
+    char *     device)
+{
+    char *errstr = NULL;
+    char *datestamp = NULL;
+    char *label = NULL;
+
+    (void)ud;  /* Quiet unused parameter warning */
+
+    if(rc > 1)
+       error("could not load slot %s: %s", slotstr, changer_resultstr);
+    else if(rc == 1)
+       fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
+    else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
+       fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
+    else {
+       fprintf(stderr, "slot %s: date %-8s label %s\n",
+               slotstr, datestamp, label);
+       changer_label(slotstr, label);
+    }
+    amfree(errstr);
+    amfree(datestamp);
+    amfree(label);
+    return 0;
+}
+
+void
+update_labeldb(
+    int                argc,
+    char **    argv)
+{
+    (void)argv;        /* Quiet unused parameter warning */
+
+    if(argc != 1)
+       usage();
+
+    changer_find(NULL, show_init_all, update_one_slot, NULL);
+}