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 2003/11/25 12:21:08 martinea 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;
101 for(fd = 3; fd < FD_SETSIZE; fd++) {
103 * Make sure nobody spoofs us with a lot of extra open files
104 * that would cause an open we do to get a very high file
105 * descriptor, which in turn might be used as an index into
106 * an array (e.g. an fd_set).
116 malloc_size_1 = malloc_inuse(&malloc_hist_1);
118 erroutput_type = ERR_INTERACTIVE;
120 if(argc < 3) usage();
122 config_name = argv[1];
124 config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
125 conffile = stralloc2(config_dir, CONFFILE_NAME);
126 if (read_conffile(conffile)) {
127 error("errors processing config file \"%s\"", conffile);
129 conf_tapelist = getconf_str(CNF_TAPELIST);
130 if (*conf_tapelist == '/') {
131 conf_tapelist = stralloc(conf_tapelist);
133 conf_tapelist = stralloc2(config_dir, conf_tapelist);
135 if (read_tapelist(conf_tapelist)) {
136 error("could not load tapelist \"%s\"", conf_tapelist);
138 amfree(conf_tapelist);
141 uid_dumpuser = uid_me;
142 dumpuser = getconf_str(CNF_DUMPUSER);
144 if ((pw = getpwnam(dumpuser)) == NULL) {
145 error("cannot look up dump user \"%s\"", dumpuser);
148 uid_dumpuser = pw->pw_uid;
149 if ((pw = getpwuid(uid_me)) == NULL) {
150 error("cannot look up my own uid %ld", (long)uid_me);
153 if (uid_me != uid_dumpuser) {
154 error("running as user \"%s\" instead of \"%s\"",
155 pw->pw_name, dumpuser);
159 if((have_changer = changer_init()) == 0) {
160 error("no tpchanger specified in \"%s\"", conffile);
161 } else if (have_changer != 1) {
162 error("changer initialization failed: %s", strerror(errno));
165 /* switch on command name */
167 argc -= 2; argv += 2;
168 if(strcmp(argv[0], "reset") == 0) reset_changer(argc, argv);
169 else if(strcmp(argv[0], "clean") == 0) clean_tape(argc, argv);
170 else if(strcmp(argv[0], "eject") == 0) eject_tape(argc, argv);
171 else if(strcmp(argv[0], "slot") == 0) load_slot(argc, argv);
172 else if(strcmp(argv[0], "label") == 0) load_label(argc, argv);
173 else if(strcmp(argv[0], "current") == 0) show_current(argc, argv);
174 else if(strcmp(argv[0], "show") == 0) show_slots(argc, argv);
175 else if(strcmp(argv[0], "taper") == 0) taper_scan(argc, argv);
176 else if(strcmp(argv[0], "device") == 0) show_device(argc, argv);
177 else if(strcmp(argv[0], "update") == 0) update_labeldb(argc, argv);
179 fprintf(stderr, "%s: unknown command \"%s\"\n", argv0, argv[0]);
183 amfree(changer_resultstr);
187 malloc_size_2 = malloc_inuse(&malloc_hist_2);
189 if(malloc_size_1 != malloc_size_2) {
190 malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
197 /* ---------------------------- */
199 void reset_changer(argc, argv)
203 char *slotstr = NULL;
205 switch(changer_reset(&slotstr)) {
207 fprintf(stderr, "%s: changer is reset, slot %s is loaded.\n",
208 get_pname(), slotstr);
211 fprintf(stderr, "%s: changer is reset, but slot %s not loaded: %s\n",
212 get_pname(), slotstr, changer_resultstr);
215 error("could not reset changer: %s", changer_resultstr);
221 /* ---------------------------- */
222 void clean_tape(argc, argv)
228 if(changer_clean(&devstr) == 0) {
229 fprintf(stderr, "%s: device %s is clean.\n", get_pname(), devstr);
231 fprintf(stderr, "%s: device %s not clean: %s\n",
232 get_pname(), devstr ? devstr : "??", changer_resultstr);
238 /* ---------------------------- */
239 void eject_tape(argc, argv)
243 char *slotstr = NULL;
245 if(changer_eject(&slotstr) == 0) {
246 fprintf(stderr, "%s: slot %s is ejected.\n", get_pname(), slotstr);
248 fprintf(stderr, "%s: slot %s not ejected: %s\n",
249 get_pname(), slotstr ? slotstr : "??", changer_resultstr);
255 /* ---------------------------- */
257 void load_slot(argc, argv)
261 char *slotstr = NULL, *devicename = NULL;
268 is_advance = (strcmp(argv[1], "advance") == 0);
269 if(changer_loadslot(argv[1], &slotstr, &devicename)) {
270 error("could not load slot %s: %s", slotstr, changer_resultstr);
272 if(! is_advance && (errstr = tape_rewind(devicename)) != NULL) {
274 "%s: could not rewind %s: %s", get_pname(), devicename, errstr);
278 fprintf(stderr, "%s: changed to slot %s", get_pname(), slotstr);
280 fprintf(stderr, " on %s", devicename);
288 /* ---------------------------- */
290 int nslots, backwards, found, got_match, tapedays;
292 char *label = NULL, *first_match_label = NULL, *first_match = NULL;
293 char *searchlabel, *labelstr;
296 int scan_init(rc, ns, bk)
300 error("could not get changer info: %s", changer_resultstr);
308 int loadlabel_slot(rc, slotstr, device)
316 error("could not load slot %s: %s", slotstr, changer_resultstr);
318 fprintf(stderr, "%s: slot %s: %s\n",
319 get_pname(), slotstr, changer_resultstr);
320 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
321 fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
323 fprintf(stderr, "%s: slot %s: date %-8s label %s",
324 get_pname(), slotstr, datestamp, label);
325 if(strcmp(label, FAKE_LABEL) != 0
326 && strcmp(label, searchlabel) != 0)
327 fprintf(stderr, " (wrong tape)\n");
329 fprintf(stderr, " (exact label match)\n");
330 if((errstr = tape_rewind(device)) != NULL) {
332 "%s: could not rewind %s: %s",
333 get_pname(), device, errstr);
347 void load_label(argc, argv)
354 searchlabel = argv[1];
356 fprintf(stderr, "%s: scanning for tape with label %s\n",
357 get_pname(), searchlabel);
361 changer_find(scan_init, loadlabel_slot, searchlabel);
364 fprintf(stderr, "%s: label %s is now loaded.\n",
365 get_pname(), searchlabel);
367 fprintf(stderr, "%s: could not find label %s in tape rack.\n",
368 get_pname(), searchlabel);
372 /* ---------------------------- */
374 int show_init(rc, ns, bk)
378 error("could not get changer info: %s", changer_resultstr);
385 int show_init_all(rc, ns, bk)
388 int ret = show_init(rc, ns, bk);
389 fprintf(stderr, "%s: scanning all %d slots in tape-changer rack:\n",
390 get_pname(), nslots);
394 int show_init_current(rc, ns, bk)
397 int ret = show_init(rc, ns, bk);
398 fprintf(stderr, "%s: scanning current slot in tape-changer rack:\n",
403 int update_one_slot(rc, slotstr, device)
405 char *slotstr, *device;
410 error("could not load slot %s: %s", slotstr, changer_resultstr);
412 fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
413 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
414 fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
416 fprintf(stderr, "slot %s: date %-8s label %s\n",
417 slotstr, datestamp, label);
418 changer_label(slotstr,label);
425 int show_slot(rc, slotstr, device)
427 char *slotstr, *device;
432 error("could not load slot %s: %s", slotstr, changer_resultstr);
434 fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
435 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
436 fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
438 fprintf(stderr, "slot %s: date %-8s label %s\n",
439 slotstr, datestamp, label);
446 void show_current(argc, argv)
453 changer_current(show_init_current, show_slot);
456 void update_labeldb(argc, argv)
463 changer_scan(show_init_all, update_one_slot);
466 void show_slots(argc, argv)
473 changer_scan(show_init_all, show_slot);
477 /* ---------------------------- */
479 int taperscan_slot(rc, slotstr, device)
487 error("could not load slot %s: %s", slotstr, changer_resultstr);
489 fprintf(stderr, "%s: slot %s: %s\n",
490 get_pname(), slotstr, changer_resultstr);
492 if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL) {
493 fprintf(stderr, "%s: slot %s: %s\n", get_pname(), slotstr, errstr);
495 /* got an amanda tape */
496 fprintf(stderr, "%s: slot %s: date %-8s label %s",
497 get_pname(), slotstr, datestamp, label);
498 if(searchlabel != NULL
499 && (strcmp(label, FAKE_LABEL) == 0
500 || strcmp(label, searchlabel) == 0)) {
501 /* it's the one we are looking for, stop here */
502 fprintf(stderr, " (exact label match)\n");
508 else if(!match(labelstr, label))
509 fprintf(stderr, " (no match)\n");
511 /* not an exact label match, but a labelstr match */
512 /* check against tape list */
513 tp = lookup_tapelabel(label);
515 fprintf(stderr, " (not in tapelist)\n");
516 else if(!reusable_tape(tp))
517 fprintf(stderr, " (active tape)\n");
518 else if(got_match == 0 && tp->datestamp == 0) {
520 first_match = newstralloc(first_match, slotstr);
521 first_match_label = newstralloc(first_match_label, label);
522 fprintf(stderr, " (new tape)\n");
529 fprintf(stderr, " (labelstr match)\n");
532 first_match = newstralloc(first_match, slotstr);
533 first_match_label = newstralloc(first_match_label, label);
534 fprintf(stderr, " (first labelstr match)\n");
535 if(!backwards || !searchlabel) {
550 void taper_scan(argc, argv)
554 char *slotstr = NULL, *device = NULL;
556 if((tp = lookup_last_reusable_tape(0)) == NULL)
559 searchlabel = stralloc(tp->label);
561 tapedays = getconf_int(CNF_TAPECYCLE);
562 labelstr = getconf_str(CNF_LABELSTR);
566 fprintf(stderr, "%s: scanning for ", get_pname());
567 if(searchlabel) fprintf(stderr, "tape label %s or ", searchlabel);
568 fprintf(stderr, "a new tape.\n");
570 if (searchlabel != NULL)
571 changer_find(scan_init, taperscan_slot, searchlabel);
573 changer_scan(scan_init, taperscan_slot);
576 fprintf(stderr, "%s: settling for new tape\n", get_pname());
577 searchlabel = newstralloc(searchlabel, first_match_label);
579 else if(found == 2) {
580 fprintf(stderr, "%s: %s: settling for first labelstr match\n",
582 searchlabel? "gravity stacker": "looking only for new tape");
583 searchlabel = newstralloc(searchlabel, first_match_label);
585 else if(!found && got_match) {
587 "%s: %s not found, going back to first labelstr match %s\n",
588 get_pname(), searchlabel, first_match_label);
589 searchlabel = newstralloc(searchlabel, first_match_label);
590 if(changer_loadslot(first_match, &slotstr, &device) == 0) {
593 fprintf(stderr, "%s: could not load labelstr match in slot %s: %s\n",
594 get_pname(), first_match, changer_resultstr);
600 fprintf(stderr, "%s: could not find ", get_pname());
601 if(searchlabel) fprintf(stderr, "tape %s or ", searchlabel);
602 fprintf(stderr, "a new tape in the tape rack.\n");
606 fprintf(stderr, "%s: label %s is now loaded.\n",
607 get_pname(), searchlabel);
611 amfree(first_match_label);
614 /* ---------------------------- */
616 void show_device(argc, argv)
620 char *slot = NULL, *device = NULL;
622 if(changer_loadslot("current", &slot, &device))
623 error("Could not load current slot.\n");
625 printf("%s\n", device);