Imported Upstream version 2.4.5p1
[debian/amanda] / server-src / amlabel.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
4  * All Rights Reserved.
5  *
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.
15  *
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.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: amlabel.c,v 1.18.2.15.4.3.2.4.2.4 2005/10/02 13:48:42 martinea Exp $
28  *
29  * write an Amanda label on a tape
30  */
31 #include "amanda.h"
32 #include "conffile.h"
33 #include "tapefile.h"
34 #include "tapeio.h"
35 #include "changer.h"
36
37 #ifdef HAVE_LIBVTBLC
38 #include <vtblc.h>
39 #endif /* HAVE_LIBVTBLC */
40
41 /* local functions */
42
43 void usage P((char *argv0));
44
45 void usage(argv0)
46 char *argv0;
47 {
48     fprintf(stderr, "Usage: %s [-f] <conf> <label> [slot <slot-number>]\n",
49             argv0);
50     exit(1);
51 }
52
53 int main(argc, argv)
54     int argc;
55     char **argv;
56 {
57     char *conffile;
58     char *conf_tapelist;
59     char *outslot = NULL;
60     char *errstr = NULL, *label, *oldlabel=NULL, *tapename = NULL;
61     char *labelstr, *slotstr;
62     char *olddatestamp=NULL;
63     char *conf_tapelist_old;
64     unsigned long malloc_hist_1, malloc_size_1;
65     unsigned long malloc_hist_2, malloc_size_2;
66 #ifdef HAVE_LINUX_ZFTAPE_H
67     int fd = -1;
68     int isa_zftape;
69 #endif /* HAVE_LINUX_ZFTAPE_H */
70     int have_changer;
71     int force, tape_ok;
72     tape_t *tp;
73     tapetype_t *tape;
74     long tt_blocksize_kb;
75     int slotcommand;
76     uid_t uid_me;
77     uid_t uid_dumpuser;
78     char *dumpuser;
79     struct passwd *pw;
80
81 #ifdef HAVE_LIBVTBLC
82     int vtbl_no      = -1;
83     char *datestr    = NULL;
84     char *rawtapedev = NULL;
85     int first_seg, last_seg;
86 #endif /* HAVE_LIBVTBLC */
87
88     safe_fd(-1, 0);
89     safe_cd();
90
91     set_pname("amlabel");
92     dbopen();
93
94     malloc_size_1 = malloc_inuse(&malloc_hist_1);
95
96     erroutput_type = ERR_INTERACTIVE;
97
98     if(argc > 1 && strcmp(argv[1],"-f") == 0)
99          force=1;
100     else force=0;
101
102     if(argc != 3+force && argc != 5+force)
103         usage(argv[0]);
104
105     config_name = argv[1+force];
106     label = argv[2+force];
107
108     if(argc == 5+force) {
109         if(strcmp(argv[3+force], "slot"))
110             usage(argv[0]);
111         slotstr = argv[4+force];
112         slotcommand = 1;
113     } else {
114         slotstr = "current";
115         slotcommand = 0;
116     }
117
118     config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
119     conffile = stralloc2(config_dir, CONFFILE_NAME);
120     if (read_conffile(conffile)) {
121         error("errors processing config file \"%s\"", conffile);
122     }
123     conf_tapelist = getconf_str(CNF_TAPELIST);
124     if (*conf_tapelist == '/') {
125         conf_tapelist = stralloc(conf_tapelist);
126     } else {
127         conf_tapelist = stralloc2(config_dir, conf_tapelist);
128     }
129     if (read_tapelist(conf_tapelist)) {
130         error("could not load tapelist \"%s\"", conf_tapelist);
131     }
132
133     uid_me = getuid();
134     uid_dumpuser = uid_me;
135     dumpuser = getconf_str(CNF_DUMPUSER);
136
137     if ((pw = getpwnam(dumpuser)) == NULL) {
138         error("cannot look up dump user \"%s\"", dumpuser);
139         /* NOTREACHED */
140     }
141     uid_dumpuser = pw->pw_uid;
142     if ((pw = getpwuid(uid_me)) == NULL) {
143         error("cannot look up my own uid %ld", (long)uid_me);
144         /* NOTREACHED */
145     }
146     if (uid_me != uid_dumpuser) {
147         error("running as user \"%s\" instead of \"%s\"",
148               pw->pw_name, dumpuser);
149         /* NOTREACHED */
150     }
151
152     labelstr = getconf_str(CNF_LABELSTR);
153
154     if(!match(labelstr, label))
155         error("label %s doesn't match labelstr \"%s\"", label, labelstr);
156
157     if((tp = lookup_tapelabel(label))!=NULL) {
158         if(!force)
159             error("label %s already on a tape\n",label);
160     }
161     tape = lookup_tapetype(getconf_str(CNF_TAPETYPE));
162     tt_blocksize_kb = tape->blocksize;
163
164     if((have_changer = changer_init()) == 0) {
165         if(slotcommand) {
166             fprintf(stderr,
167              "%s: no tpchanger specified in \"%s\", so slot command invalid\n",
168                     argv[0], conffile);
169             usage(argv[0]);
170         }
171         tapename = stralloc(getconf_str(CNF_TAPEDEV));
172 #ifdef HAVE_LIBVTBLC
173         rawtapedev = stralloc(getconf_str(CNF_RAWTAPEDEV));
174 #endif /* HAVE_LIBVTBLC */
175     } else if(have_changer != 1) {
176         error("changer initialization failed: %s", strerror(errno));
177     } else {
178         if(changer_loadslot(slotstr, &outslot, &tapename)) {
179             error("could not load slot \"%s\": %s", slotstr, changer_resultstr);
180         }
181
182         printf("labeling tape in slot %s (%s):\n", outslot, tapename);
183     }
184
185 #ifdef HAVE_LINUX_ZFTAPE_H
186     isa_zftape = is_zftape(tapename);
187     if (isa_zftape) {
188         if((fd = tape_open(tapename, O_WRONLY)) == -1) {
189             errstr = newstralloc2(errstr, "amlabel: ",
190                                   (errno == EACCES) ? "tape is write-protected"
191                                   : strerror(errno));
192             error(errstr);
193         }
194     }
195 #endif /* HAVE_LINUX_ZFTAPE_H */
196
197     printf("rewinding"); fflush(stdout);
198
199 #ifdef HAVE_LINUX_ZFTAPE_H
200     if (isa_zftape) {
201         if(tapefd_rewind(fd) == -1) {
202             putchar('\n');
203             error(strerror(errno));
204         }
205     }
206     else
207 #endif /* HAVE_LINUX_ZFTAPE_H */
208     if((errstr = tape_rewind(tapename)) != NULL) {
209         putchar('\n');
210         error(errstr);
211     }
212
213     tape_ok=1;
214     printf(", reading label");fflush(stdout);
215     if((errstr = tape_rdlabel(tapename, &olddatestamp, &oldlabel)) != NULL) {
216         printf(", %s\n",errstr);
217         tape_ok=1;
218     }
219     else {
220         /* got an amanda tape */
221         printf(" %s",oldlabel);
222         if(strcmp(oldlabel, FAKE_LABEL) != 0
223            && match(labelstr, oldlabel) == 0) {
224             printf(", tape is in another amanda configuration");
225             if(!force)
226                 tape_ok=0;
227         }
228         else {
229             if((tp = lookup_tapelabel(oldlabel)) != NULL) {
230                 printf(", tape is active");
231                 if(!force)
232                     tape_ok=0;
233             }
234         }
235         printf("\n");
236     }
237     amfree(oldlabel);
238     amfree(olddatestamp);
239         
240     printf("rewinding"); fflush(stdout);
241
242 #ifdef HAVE_LINUX_ZFTAPE_H
243     if (isa_zftape) {
244         if(tapefd_rewind(fd) == -1) {
245             putchar('\n');
246             error(strerror(errno));
247         }
248     }
249     else
250 #endif /* HAVE_LINUX_ZFTAPE_H */
251     if((errstr = tape_rewind(tapename)) != NULL) {
252         putchar('\n');
253         error(errstr);
254     }
255
256     if(tape_ok) {
257         printf(", writing label %s", label); fflush(stdout);
258
259 #ifdef HAVE_LINUX_ZFTAPE_H
260         if (isa_zftape) {
261             errstr = tapefd_wrlabel(fd, "X", label, tt_blocksize_kb * 1024);
262             if(errstr != NULL) {
263                 putchar('\n');
264                 error(errstr);
265             }
266         }
267         else
268 #endif /* HAVE_LINUX_ZFTAPE_H */
269         errstr = tape_wrlabel(tapename, "X", label, tt_blocksize_kb * 1024);
270         if(errstr != NULL) {
271             putchar('\n');
272             error(errstr);
273         }
274
275 #ifdef HAVE_LINUX_ZFTAPE_H
276         if (isa_zftape) {
277             tapefd_weof(fd, 1);
278         }
279 #endif /* HAVE_LINUX_ZFTAPE_H */
280
281 #ifdef HAVE_LINUX_ZFTAPE_H
282         if (isa_zftape) {
283             errstr = tapefd_wrendmark(fd, "X", tt_blocksize_kb * 1024);
284             if(errstr != NULL) {
285                 putchar('\n');
286                 error(errstr);
287             }
288         }
289         else
290 #endif /* HAVE_LINUX_ZFTAPE_H */
291         errstr = tape_wrendmark(tapename, "X", tt_blocksize_kb * 1024);
292         if(errstr != NULL) {
293             putchar('\n');
294             error(errstr);
295         }
296
297 #ifdef HAVE_LINUX_ZFTAPE_H
298         if (isa_zftape) {
299             tapefd_weof(fd, 1);
300
301             printf(",\nrewinding"); fflush(stdout); 
302      
303             if(tapefd_rewind(fd) == -1) { 
304                 putchar('\n'); 
305                 error(strerror(errno)); 
306             } 
307             close(fd);
308 #ifdef HAVE_LIBVTBLC
309             /* update volume table */
310             printf(", updating volume table"); fflush(stdout);
311     
312             if ((fd = raw_tape_open(rawtapedev, O_RDWR)) == -1) {
313                 if(errno == EACCES) {
314                     errstr = newstralloc(errstr,
315                                          "updating volume table: raw tape device is write protected");
316                 } else {
317                     errstr = newstralloc2(errstr,
318                                           "updating volume table: ", strerror(errno));
319                 }
320                 putchar('\n');
321                 error(errstr);
322             }
323             /* read volume table */
324             if ((num_volumes = read_vtbl(fd, volumes, vtbl_buffer,
325                                          &first_seg, &last_seg)) == -1 ) {
326                 errstr = newstralloc2(errstr,
327                                       "reading volume table: ", strerror(errno));
328                 putchar('\n');
329                 error(errstr);
330             }
331             /* set date and volume label for first entry */
332             vtbl_no = 0;
333             datestr = NULL; 
334             if (set_date(datestr, volumes, num_volumes, vtbl_no)){
335                 errstr = newstralloc2(errstr,
336                                       "setting date for entry 1: ", strerror(errno));
337                 putchar('\n');
338                 error(errstr);
339             }
340             if(set_label(label, volumes, num_volumes, vtbl_no)){
341                 errstr = newstralloc2(errstr,
342                                       "setting label for entry 1: ", strerror(errno));
343                 putchar('\n');
344                 error(errstr);
345             }
346             /* set date and volume label for last entry */
347             vtbl_no = 1;
348             datestr = NULL; 
349             if (set_date(datestr, volumes, num_volumes, vtbl_no)){
350                 errstr = newstralloc2(errstr,
351                                       "setting date for entry 2: ", strerror(errno));
352                 putchar('\n');
353                 error(errstr);
354             }
355             if(set_label("AMANDA Tape End", volumes, num_volumes, vtbl_no)){
356                 errstr = newstralloc2(errstr,
357                                       "setting label for entry 2: ", strerror(errno));
358                 putchar('\n');
359                 error(errstr);
360             }
361             /* write volume table back */
362             if (write_vtbl(fd, volumes, vtbl_buffer, num_volumes, first_seg,
363                            op_mode == trunc)) {
364                 errstr = newstralloc2(errstr,
365                                       "writing volume table: ", strerror(errno));
366                 putchar('\n');
367                 error(errstr);
368             }  
369             close(fd);
370 #endif /* HAVE_LIBVTBLC */
371         }
372 #endif /* HAVE_LINUX_ZFTAPE_H */
373
374         if (tape_ok) {
375             printf(", checking label"); fflush(stdout);
376
377             if((errstr = tape_rdlabel(tapename, &olddatestamp, &oldlabel)) != NULL) {
378                 putchar('\n');
379                 if (strcmp(errstr, "not an amanda tape") != 0)
380                     error(errstr);
381                 error("no label found, are you sure %s is non-rewinding?",
382                       tapename);
383             }
384
385             if (strcmp("X", olddatestamp) != 0 ||
386                 (strcmp(oldlabel, FAKE_LABEL) != 0
387                  && strcmp(label, oldlabel) != 0)) {
388                 putchar('\n');
389                 error("read label %s back, timestamp %s (expected X), what now?",
390                       oldlabel, olddatestamp);
391             }
392             amfree(oldlabel);
393             amfree(olddatestamp);
394
395             /* write tape list */
396
397             /* make a copy */
398             conf_tapelist_old = stralloc2(conf_tapelist, ".amlabel");
399             if(write_tapelist(conf_tapelist_old)) {
400                 error("couldn't write tapelist: %s", strerror(errno));
401             }
402             amfree(conf_tapelist_old);
403
404             /* XXX add cur_tape number to tape list structure */
405             remove_tapelabel(label);
406             add_tapelabel(0, label);
407             if(write_tapelist(conf_tapelist)) {
408                 error("couldn't write tapelist: %s", strerror(errno));
409             }
410         } /* write tape list */
411
412         if(have_changer) {
413             /* Now we try to inform the changer, about the new label */
414             changer_label(outslot,label); 
415         }
416         printf(", done.\n");
417     } else {
418         printf("\ntape not labeled\n");
419     }
420
421     amfree(outslot);
422     amfree(tapename);
423     amfree(conffile);
424     amfree(conf_tapelist);
425     amfree(config_dir);
426     config_name=NULL;
427
428     malloc_size_2 = malloc_inuse(&malloc_hist_2);
429
430     if(malloc_size_1 != malloc_size_2) {
431         malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
432     }
433
434     dbclose();
435     return 0;
436 }