2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998, 2000 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: amlabel.c,v 1.53 2006/07/25 18:27:57 martinea Exp $
29 * write an Amanda label on a tape
36 #include <timestamp.h>
37 #include <taperscan.h>
41 int main(int argc, char **argv);
43 static void usage(void) {
44 g_fprintf(stderr, _("Usage: %s [-f] <conf> <label> [slot <slot-number>] [-o configoption]*\n"),
56 char *label, *tapename = NULL;
57 char *labelstr, *slotstr;
58 char *conf_tapelist_old;
62 size_t tt_blocksize_kb;
65 DeviceStatusFlags device_status;
67 config_overwrites_t *cfg_ovr = NULL;
70 * Configure program for internationalization:
71 * 1) Only set the message locale for now.
72 * 2) Set textdomain for all amanda related programs to "amanda"
73 * We don't want to be forced to support dozens of message catalogs.
75 setlocale(LC_MESSAGES, "C");
83 dbopen(DBG_SUBDIR_SERVER);
86 /* Don't die when child closes pipe */
87 signal(SIGPIPE, SIG_IGN);
89 erroutput_type = ERR_INTERACTIVE;
91 cfg_ovr = extract_commandline_config_overwrites(&argc, &argv);
93 if(argc > 1 && strcmp(argv[1],"-f") == 0)
97 if(argc != 3+force && argc != 5+force)
100 cfg_opt = argv[1+force];
101 label = argv[2+force];
103 if(argc == 5+force) {
104 if(strcmp(argv[3+force], "slot"))
106 slotstr = argv[4+force];
113 config_init(CONFIG_INIT_EXPLICIT_NAME, cfg_opt);
114 apply_config_overwrites(cfg_ovr);
116 if (config_errors(NULL) >= CFGERR_WARNINGS) {
117 config_print_errors();
118 if (config_errors(NULL) >= CFGERR_ERRORS) {
119 g_critical(_("errors processing config file"));
123 check_running_as(RUNNING_AS_DUMPUSER);
125 dbrename(get_config_name(), DBG_SUBDIR_SERVER);
127 conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));
128 if (read_tapelist(conf_tapelist)) {
129 error(_("could not load tapelist \"%s\""), conf_tapelist);
133 labelstr = getconf_str(CNF_LABELSTR);
135 if(!match(labelstr, label)) {
136 error(_("label %s doesn't match labelstr \"%s\""), label, labelstr);
140 if((lookup_tapelabel(label))!=NULL) {
142 error(_("label %s already on a tape\n"),label);
146 tape = lookup_tapetype(getconf_str(CNF_TAPETYPE));
147 tt_blocksize_kb = (size_t)tapetype_get_blocksize(tape);
149 if((have_changer = changer_init()) == 0) {
152 _("%s: no tpchanger specified in \"%s\", so slot command invalid\n"),
153 argv[0], get_config_filename());
156 tapename = getconf_str(CNF_TAPEDEV);
157 if (tapename == NULL) {
158 error(_("No tapedev specified"));
160 } else if(have_changer != 1) {
161 error(_("changer initialization failed: %s"), strerror(errno));
164 if(changer_loadslot(slotstr, &outslot, &tapename)) {
165 error(_("could not load slot \"%s\": %s"), slotstr, changer_resultstr);
169 g_printf(_("labeling tape in slot %s (%s):\n"), outslot, tapename);
173 g_printf("Reading label...\n");fflush(stdout);
174 device = device_open(tapename);
175 g_assert(device != NULL);
176 if (device->status != DEVICE_STATUS_SUCCESS) {
177 error("Could not open device %s: %s.\n", tapename,
178 device_error(device));
181 if (!device_configure(device, TRUE)) {
182 error("Could not configure device %s: %s.\n", tapename,
183 device_error(device));
186 device_status = device_read_label(device);
188 if (device_status & DEVICE_STATUS_VOLUME_UNLABELED) {
189 /* if there's no header, then the tape was truly empty; otherwise, there
190 * was *something* on the tape, so let's be careful and require a force */
191 if (!device->volume_header || device->volume_header->type == F_EMPTY) {
192 g_printf("Found an empty tape.\n");
194 g_printf("Found a non-Amanda tape.\n");
198 } else if (device_status != DEVICE_STATUS_SUCCESS) {
199 g_printf("Reading the tape label failed: %s.\n",
200 device_error_or_status(device));
203 /* got an amanda tape */
204 g_printf(_("Found Amanda tape %s"),device->volume_label);
205 if(match(labelstr, device->volume_label) == 0) {
206 g_printf(_(", but it is not from configuration %s."),
211 if((lookup_tapelabel(device->volume_label)) != NULL) {
212 g_printf(_(", tape is active"));
221 char *timestamp = NULL;
223 g_printf(_("Writing label %s..\n"), label); fflush(stdout);
225 timestamp = get_undef_timestamp();
226 if (!device_start(device, ACCESS_WRITE, label, timestamp)) {
227 error(_("Error writing label: %s.\n"),
228 device_error(device));
229 g_assert_not_reached();
230 } else if (!device_finish(device)) {
231 error(_("Error closing device: %s.\n"),
232 device_error(device));
233 g_assert_not_reached();
237 g_printf(_("Checking label...\n")); fflush(stdout);
239 device_status = device_read_label(device);
240 if (device_status != DEVICE_STATUS_SUCCESS) {
241 g_printf(_("Checking the tape label failed: %s.\n"),
242 device_error_or_status(device));
244 } else if (device->volume_label == NULL) {
245 error(_("no label found.\n"));
246 g_assert_not_reached();
247 } else if (strcmp(device->volume_label, label) != 0) {
248 error(_("Read back a different label: Got %s, but expected %s\n"),
249 device->volume_label, label);
250 g_assert_not_reached();
251 } else if (get_timestamp_state(device->volume_time) !=
253 error(_("Read the right label, but the wrong timestamp: "
254 "Got %s, expected X.\n"), device->volume_time);
255 g_assert_not_reached();
258 /* write tape list */
261 conf_tapelist_old = stralloc2(conf_tapelist, ".amlabel");
262 if(write_tapelist(conf_tapelist_old)) {
263 error(_("couldn't write tapelist: %s"), strerror(errno));
266 amfree(conf_tapelist_old);
268 /* XXX add cur_tape number to tape list structure */
269 remove_tapelabel(label);
270 add_tapelabel("0", label, NULL);
271 if(write_tapelist(conf_tapelist)) {
272 error(_("couldn't write tapelist: %s"), strerror(errno));
276 if (have_changer && changer_label(outslot, label) != 0) {
277 error(_("couldn't update barcode database for slot %s, label %s\n"), outslot, label);
281 g_printf(_("Success!\n"));
283 g_printf(_("\ntape not labeled\n"));
287 g_object_unref(device);
292 amfree(conf_tapelist);