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.47 2006/07/25 18:27:57 martinea Exp $
29 * tape changer interface program
34 #include "taperscan.h"
39 #include "timestamp.h"
42 static void usage(void);
43 int main(int argc, char **argv);
44 static void reset_changer(int argc, char **argv);
45 static void eject_tape(int argc, char **argv);
46 static void clean_tape(int argc, char **argv);
47 static void load_slot(int argc, char **argv);
48 static void load_label(int argc, char **argv);
49 static void show_slots(int argc, char **argv);
50 static void show_current(int argc, char **argv);
51 static void amtape_taper_scan(int argc, char **argv);
52 static void show_device(int argc, char **argv);
53 static int loadlabel_slot(void *ud, int rc, char *slotstr, char *device);
54 int show_init(void *ud, int rc, int ns, int bk, int s);
55 static int show_slots_slot(void *ud, int rc, char *slotstr, char *device);
59 void (*fn)(int, char **);
62 { "reset", reset_changer,
63 T_("reset Reset changer to known state") },
64 { "eject", eject_tape,
65 T_("eject Eject current tape from drive") },
66 { "clean", clean_tape,
67 T_("clean Clean the drive") },
69 T_("show Show contents of all slots") },
70 { "current", show_current,
71 T_("current Show contents of current slot") },
73 T_("slot <slot #> load tape from slot <slot #>") },
75 T_("slot current load tape from current slot") },
77 T_("slot prev load tape from previous slot") },
79 T_("slot next load tape from next slot") },
81 T_("slot advance advance to next slot but do not load") },
83 T_("slot first load tape from first slot") },
85 T_("slot last load tape from last slot") },
86 { "label", load_label,
87 T_("label <label> find and load labeled tape") },
88 { "taper", amtape_taper_scan,
89 T_("taper perform taper's scan alg.") },
90 { "device", show_device,
91 T_("device show current tape device") },
92 { "update", show_slots,
93 T_("update update the label matchingdatabase")},
95 #define NCMDS (int)(sizeof(cmdtab) / sizeof(cmdtab[0]))
102 g_fprintf(stderr, _("Usage: amtape%s <conf> <command> {<args>} [-o configoption]*\n"), versionsuffix());
103 g_fprintf(stderr, _("\tValid commands are:\n"));
104 for (i = 0; i < NCMDS; i++)
105 g_fprintf(stderr, "\t\t%s\n", _(cmdtab[i].usage));
117 config_overwrites_t *cfg_ovr = NULL;
120 * Configure program for internationalization:
121 * 1) Only set the message locale for now.
122 * 2) Set textdomain for all amanda related programs to "amanda"
123 * We don't want to be forced to support dozens of message catalogs.
125 setlocale(LC_MESSAGES, "C");
126 textdomain("amanda");
133 /* Don't die when child closes pipe */
134 signal(SIGPIPE, SIG_IGN);
136 dbopen(DBG_SUBDIR_SERVER);
138 malloc_size_1 = malloc_inuse(&malloc_hist_1);
140 erroutput_type = ERR_INTERACTIVE;
142 cfg_ovr = extract_commandline_config_overwrites(&argc, &argv);
143 if(argc < 3) usage();
145 config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_FATAL,
147 apply_config_overwrites(cfg_ovr);
149 check_running_as(RUNNING_AS_DUMPUSER);
151 dbrename(config_name, DBG_SUBDIR_SERVER);
153 conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));
154 if (read_tapelist(conf_tapelist)) {
155 error(_("could not load tapelist \"%s\""), conf_tapelist);
158 amfree(conf_tapelist);
160 if((have_changer = changer_init()) == 0) {
161 error(_("no tpchanger specified in \"%s\""), config_filename);
163 } else if (have_changer != 1) {
164 error(_("changer initialization failed: %s"), strerror(errno));
168 /* switch on command name */
170 argc -= 2; argv += 2;
171 for (i = 0; i < NCMDS; i++)
172 if (strcmp(argv[0], cmdtab[i].name) == 0) {
173 (*cmdtab[i].fn)(argc, argv);
177 g_fprintf(stderr, _("%s: unknown command \"%s\"\n"), get_pname(), argv[0]);
181 amfree(changer_resultstr);
187 /* ---------------------------- */
190 reset_changer(G_GNUC_UNUSED int argc,
191 G_GNUC_UNUSED char ** argv) {
192 char *slotstr = NULL;
194 (void)argc; /* Quiet unused parameter warning */
195 (void)argv; /* Quiet unused parameter warning */
197 switch(changer_reset(&slotstr)) {
199 g_fprintf(stderr, _("%s: changer is reset, slot %s is loaded.\n"),
200 get_pname(), slotstr);
203 g_fprintf(stderr, _("%s: changer is reset, but slot %s not loaded: %s\n"),
204 get_pname(), slotstr, changer_resultstr);
207 error(_("could not reset changer: %s"), changer_resultstr);
214 /* ---------------------------- */
216 clean_tape(G_GNUC_UNUSED int argc,
217 G_GNUC_UNUSED char ** argv) {
220 (void)argc; /* Quiet unused parameter warning */
221 (void)argv; /* Quiet unused parameter warning */
223 if(changer_clean(&devstr) == 0) {
224 g_fprintf(stderr, _("%s: device %s is clean.\n"), get_pname(), devstr);
226 g_fprintf(stderr, _("%s: device %s not clean: %s\n"),
227 get_pname(), devstr ? devstr : "??", changer_resultstr);
233 /* ---------------------------- */
235 eject_tape(G_GNUC_UNUSED int argc,
236 G_GNUC_UNUSED char ** argv) {
237 char *slotstr = NULL;
239 (void)argc; /* Quiet unused parameter warning */
240 (void)argv; /* Quiet unused parameter warning */
242 if(changer_eject(&slotstr) == 0) {
243 g_fprintf(stderr, _("%s: slot %3s is ejected.\n"), get_pname(), slotstr);
245 g_fprintf(stderr, _("%s: slot %3s not ejected: %s\n"),
246 get_pname(), slotstr ? slotstr : "??", changer_resultstr);
252 /* ---------------------------- */
259 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);
275 device = device_open(devicename);
276 if (device == NULL) {
278 _("%s: could not open device %s"), get_pname(),
281 g_object_unref(device);
285 g_fprintf(stderr, _("%s: changed to slot %s"), get_pname(), slotstr);
287 g_fprintf(stderr, _(" on %s"), devicename);
295 /* ---------------------------- */
297 /* This initalizes the ChangerStatus structure for all commands that
298 use changer_find; namely, show_slots, load_label, and
301 scan_init(G_GNUC_UNUSED void * data, int rc, G_GNUC_UNUSED int numslots,
302 G_GNUC_UNUSED int backwards, G_GNUC_UNUSED int searchable) {
304 error(_("could not get changer info: %s"), changer_resultstr);
314 static int scan_init_print(void * data, int rc, int numslots,
315 int backwards, int searchable) {
317 g_fprintf(stderr, _("%s: scanning all %d slots in tape-changer rack:\n"),
318 get_pname(), numslots);
320 return scan_init(data, rc, numslots, backwards, searchable);
326 } LabelChangerStatus;
328 /* This is the 'user_slot' callback for the 'load label' command. */
336 LabelChangerStatus * status = ud;
338 ReadLabelStatusFlags label_status;
341 error(_("could not load slot %s: %s"), slotstr, changer_resultstr);
342 g_assert_not_reached();
343 } else if (rc == 1) {
344 g_fprintf(stderr, _("%s: slot %3s: %s\n"),
345 get_pname(), slotstr, changer_resultstr);
349 device = device_open(device_name);
350 if (device == NULL) {
351 g_fprintf(stderr, _("%s: slot %3s: Could not open device.\n"),
352 get_pname(), slotstr);
356 device_set_startup_properties_from_config(device);
358 label_status = device_read_label(device);
359 if (label_status != READ_LABEL_STATUS_SUCCESS) {
361 g_english_strjoinv_and_free
362 (g_flags_nick_to_strv(label_status,
363 READ_LABEL_STATUS_FLAGS_TYPE), "or");
364 g_fprintf(stderr, _("%s: slot %3s: %s\n"),
365 get_pname(), slotstr, errstr);
366 g_object_unref(device);
370 g_fprintf(stderr, _("%s: slot %3s: time %-14s label %s"),
371 get_pname(), slotstr, device->volume_time, device->volume_label);
373 if(strcmp(device->volume_label, status->searchlabel) != 0) {
374 g_fprintf(stderr, _(" (wrong tape)\n"));
375 g_object_unref(device);
378 g_fprintf(stderr, _(" (exact label match)\n"));
379 g_object_unref(device);
384 g_assert_not_reached();
387 /* This does the 'load label' command. */
393 LabelChangerStatus status;
400 status.searchlabel = argv[1];
402 g_fprintf(stderr, _("%s: scanning for tape with label %s\n"),
403 get_pname(), status.searchlabel);
407 changer_find(&status, scan_init, loadlabel_slot, status.searchlabel);
410 g_fprintf(stderr, _("%s: label %s is now loaded.\n"),
411 get_pname(), status.searchlabel);
413 g_fprintf(stderr, _("%s: could not find label %s in tape rack.\n"),
414 get_pname(), status.searchlabel);
418 /* ---------------------------- */
420 /* This is the user_slot function for "amtape show". */
422 show_slots_slot(G_GNUC_UNUSED void * data, int rc, char * slotstr,
428 error(_("could not load slot %s: %s"), slotstr, changer_resultstr);
429 g_assert_not_reached();
433 g_fprintf(stderr, _("slot %s: %s\n"), slotstr, changer_resultstr);
437 device = device_open(device_name);
438 if (device == NULL) {
439 g_fprintf(stderr, _("%s: slot %3s: Could not open device.\n"),
440 get_pname(), slotstr);
442 ReadLabelStatusFlags label_status;
443 device_set_startup_properties_from_config(device);
444 label_status = device_read_label(device);
446 if (label_status != READ_LABEL_STATUS_SUCCESS) {
448 g_english_strjoinv_and_free
449 (g_flags_nick_to_strv(label_status,
450 READ_LABEL_STATUS_FLAGS_TYPE), "or");
451 g_fprintf(stderr, _("%s: slot %3s: %s\n"),
452 get_pname(), slotstr, errstr);
454 g_fprintf(stderr, _("slot %3s: time %-14s label %s\n"),
455 slotstr, device->volume_time, device->volume_label);
457 /* update the changer db */
458 changer_label(slotstr, device->volume_label);
463 g_object_unref(device);
469 show_current(int argc, G_GNUC_UNUSED char ** argv) {
475 g_fprintf(stderr, _("%s: scanning current slot in tape-changer rack:\n"),
477 changer_current(NULL, scan_init, show_slots_slot);
481 show_slots(int argc, G_GNUC_UNUSED char ** argv) {
486 changer_find(NULL, scan_init_print, show_slots_slot, NULL);
490 /* ---------------------------- */
493 amtape_taper_scan(G_GNUC_UNUSED int argc, G_GNUC_UNUSED char ** argv) {
497 char *timestamp = NULL;
498 char *tapedev = NULL;
503 g_fprintf(stderr, _("%s: scanning for "), get_pname());
505 tp = lookup_last_reusable_tape(0);
509 searchlabel = stralloc(tp->label);
510 g_fprintf(stderr, _("tape label %s or "), searchlabel);
512 g_fprintf(stderr, _("a new tape.\n"));
514 result = taper_scan(searchlabel, &label, ×tamp, &tapedev, NULL,
515 FILE_taperscan_output_callback, stderr, NULL, NULL);
518 g_fprintf(stderr, _("Could not find a non-active Amanda tape.\n"));
520 g_fprintf(stderr, _("Tape with label `%s' is now loaded.\n"), label);
522 } else if (result == 3) {
523 g_fprintf(stderr, _("New tape loaded, it will be labelled `%s'.\n"),
526 g_fprintf(stderr, _("Tape with label `%s' is now loaded.\n"), label);
535 /* ---------------------------- */
538 show_device(G_GNUC_UNUSED int argc,
539 G_GNUC_UNUSED char ** argv) {
540 char *slot = NULL, *device = NULL;
542 if(changer_loadslot(_("current"), &slot, &device)) {
543 error(_("Could not load current slot.\n"));
547 g_printf("%s\n", device);
552 /* ---------------------------- */
562 char *datestamp = NULL;
565 (void)ud; /* Quiet unused parameter warning */
568 error("could not load slot %s: %s", slotstr, changer_resultstr);
570 fprintf(stderr, "slot %s: %s\n", slotstr, changer_resultstr);
571 else if((errstr = tape_rdlabel(device, &datestamp, &label)) != NULL)
572 fprintf(stderr, "slot %s: %s\n", slotstr, errstr);
574 fprintf(stderr, "slot %s: date %-8s label %s\n",
575 slotstr, datestamp, label);
576 changer_label(slotstr, label);
589 (void)argv; /* Quiet unused parameter warning */
594 changer_find(NULL, show_init_all, update_one_slot, NULL);