2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: amtape.c,v 1.22.2.6.4.5.2.4.2.1 2005/09/20 21:31:52 jrjackson Exp $
29 * tape changer interface program
41 int main P((int argc, char **argv));
42 void reset_changer P((int argc, char **argv));
43 void eject_tape P((int argc, char **argv));
44 void clean_tape P((int argc, char **argv));
45 void load_slot P((int argc, char **argv));
46 void load_label P((int argc, char **argv));
47 void show_slots P((int argc, char **argv));
48 void show_current P((int argc, char **argv));
49 void taper_scan P((int argc, char **argv));
50 void show_device P((int argc, char **argv));
51 int scan_init P((int rc, int ns, int bk));
52 int loadlabel_slot P((int rc, char *slotstr, char *device));
53 int show_init P((int rc, int ns, int bk));
54 int show_init_all P((int rc, int ns, int bk));
55 int show_init_current P((int rc, int ns, int bk));
56 int show_slot P((int rc, char *slotstr, char *device));
57 int taperscan_slot P((int rc, char *slotstr, char *device));
58 int update_one_slot P((int rc, char *slotstr, char *device));
59 void update_labeldb P((int argc, char **argv));
63 fprintf(stderr, "Usage: amtape%s <conf> <command>\n", versionsuffix());
64 fprintf(stderr, "\tValid commands are:\n");
65 fprintf(stderr, "\t\treset Reset changer to known state\n");
66 fprintf(stderr, "\t\teject Eject current tape from drive\n");
67 fprintf(stderr, "\t\tclean Clean the drive\n");
68 fprintf(stderr, "\t\tshow Show contents of all slots\n");
69 fprintf(stderr, "\t\tcurrent Show contents of current slot\n");
70 fprintf(stderr, "\t\tslot <slot #> load tape from slot <slot #>\n");
71 fprintf(stderr, "\t\tslot current load tape from current slot\n");
72 fprintf(stderr, "\t\tslot prev load tape from previous slot\n");
73 fprintf(stderr, "\t\tslot next load tape from next slot\n");
74 fprintf(stderr, "\t\tslot advance advance to next slot but do not load\n");
75 fprintf(stderr, "\t\tslot first load tape from first slot\n");
76 fprintf(stderr, "\t\tslot last load tape from last slot\n");
77 fprintf(stderr, "\t\tlabel <label> find and load labeled tape\n");
78 fprintf(stderr, "\t\ttaper perform taper's scan alg.\n");
79 fprintf(stderr, "\t\tdevice show current tape device\n");
80 fprintf(stderr, "\t\tupdate update the label matchingdatabase\n");
91 char *argv0 = argv[0];
92 unsigned long malloc_hist_1, malloc_size_1;
93 unsigned long malloc_hist_2, malloc_size_2;
106 malloc_size_1 = malloc_inuse(&malloc_hist_1);
108 erroutput_type = ERR_INTERACTIVE;
110 if(argc < 3) usage();
112 config_name = argv[1];
114 config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
115 conffile = stralloc2(config_dir, CONFFILE_NAME);
116 if (read_conffile(conffile)) {
117 error("errors processing config file \"%s\"", conffile);
119 conf_tapelist = getconf_str(CNF_TAPELIST);
120 if (*conf_tapelist == '/') {
121 conf_tapelist = stralloc(conf_tapelist);
123 conf_tapelist = stralloc2(config_dir, conf_tapelist);
125 if (read_tapelist(conf_tapelist)) {
126 error("could not load tapelist \"%s\"", conf_tapelist);
128 amfree(conf_tapelist);
131 uid_dumpuser = uid_me;
132 dumpuser = getconf_str(CNF_DUMPUSER);
134 if ((pw = getpwnam(dumpuser)) == NULL) {
135 error("cannot look up dump user \"%s\"", dumpuser);
138 uid_dumpuser = pw->pw_uid;
139 if ((pw = getpwuid(uid_me)) == NULL) {
140 error("cannot look up my own uid %ld", (long)uid_me);
143 if (uid_me != uid_dumpuser) {
144 error("running as user \"%s\" instead of \"%s\"",
145 pw->pw_name, dumpuser);
149 if((have_changer = changer_init()) == 0) {
150 error("no tpchanger specified in \"%s\"", conffile);
151 } else if (have_changer != 1) {
152 error("changer initialization failed: %s", strerror(errno));
155 /* switch on command name */
157 argc -= 2; argv += 2;
158 if(strcmp(argv[0], "reset") == 0) reset_changer(argc, argv);
159 else if(strcmp(argv[0], "clean") == 0) clean_tape(argc, argv);
160 else if(strcmp(argv[0], "eject") == 0) eject_tape(argc, argv);
161 else if(strcmp(argv[0], "slot") == 0) load_slot(argc, argv);
162 else if(strcmp(argv[0], "label") == 0) load_label(argc, argv);
163 else if(strcmp(argv[0], "current") == 0) show_current(argc, argv);
164 else if(strcmp(argv[0], "show") == 0) show_slots(argc, argv);
165 else if(strcmp(argv[0], "taper") == 0) taper_scan(argc, argv);
166 else if(strcmp(argv[0], "device") == 0) show_device(argc, argv);
167 else if(strcmp(argv[0], "update") == 0) update_labeldb(argc, argv);
169 fprintf(stderr, "%s: unknown command \"%s\"\n", argv0, argv[0]);
173 amfree(changer_resultstr);
177 malloc_size_2 = malloc_inuse(&malloc_hist_2);
179 if(malloc_size_1 != malloc_size_2) {
180 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
187 /* ---------------------------- */
189 void reset_changer(argc, argv)
193 char *slotstr = NULL;
195 switch(changer_reset(&slotstr)) {
197 fprintf(stderr, "%s: changer is reset, slot %s is loaded.\n",
198 get_pname(), slotstr);
201 fprintf(stderr, "%s: changer is reset, but slot %s not loaded: %s\n",
202 get_pname(), slotstr, changer_resultstr);
205 error("could not reset changer: %s", changer_resultstr);
211 /* ---------------------------- */
212 void clean_tape(argc, argv)
218 if(changer_clean(&devstr) == 0) {
219 fprintf(stderr, "%s: device %s is clean.\n", get_pname(), devstr);
221 fprintf(stderr, "%s: device %s not clean: %s\n",
222 get_pname(), devstr ? devstr : "??", changer_resultstr);
228 /* ---------------------------- */
229 void eject_tape(argc, argv)
233 char *slotstr = NULL;
235 if(changer_eject(&slotstr) == 0) {
236 fprintf(stderr, "%s: slot %s is ejected.\n", get_pname(), slotstr);
238 fprintf(stderr, "%s: slot %s not ejected: %s\n",
239 get_pname(), slotstr ? slotstr : "??", changer_resultstr);
245 /* ---------------------------- */
247 void load_slot(argc, argv)
251 char *slotstr = NULL, *devicename = NULL;
258 is_advance = (strcmp(argv[1], "advance") == 0);
259 if(changer_loadslot(argv[1], &slotstr, &devicename)) {
260 error("could not load slot %s: %s", slotstr, changer_resultstr);
262 if(! is_advance && (errstr = tape_rewind(devicename)) != NULL) {
264 "%s: could not rewind %s: %s", get_pname(), devicename, errstr);
268 fprintf(stderr, "%s: changed to slot %s", get_pname(), slotstr);
270 fprintf(stderr, " on %s", devicename);
278 /* ---------------------------- */
280 int nslots, backwards, found, got_match, tapedays;
282 char *label = NULL, *first_match_label = NULL, *first_match = NULL;
283 char *searchlabel, *labelstr;
286 int scan_init(rc, ns, bk)
290 error("could not get changer info: %s", changer_resultstr);
298 int loadlabel_slot(rc, slotstr, device)
306 error("could not load slot %s: %s", slotstr, changer_resultstr);
308 fprintf(stderr, "%s: slot %s: %s\n",
309 get_pname(), slotstr, changer_resultstr);
310 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
311 fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
313 fprintf(stderr, "%s: slot %s: date %-8s label %s",
314 get_pname(), slotstr, datestamp, label);
315 if(strcmp(label, FAKE_LABEL) != 0
316 && strcmp(label, searchlabel) != 0)
317 fprintf(stderr, " (wrong tape)\n");
319 fprintf(stderr, " (exact label match)\n");
320 if((errstr = tape_rewind(device)) != NULL) {
322 "%s: could not rewind %s: %s",
323 get_pname(), device, errstr);
337 void load_label(argc, argv)
344 searchlabel = argv[1];
346 fprintf(stderr, "%s: scanning for tape with label %s\n",
347 get_pname(), searchlabel);
351 changer_find(scan_init, loadlabel_slot, searchlabel);
354 fprintf(stderr, "%s: label %s is now loaded.\n",
355 get_pname(), searchlabel);
357 fprintf(stderr, "%s: could not find label %s in tape rack.\n",
358 get_pname(), searchlabel);
362 /* ---------------------------- */
364 int show_init(rc, ns, bk)
368 error("could not get changer info: %s", changer_resultstr);
375 int show_init_all(rc, ns, bk)
378 int ret = show_init(rc, ns, bk);
379 fprintf(stderr, "%s: scanning all %d slots in tape-changer rack:\n",
380 get_pname(), nslots);
384 int show_init_current(rc, ns, bk)
387 int ret = show_init(rc, ns, bk);
388 fprintf(stderr, "%s: scanning current slot in tape-changer rack:\n",
393 int update_one_slot(rc, slotstr, device)
395 char *slotstr, *device;
400 error("could not load slot %s: %s", slotstr, changer_resultstr);
402 fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
403 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
404 fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
406 fprintf(stderr, "slot %s: date %-8s label %s\n",
407 slotstr, datestamp, label);
408 changer_label(slotstr,label);
415 int show_slot(rc, slotstr, device)
417 char *slotstr, *device;
422 error("could not load slot %s: %s", slotstr, changer_resultstr);
424 fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
425 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
426 fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
428 fprintf(stderr, "slot %s: date %-8s label %s\n",
429 slotstr, datestamp, label);
436 void show_current(argc, argv)
443 changer_current(show_init_current, show_slot);
446 void update_labeldb(argc, argv)
453 changer_scan(show_init_all, update_one_slot);
456 void show_slots(argc, argv)
463 changer_scan(show_init_all, show_slot);
467 /* ---------------------------- */
469 int taperscan_slot(rc, slotstr, device)
477 error("could not load slot %s: %s", slotstr, changer_resultstr);
479 fprintf(stderr, "%s: slot %s: %s\n",
480 get_pname(), slotstr, changer_resultstr);
482 if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
483 fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
485 /* got an amanda tape */
486 fprintf(stderr, "%s: slot %s: date %-8s label %s",
487 get_pname(), slotstr, datestamp, label);
488 if(searchlabel != NULL
489 && (strcmp(label, FAKE_LABEL) == 0
490 || strcmp(label, searchlabel) == 0)) {
491 /* it's the one we are looking for, stop here */
492 fprintf(stderr, " (exact label match)\n");
498 else if(!match(labelstr, label))
499 fprintf(stderr, " (no match)\n");
501 /* not an exact label match, but a labelstr match */
502 /* check against tape list */
503 tp = lookup_tapelabel(label);
505 fprintf(stderr, " (not in tapelist)\n");
506 else if(!reusable_tape(tp))
507 fprintf(stderr, " (active tape)\n");
508 else if(got_match == 0 && tp->datestamp == 0) {
510 first_match = newstralloc(first_match, slotstr);
511 first_match_label = newstralloc(first_match_label, label);
512 fprintf(stderr, " (new tape)\n");
519 fprintf(stderr, " (labelstr match)\n");
522 first_match = newstralloc(first_match, slotstr);
523 first_match_label = newstralloc(first_match_label, label);
524 fprintf(stderr, " (first labelstr match)\n");
525 if(!backwards || !searchlabel) {
540 void taper_scan(argc, argv)
544 char *slotstr = NULL, *device = NULL;
546 if((tp = lookup_last_reusable_tape(0)) == NULL)
549 searchlabel = stralloc(tp->label);
551 tapedays = getconf_int(CNF_TAPECYCLE);
552 labelstr = getconf_str(CNF_LABELSTR);
556 fprintf(stderr, "%s: scanning for ", get_pname());
557 if(searchlabel) fprintf(stderr, "tape label %s or ", searchlabel);
558 fprintf(stderr, "a new tape.\n");
560 if (searchlabel != NULL)
561 changer_find(scan_init, taperscan_slot, searchlabel);
563 changer_scan(scan_init, taperscan_slot);
566 fprintf(stderr, "%s: settling for new tape\n", get_pname());
567 searchlabel = newstralloc(searchlabel, first_match_label);
569 else if(found == 2) {
570 fprintf(stderr, "%s: %s: settling for first labelstr match\n",
572 searchlabel? "gravity stacker": "looking only for new tape");
573 searchlabel = newstralloc(searchlabel, first_match_label);
575 else if(!found && got_match) {
577 "%s: %s not found, going back to first labelstr match %s\n",
578 get_pname(), searchlabel, first_match_label);
579 searchlabel = newstralloc(searchlabel, first_match_label);
580 if(changer_loadslot(first_match, &slotstr, &device) == 0) {
583 fprintf(stderr, "%s: could not load labelstr match in slot %s: %s\n",
584 get_pname(), first_match, changer_resultstr);
590 fprintf(stderr, "%s: could not find ", get_pname());
591 if(searchlabel) fprintf(stderr, "tape %s or ", searchlabel);
592 fprintf(stderr, "a new tape in the tape rack.\n");
596 fprintf(stderr, "%s: label %s is now loaded.\n",
597 get_pname(), searchlabel);
601 amfree(first_match_label);
604 /* ---------------------------- */
606 void show_device(argc, argv)
610 char *slot = NULL, *device = NULL;
612 if(changer_loadslot("current", &slot, &device))
613 error("Could not load current slot.\n");
615 printf("%s\n", device);