1 /*
2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1998 University of Maryland at College Park
4 * Copyright (c) 2007-2013 Zmanda, Inc. All Rights Reserved.
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of U.M. not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. U.M. makes no representations about the
14 * suitability of this software for any purpose. It is provided "as is"
15 * without express or implied warranty.
16 *
17 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Author: James da Silva, Systems Design and Analysis Group
25 * Computer Science Department
26 * University of Maryland at College Park
27 */
28 /*
29 * $Id: diskfile.c,v 1.95 2006/07/26 15:17:37 martinea Exp $
30 *
31 * read disklist file
32 */
33 #include "amanda.h"
34 #include "match.h"
35 #include "arglist.h"
36 #include "conffile.h"
37 #include "diskfile.h"
38 #include "util.h"
39 #include "amxml.h"
40
41 static am_host_t *hostlist = NULL;
42 static netif_t *all_netifs = NULL;
43
44 /* local functions */
45 static char *upcase(char *st);
46 static int parse_diskline(disklist_t *, const char *, FILE *, int *, char **);
47 static void disk_parserror(const char *, int, const char *, ...)
48 G_GNUC_PRINTF(3, 4);
49
50
51 cfgerr_level_t
read_diskfile(const char * filename,disklist_t * lst)52 read_diskfile(
53 const char *filename,
54 disklist_t *lst)
55 {
56 FILE *diskf;
57 int line_num;
58 char *line = NULL;
59
60 /* initialize */
61 if (hostlist == NULL) {
62 lst->head = lst->tail = NULL;
63 }
64 line_num = 0;
65
66 /* if we already have config errors, then don't bother */
67 if (config_errors(NULL) >= CFGERR_ERRORS) {
68 return config_errors(NULL);
69 }
70
71 if ((diskf = fopen(filename, "r")) == NULL) {
72 config_add_error(CFGERR_ERRORS,
73 vstrallocf(_("Could not open '%s': %s"), filename, strerror(errno)));
74 goto end;
75 /*NOTREACHED*/
76 }
77
78 while ((line = agets(diskf)) != NULL) {
79 line_num++;
80 if (line[0] != '\0') {
81 if (parse_diskline(lst, filename, diskf, &line_num, &line) < 0) {
82 goto end;
83 }
84 }
85 amfree(line);
86 }
87
88 end:
89 amfree(line);
90 afclose(diskf);
91 return config_errors(NULL);
92 }
93
94 am_host_t *
get_hostlist(void)95 get_hostlist(void)
96 {
97 return hostlist;
98 }
99
100 am_host_t *
lookup_host(const char * hostname)101 lookup_host(
102 const char *hostname)
103 {
104 am_host_t *p;
105
106 for (p = hostlist; p != NULL; p = p->next) {
107 if(strcasecmp(p->hostname, hostname) == 0) return p;
108 }
109 return (NULL);
110 }
111
112 disk_t *
lookup_disk(const char * hostname,const char * diskname)113 lookup_disk(
114 const char *hostname,
115 const char *diskname)
116 {
117 am_host_t *host;
118 disk_t *disk;
119
120 host = lookup_host(hostname);
121 if (host == NULL)
122 return (NULL);
123
124 for (disk = host->disks; disk != NULL; disk = disk->hostnext) {
125 if (strcmp(disk->name, diskname) == 0)
126 return (disk);
127 }
128 return (NULL);
129 }
130
131
132 /*
133 * put disk on end of queue
134 */
135
136 void
enqueue_disk(disklist_t * list,disk_t * disk)137 enqueue_disk(
138 disklist_t *list,
139 disk_t * disk)
140 {
141 if(list->tail == NULL) list->head = disk;
142 else list->tail->next = disk;
143 disk->prev = list->tail;
144
145 list->tail = disk;
146 disk->next = NULL;
147 }
148
149
150 /*
151 * put disk on head of queue
152 */
153
154 void
headqueue_disk(disklist_t * list,disk_t * disk)155 headqueue_disk(
156 disklist_t *list,
157 disk_t * disk)
158 {
159 if(list->head == NULL) list->tail = disk;
160 else list->head->prev = disk;
161 disk->next = list->head;
162
163 list->head = disk;
164 disk->prev = NULL;
165 }
166
167
168 /*
169 * insert in sorted order
170 */
171
172 void
insert_disk(disklist_t * list,disk_t * disk,int (* cmp)(disk_t * a,disk_t * b))173 insert_disk(
174 disklist_t *list,
175 disk_t * disk,
176 int (*cmp)(disk_t *a, disk_t *b))
177 {
178 disk_t *prev, *ptr;
179
180 prev = NULL;
181 ptr = list->head;
182
183 while(ptr != NULL) {
184 if(cmp(disk, ptr) < 0) break;
185 prev = ptr;
186 ptr = ptr->next;
187 }
188 disk->next = ptr;
189 disk->prev = prev;
190
191 if(prev == NULL) list->head = disk;
192 else prev->next = disk;
193 if(ptr == NULL) list->tail = disk;
194 else ptr->prev = disk;
195 }
196
197 disk_t *
add_disk(disklist_t * list,char * hostname,char * diskname)198 add_disk(
199 disklist_t *list,
200 char * hostname,
201 char * diskname)
202 {
203 disk_t *disk;
204 am_host_t *host;
205
206 disk = alloc(SIZEOF(disk_t));
207 bzero(disk, SIZEOF(disk_t));
208 disk->line = 0;
209 disk->allow_split = 0;
210 disk->max_warnings = 20;
211 disk->splitsize = (off_t)0;
212 disk->tape_splitsize = (off_t)0;
213 disk->split_diskbuffer = NULL;
214 disk->fallback_splitsize = (off_t)0;
215 disk->hostname = stralloc(hostname);
216 disk->name = stralloc(diskname);
217 disk->device = stralloc(diskname);
218 disk->spindle = -1;
219 disk->up = NULL;
220 disk->compress = COMP_NONE;
221 disk->encrypt = ENCRYPT_NONE;
222 disk->start_t = 0;
223 disk->todo = 1;
224 disk->index = 1;
225 disk->exclude_list = NULL;
226 disk->exclude_file = NULL;
227 disk->include_list = NULL;
228 disk->include_file = NULL;
229 disk->application = NULL;
230 disk->pp_scriptlist = NULL;
231
232 host = lookup_host(hostname);
233 if(host == NULL) {
234 host = alloc(SIZEOF(am_host_t));
235 host->next = hostlist;
236 hostlist = host;
237
238 host->hostname = stralloc(hostname);
239 host->disks = NULL;
240 host->inprogress = 0;
241 host->maxdumps = 1;
242 host->netif = NULL;
243 host->start_t = 0;
244 host->up = NULL;
245 host->features = NULL;
246 host->pre_script = 0;
247 host->post_script = 0;
248 }
249 enqueue_disk(list, disk);
250
251 disk->host = host;
252 disk->hostnext = host->disks;
253 host->disks = disk;
254
255 return disk;
256 }
257
258
259 /*
260 * check if disk is present in list. Return true if so, false otherwise.
261 */
262
263 int
find_disk(disklist_t * list,disk_t * disk)264 find_disk(
265 disklist_t *list,
266 disk_t * disk)
267 {
268 disk_t *t;
269
270 t = list->head;
271 while ((t != NULL) && (t != disk)) {
272 t = t->next;
273 }
274 return (t == disk);
275 }
276
277
278 /*
279 * sort a whole queue
280 */
281
282 void
sort_disk(disklist_t * in,disklist_t * out,int (* cmp)(disk_t * a,disk_t * b))283 sort_disk(
284 disklist_t *in,
285 disklist_t *out,
286 int (*cmp)(disk_t *a, disk_t *b))
287 {
288 disklist_t *tmp;
289 disk_t *disk;
290
291 tmp = in; /* just in case in == out */
292
293 out->head = (disk_t *)0;
294 out->tail = (disk_t *)0;
295
296 while((disk = dequeue_disk(tmp)))
297 insert_disk(out, disk, cmp);
298 }
299
300
301 /*
302 * remove disk from front of queue
303 */
304
305 disk_t *
dequeue_disk(disklist_t * list)306 dequeue_disk(
307 disklist_t *list)
308 {
309 disk_t *disk;
310
311 if(list->head == NULL) return NULL;
312
313 disk = list->head;
314 list->head = disk->next;
315
316 if(list->head == NULL) list->tail = NULL;
317 else list->head->prev = NULL;
318
319 disk->prev = disk->next = NULL; /* for debugging */
320 return disk;
321 }
322
323 void
remove_disk(disklist_t * list,disk_t * disk)324 remove_disk(
325 disklist_t *list,
326 disk_t * disk)
327 {
328 if(disk->prev == NULL) list->head = disk->next;
329 else disk->prev->next = disk->next;
330
331 if(disk->next == NULL) list->tail = disk->prev;
332 else disk->next->prev = disk->prev;
333
334 disk->prev = disk->next = NULL;
335 }
336
337 void
unload_disklist(void)338 unload_disklist(void)
339 {
340 disk_t *dp, *dpnext;
341 am_host_t *host, *hostnext;
342 netif_t *netif, *next_if;
343
344 for(host=hostlist; host != NULL; host = hostnext) {
345 amfree(host->hostname);
346 am_release_feature_set(host->features);
347 host->features = NULL;
348 hostnext = host->next;
349 for (dp = host->disks; dp != NULL ; dp = dpnext) {
350 dpnext = dp->hostnext;
351 amfree(dp->filename);
352 amfree(dp->name);
353 amfree(dp->hostname);
354 amfree(dp->device);
355 free_sl(dp->exclude_file);
356 free_sl(dp->exclude_list);
357 free_sl(dp->include_file);
358 free_sl(dp->include_list);
359 free(dp);
360 }
361 amfree(host);
362 }
363 hostlist=NULL;
364
365 for (netif = all_netifs; netif != NULL; netif = next_if) {
366 next_if = netif->next;
367 amfree(netif);
368 }
369 all_netifs = NULL;
370 }
371
372 static char *
upcase(char * st)373 upcase(
374 char *st)
375 {
376 char *s = st;
377
378 while(*s) {
379 if(islower((int)*s)) *s = (char)toupper((int)*s);
380 s++;
381 }
382 return st;
383 }
384
385
386 /* return 0 on success */
387 /* return -1 on error */
388 static int
parse_diskline(disklist_t * lst,const char * filename,FILE * diskf,int * line_num_p,char ** line_p)389 parse_diskline(
390 disklist_t *lst,
391 const char *filename,
392 FILE * diskf,
393 int * line_num_p,
394 /*@keep@*/ char ** line_p)
395 {
396 am_host_t *host;
397 disk_t *disk;
398 dumptype_t *dtype;
399 netif_t *netif = NULL;
400 interface_t *cfg_if = NULL;
401 char *hostname = NULL;
402 char *diskname, *diskdevice;
403 char *dumptype;
404 char *s, *fp;
405 int ch, dup = 0;
406 char *line = *line_p;
407 int line_num = *line_num_p;
408 struct tm *stm;
409 time_t st;
410 char *shost, *sdisk;
411 am_host_t *p;
412 disk_t *dp;
413 identlist_t pp_iter;
414
415 assert(filename != NULL);
416 assert(line_num > 0);
417 assert(line != NULL);
418
419 s = line;
420 ch = *s++;
421 skip_whitespace(s, ch);
422 if(ch == '\0' || ch == '#')
423 return (0);
424
425 fp = s - 1;
426 skip_non_whitespace(s, ch);
427 s[-1] = '\0';
428 if (g_str_equal(fp, "includefile")) {
429 char *include_name;
430 char *include_filename;
431 skip_whitespace(s, ch);
432 if (ch == '\0' || ch == '#') {
433 disk_parserror(filename, line_num, _("include filename name expected"));
434 return (-1);
435 }
436 fp = s - 1;
437 skip_quoted_string(s, ch);
438 s[-1] = '\0';
439 include_name = unquote_string(fp);
440 include_filename = config_dir_relative(include_name);
441 read_diskfile(include_filename, lst);
442 g_free(include_filename);
443 g_free(include_name);
444 if (config_errors(NULL) >= CFGERR_WARNINGS) {
445 return -1;
446 } else {
447 return 0;
448 }
449 }
450 host = lookup_host(fp);
451 if (host == NULL) {
452 hostname = stralloc(fp);
453 } else {
454 hostname = stralloc(host->hostname);
455 if (strcmp(host->hostname, fp) != 0) {
456 disk_parserror(filename, line_num, _("Same host with different case: \"%s\" and \"%s\"."), host->hostname, fp);
457 return -1;
458 }
459 }
460
461 shost = sanitise_filename(hostname);
462 for (p = hostlist; p != NULL; p = p->next) {
463 char *shostp = sanitise_filename(p->hostname);
464 if (strcmp(hostname, p->hostname) &&
465 !strcmp(shost, shostp)) {
466 disk_parserror(filename, line_num, _("Two hosts are mapping to the same name: \"%s\" and \"%s\""), p->hostname, hostname);
467 return(-1);
468 }
469 else if (strcasecmp(hostname, p->hostname) &&
470 match_host(hostname, p->hostname) &&
471 match_host(p->hostname, hostname)) {
472 disk_parserror(filename, line_num, _("Duplicate host name: \"%s\" and \"%s\""), p->hostname, hostname);
473 return(-1);
474 }
475 amfree(shostp);
476 }
477 amfree(shost);
478
479 skip_whitespace(s, ch);
480 if(ch == '\0' || ch == '#') {
481 disk_parserror(filename, line_num, _("disk device name expected"));
482 amfree(hostname);
483 return (-1);
484 }
485
486 fp = s - 1;
487 skip_quoted_string(s, ch);
488 s[-1] = '\0';
489 diskname = unquote_string(fp);
490 if (strlen(diskname) == 0) {
491 disk_parserror(filename, line_num, _("invalid empty diskname"));
492 amfree(hostname);
493 return (-1);
494 }
495 skip_whitespace(s, ch);
496 if(ch == '\0' || ch == '#') {
497 disk_parserror(filename, line_num, _("disk dumptype expected"));
498 amfree(hostname);
499 amfree(diskname);
500 return (-1);
501 }
502 fp = s - 1;
503 skip_quoted_string(s, ch);
504 s[-1] = '\0';
505
506 /* diskdevice */
507 dumptype = NULL;
508 diskdevice = NULL;
509 if(fp[0] != '{') {
510 dumptype = unquote_string(fp);
511 if (strlen(dumptype) == 0) {
512 disk_parserror(filename, line_num, _("invalid empty diskdevice"));
513 amfree(hostname);
514 return (-1);
515 }
516 if (lookup_dumptype(dumptype) == NULL) {
517 diskdevice = dumptype;
518 skip_whitespace(s, ch);
519 if(ch == '\0' || ch == '#') {
520 disk_parserror(filename, line_num,
521 _("disk dumptype '%s' not found"), dumptype);
522 amfree(hostname);
523 amfree(diskdevice);
524 amfree(diskname);
525 return (-1);
526 }
527
528 fp = s - 1;
529 skip_quoted_string(s, ch);
530 s[-1] = '\0';
531 if (fp[0] != '{') {
532 dumptype = unquote_string(fp);
533 }
534 }
535 }
536
537 /* check for duplicate disk */
538 disk = NULL;
539 if (host) {
540 if ((disk = lookup_disk(hostname, diskname)) != NULL) {
541 dup = 1;
542 } else {
543 disk = host->disks;
544 do {
545 char *a1, *a2;
546 a1 = clean_regex(diskname, 1);
547 a2 = clean_regex(disk->name, 1);
548
549 if (match_disk(a1, disk->name) && match_disk(a2, diskname)) {
550 dup = 1;
551 } else {
552 disk = disk->hostnext;
553 }
554 amfree(a1);
555 amfree(a2);
556 }
557 while (dup == 0 && disk != NULL);
558 }
559 if (dup == 1) {
560 disk_parserror(filename, line_num,
561 _("duplicate disk record, previous on line %d"),
562 disk->line);
563 }
564 }
565 if (!disk) {
566 disk = alloc(SIZEOF(disk_t));
567 disk->filename = g_strdup(filename);
568 disk->line = line_num;
569 disk->hostname = hostname;
570 disk->name = diskname;
571 disk->device = diskdevice;
572 disk->spindle = -1;
573 disk->up = NULL;
574 disk->inprogress = 0;
575 disk->application = NULL;
576 disk->pp_scriptlist = NULL;
577 disk->dataport_list = NULL;
578 }
579
580 if (host) {
581 sdisk = sanitise_filename(diskname);
582 for (dp = host->disks; dp != NULL; dp = dp->hostnext) {
583 char *sdiskp = sanitise_filename(dp->name);
584 if (strcmp(diskname, dp->name) != 0 &&
585 strcmp(sdisk, sdiskp) == 0) {
586 disk_parserror(filename, line_num,
587 _("Two disks are mapping to the same name: \"%s\" and \"%s\"; you must use different diskname"),
588 dp->name, diskname);
589 return(-1);
590 }
591 amfree(sdiskp);
592 }
593 amfree(sdisk);
594 }
595
596 if (fp[0] == '{') {
597 s[-1] = (char)ch;
598 s = fp+2;
599 skip_whitespace(s, ch);
600 if (ch != '\0' && ch != '#') {
601 disk_parserror(filename, line_num,
602 _("expected line break after `{\', ignoring rest of line"));
603 }
604
605 if (strchr(s-1, '}') &&
606 (strchr(s-1, '#') == NULL ||
607 strchr(s-1, '}') < strchr(s-1, '#'))) {
608 disk_parserror(filename, line_num,_("'}' on same line than '{'"));
609 amfree(hostname);
610 if(!dup) {
611 amfree(disk->device);
612 amfree(disk->name);
613 amfree(disk);
614 } else {
615 amfree(diskdevice);
616 amfree(diskname);
617 }
618 return (-1);
619 }
620 dtype = read_dumptype(vstralloc("custom(", hostname,
621 ":", disk->name, ")",
622 ".", anonymous_value(), NULL),
623 diskf, (char*)filename, line_num_p);
624 if (dtype == NULL || dup) {
625 disk_parserror(filename, line_num,
626 _("read of custom dumptype failed"));
627 amfree(hostname);
628 if(!dup) {
629 amfree(disk->device);
630 amfree(disk->name);
631 amfree(disk);
632 } else {
633 amfree(diskdevice);
634 amfree(diskname);
635 }
636 return (-1);
637 }
638 amfree(line);
639
640 *line_p = line = agets(diskf);
641 line_num = *line_num_p; /* no incr, read_dumptype did it already */
642
643 if (line == NULL)
644 *line_p = line = stralloc("");
645 s = line;
646 ch = *s++;
647 } else {
648 if((dtype = lookup_dumptype(dumptype)) == NULL) {
649 char *qdt = quote_string(dumptype);
650
651 disk_parserror(filename, line_num, _("undefined dumptype `%s'"), qdt);
652 amfree(qdt);
653 amfree(hostname);
654 if (!dup) {
655 amfree(disk->device);
656 amfree(disk->name);
657 amfree(disk);
658 } else {
659 amfree(diskdevice);
660 amfree(diskname);
661 }
662 return (-1);
663 }
664 amfree(dumptype);
665 }
666
667 if (dup) {
668 /* disk_parserror already called, above */
669 g_assert(config_errors(NULL) != CFGERR_OK);
670 amfree(hostname);
671 amfree(diskdevice);
672 amfree(diskname);
673 return (-1);
674 }
675
676 disk->dtype_name = dumptype_name(dtype);
677 disk->config = dtype;
678 disk->program = dumptype_get_program(dtype);
679 disk->exclude_list = duplicate_sl(dumptype_get_exclude(dtype).sl_list);
680 disk->exclude_file = duplicate_sl(dumptype_get_exclude(dtype).sl_file);
681 disk->exclude_optional = dumptype_get_exclude(dtype).optional;
682 disk->include_list = duplicate_sl(dumptype_get_include(dtype).sl_list);
683 disk->include_file = duplicate_sl(dumptype_get_include(dtype).sl_file);
684 disk->include_optional = dumptype_get_include(dtype).optional;
685 disk->priority = dumptype_get_priority(dtype);
686 disk->dumpcycle = dumptype_get_dumpcycle(dtype);
687 /* disk->frequency = dumptype_get_frequency(dtype);*/
688 disk->auth = dumptype_get_auth(dtype);
689 disk->maxdumps = dumptype_get_maxdumps(dtype);
690 disk->allow_split = dumptype_get_allow_split(dtype);
691 disk->max_warnings = dumptype_get_max_warnings(dtype);
692 disk->tape_splitsize = dumptype_get_tape_splitsize(dtype);
693 disk->split_diskbuffer = dumptype_get_split_diskbuffer(dtype);
694 disk->fallback_splitsize = dumptype_get_fallback_splitsize(dtype);
695 if (disk->allow_split) {
696 tapetype_t *tapetype = lookup_tapetype(getconf_str(CNF_TAPETYPE));
697 disk->splitsize = tapetype_get_part_size(tapetype);
698 } else {
699 disk->splitsize = disk->tape_splitsize;
700 }
701 disk->maxpromoteday = dumptype_get_maxpromoteday(dtype);
702 disk->bumppercent = dumptype_get_bumppercent(dtype);
703 disk->bumpsize = dumptype_get_bumpsize(dtype);
704 disk->bumpdays = dumptype_get_bumpdays(dtype);
705 disk->bumpmult = dumptype_get_bumpmult(dtype);
706 disk->starttime = dumptype_get_starttime(dtype);
707 disk->application = dumptype_get_application(dtype);
708 disk->pp_scriptlist = dumptype_get_scriptlist(dtype);
709 disk->start_t = 0;
710 if (disk->starttime > 0) {
711 st = time(NULL);
712 disk->start_t = st;
713 stm = localtime(&st);
714 disk->start_t -= stm->tm_sec + 60 * stm->tm_min + 3600 * stm->tm_hour;
715 disk->start_t += disk->starttime / 100 * 3600 +
716 disk->starttime % 100 * 60;
717 if ((disk->start_t - st) < -43200)
718 disk->start_t += 86400;
719 }
720 disk->strategy = dumptype_get_strategy(dtype);
721 disk->ignore = dumptype_get_ignore(dtype);
722 disk->estimatelist = dumptype_get_estimatelist(dtype);
723 disk->compress = dumptype_get_compress(dtype);
724 disk->srvcompprog = dumptype_get_srvcompprog(dtype);
725 disk->clntcompprog = dumptype_get_clntcompprog(dtype);
726 disk->encrypt = dumptype_get_encrypt(dtype);
727 disk->srv_decrypt_opt = dumptype_get_srv_decrypt_opt(dtype);
728 disk->clnt_decrypt_opt = dumptype_get_clnt_decrypt_opt(dtype);
729 disk->srv_encrypt = dumptype_get_srv_encrypt(dtype);
730 disk->clnt_encrypt = dumptype_get_clnt_encrypt(dtype);
731 disk->amandad_path = dumptype_get_amandad_path(dtype);
732 disk->client_username = dumptype_get_client_username(dtype);
733 disk->client_port = dumptype_get_client_port(dtype);
734 disk->ssh_keys = dumptype_get_ssh_keys(dtype);
735 disk->comprate[0] = dumptype_get_comprate(dtype)[0];
736 disk->comprate[1] = dumptype_get_comprate(dtype)[1];
737 disk->data_path = dumptype_get_data_path(dtype);
738 disk->dump_limit = dumptype_get_dump_limit(dtype);
739
740 /*
741 * Boolean parameters with no value (Appears here as value 2) defaults
742 * to TRUE for backward compatibility and for logical consistency.
743 */
744 disk->record = dumptype_get_record(dtype) != 0;
745 disk->skip_incr = dumptype_get_skip_incr(dtype) != 0;
746 disk->skip_full = dumptype_get_skip_full(dtype) != 0;
747 disk->orig_holdingdisk = dumptype_get_to_holdingdisk(dtype);
748 disk->to_holdingdisk = disk->orig_holdingdisk;
749 disk->kencrypt = dumptype_get_kencrypt(dtype) != 0;
750 disk->index = dumptype_get_index(dtype) != 0;
751
752 disk->todo = 1;
753
754 skip_whitespace(s, ch);
755 fp = s - 1;
756 if(ch && ch != '#') { /* get optional spindle number */
757 char *fp1;
758 int is_digit=1;
759
760 skip_non_whitespace(s, ch);
761 s[-1] = '\0';
762 fp1=fp;
763 if (*fp1 == '-') fp1++;
764 for(;*fp1!='\0';fp1++) {
765 if(!isdigit((int)*fp1)) {
766 is_digit = 0;
767 }
768 }
769 if(is_digit == 0) {
770 disk_parserror(filename, line_num, _("non-integer spindle `%s'"), fp);
771 amfree(hostname);
772 amfree(disk->name);
773 amfree(disk);
774 return (-1);
775 }
776 disk->spindle = atoi(fp);
777 skip_integer(s, ch);
778 }
779
780 skip_whitespace(s, ch);
781 fp = s - 1;
782 if(ch && ch != '#') { /* get optional network interface */
783 skip_non_whitespace(s, ch);
784 s[-1] = '\0';
785 if((cfg_if = lookup_interface(upcase(fp))) == NULL) {
786 disk_parserror(filename, line_num,
787 _("undefined network interface `%s'"), fp);
788 amfree(hostname);
789 amfree(disk->name);
790 amfree(disk);
791 return (-1);
792 }
793 } else {
794 cfg_if = lookup_interface("default");
795 }
796
797 /* see if we already have a netif_t for this interface */
798 for (netif = all_netifs; netif != NULL; netif = netif->next) {
799 if (netif->config == cfg_if)
800 break;
801 }
802
803 /* nope; make up a new one */
804 if (!netif) {
805 netif = alloc(sizeof(*netif));
806 netif->next = all_netifs;
807 all_netifs = netif;
808 netif->config = cfg_if;
809 netif->curusage = 0;
810 }
811
812 skip_whitespace(s, ch);
813 if(ch && ch != '#') { /* now we have garbage, ignore it */
814 disk_parserror(filename, line_num, _("end of line expected"));
815 }
816
817 if (disk->program && disk->application &&
818 strcmp(disk->program,"APPLICATION")) {
819 disk_parserror(filename, line_num,
820 _("Both program and application set"));
821 }
822
823 if (disk->program && strcmp(disk->program,"APPLICATION")==0 &&
824 !disk->application) {
825 disk_parserror(filename, line_num,
826 _("program set to APPLICATION but no application set"));
827 }
828
829 if (disk->application) {
830 application_t *application;
831 char *plugin;
832
833 application = lookup_application(disk->application);
834 g_assert(application != NULL);
835 plugin = application_get_plugin(application);
836 if (!plugin || strlen(plugin) == 0) {
837 disk_parserror(filename, line_num,
838 _("plugin not set for application"));
839 }
840 }
841
842 for (pp_iter = disk->pp_scriptlist; pp_iter != NULL;
843 pp_iter = pp_iter->next) {
844 pp_script_t *pp_script;
845 char *plugin;
846 char *pp_script_name;
847
848 pp_script_name = (char*)pp_iter->data;
849 pp_script = lookup_pp_script(pp_script_name);
850 g_assert(pp_script != NULL);
851 plugin = pp_script_get_plugin(pp_script);
852 if (!plugin || strlen(plugin) == 0) {
853 disk_parserror(filename, line_num, _("plugin not set for script"));
854 }
855 }
856
857 /* success, add disk to lists */
858
859 if(host == NULL) { /* new host */
860 host = alloc(SIZEOF(am_host_t));
861 host->next = hostlist;
862 hostlist = host;
863
864 host->hostname = stralloc(hostname);
865 hostname = NULL;
866 host->disks = NULL;
867 host->inprogress = 0;
868 host->maxdumps = 1; /* will be overwritten */
869 host->netif = NULL;
870 host->start_t = 0;
871 host->up = NULL;
872 host->features = NULL;
873 host->pre_script = 0;
874 host->post_script = 0;
875 }
876
877 host->netif = netif;
878
879 enqueue_disk(lst, disk);
880
881 disk->host = host;
882 disk->hostnext = host->disks;
883 host->disks = disk;
884 host->maxdumps = disk->maxdumps;
885
886 return (0);
887 }
888
889
printf_arglist_function2(void disk_parserror,const char *,filename,int,line_num,const char *,format)890 printf_arglist_function2(void disk_parserror, const char *, filename,
891 int, line_num, const char *, format)
892 {
893 va_list argp;
894 char * msg;
895 char * errstr;
896
897 /* format the error message and hand it off to conffile */
898
899 arglist_start(argp, format);
900 msg = g_strdup_vprintf(format, argp);
901 errstr = g_strdup_printf("\"%s\", line %d: %s", filename, line_num, msg);
902 amfree(msg);
903 arglist_end(argp);
904
905 config_add_error(CFGERR_ERRORS, errstr);
906 }
907
908
909 void
dump_queue(char * st,disklist_t q,int npr,FILE * f)910 dump_queue(
911 char * st,
912 disklist_t q,
913 int npr, /* we print first npr disks on queue, plus last two */
914 FILE * f)
915 {
916 disk_t *d,*p;
917 int pos;
918 char *qname;
919
920 if(empty(q)) {
921 g_fprintf(f, _("%s QUEUE: empty\n"), st);
922 return;
923 }
924 g_fprintf(f, _("%s QUEUE:\n"), st);
925 for(pos = 0, d = q.head, p = NULL; d != NULL; p = d, d = d->next, pos++) {
926 qname = quote_string(d->name);
927 if(pos < npr) g_fprintf(f, "%3d: %-10s %-4s\n",
928 pos, d->host->hostname, qname);
929 amfree(qname);
930 }
931 if(pos > npr) {
932 if(pos > npr+2) g_fprintf(f, " ...\n");
933 if(pos > npr+1) {
934 d = p->prev;
935 g_fprintf(f, "%3d: %-10s %-4s\n", pos-2, d->host->hostname, d->name);
936 }
937 d = p;
938 g_fprintf(f, "%3d: %-10s %-4s\n", pos-1, d->host->hostname, d->name);
939 }
940 }
941
942 GPtrArray *
validate_optionstr(disk_t * dp)943 validate_optionstr(
944 disk_t *dp)
945 {
946 GPtrArray *errarray;
947 int nb_exclude;
948 int nb_include;
949 am_feature_t *their_features = dp->host->features;
950
951 assert(dp != NULL);
952 assert(dp->host != NULL);
953
954 errarray = g_ptr_array_new();
955
956 if (!am_has_feature(their_features, fe_options_auth)) {
957 if (strcasecmp(dp->auth, "bsd") == 0)
958 if (!am_has_feature(their_features, fe_options_bsd_auth))
959 g_ptr_array_add(errarray, _("does not support auth"));
960 }
961
962 switch(dp->compress) {
963 case COMP_FAST:
964 if (!am_has_feature(their_features, fe_options_compress_fast)) {
965 g_ptr_array_add(errarray, _("does not support fast compression"));
966 }
967 break;
968 case COMP_BEST:
969 if (!am_has_feature(their_features, fe_options_compress_best)) {
970 g_ptr_array_add(errarray, _("does not support best compression"));
971 }
972 break;
973 case COMP_CUST:
974 if (am_has_feature(their_features, fe_options_compress_cust)) {
975 if (dp->clntcompprog == NULL || strlen(dp->clntcompprog) == 0) {
976 g_ptr_array_add(errarray, _("client custom compression with no compression program specified"));
977 }
978 } else {
979 g_ptr_array_add(errarray, _("does not support client custom compression"));
980 }
981 break;
982 case COMP_SERVER_FAST:
983 break;
984 case COMP_SERVER_BEST:
985 break;
986 case COMP_SERVER_CUST:
987 if (dp->srvcompprog == NULL || strlen(dp->srvcompprog) == 0) {
988 g_ptr_array_add(errarray, _("server custom compression with no compression program specified"));
989 }
990 break;
991 }
992
993 switch(dp->encrypt) {
994 case ENCRYPT_CUST:
995 if (am_has_feature(their_features, fe_options_encrypt_cust)) {
996 if (dp->clnt_decrypt_opt) {
997 if (!am_has_feature(their_features, fe_options_client_decrypt_option)) {
998 g_ptr_array_add(errarray, _("does not support client decrypt option"));
999 }
1000 }
1001 if (dp->clnt_encrypt == NULL || strlen(dp->clnt_encrypt) == 0) {
1002 g_ptr_array_add(errarray, _("encrypt client with no encryption program specified"));
1003 }
1004 if (dp->compress == COMP_SERVER_FAST ||
1005 dp->compress == COMP_SERVER_BEST ||
1006 dp->compress == COMP_SERVER_CUST ) {
1007 g_ptr_array_add(errarray, _("Client encryption with server compression is not supported. See amanda.conf(5) for detail"));
1008 }
1009 } else {
1010 g_ptr_array_add(errarray, _("does not support client data encryption"));
1011 }
1012 break;
1013 case ENCRYPT_SERV_CUST:
1014 if (dp->srv_encrypt == NULL || strlen(dp->srv_encrypt) == 0) {
1015 g_ptr_array_add(errarray, _("No encryption program specified in dumptypes, Change the dumptype in the disklist or mention the encryption program to use in the dumptypes file"));
1016 }
1017 break;
1018 }
1019
1020 if (!dp->record) {
1021 if (!am_has_feature(their_features, fe_options_no_record)) {
1022 g_ptr_array_add(errarray, _("does not support no record"));
1023 }
1024 }
1025
1026 if (dp->index) {
1027 if (!am_has_feature(their_features, fe_options_index)) {
1028 g_ptr_array_add(errarray, _("does not support index"));
1029 }
1030 }
1031
1032 if (dp->kencrypt) {
1033 if (!am_has_feature(their_features, fe_options_kencrypt)) {
1034 g_ptr_array_add(errarray, _("does not support kencrypt"));
1035 }
1036 }
1037
1038 nb_exclude = 0;
1039 if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
1040 nb_exclude = dp->exclude_file->nb_element;
1041 if (!am_has_feature(their_features, fe_options_exclude_file)) {
1042 g_ptr_array_add(errarray, _("does not support exclude file"));
1043 }
1044 }
1045
1046 if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
1047 nb_exclude += dp->exclude_list->nb_element;
1048 if (!am_has_feature(their_features, fe_options_exclude_list)) {
1049 g_ptr_array_add(errarray, _("does not support exclude list"));
1050 }
1051 }
1052
1053 if (nb_exclude > 1 &&
1054 !am_has_feature(their_features, fe_options_multiple_exclude)) {
1055 g_ptr_array_add(errarray, _("does not support multiple exclude"));
1056 }
1057
1058 nb_include = 0;
1059 if (dp->include_file != NULL && dp->include_file->nb_element > 0) {
1060 nb_include = dp->include_file->nb_element;
1061 if (!am_has_feature(their_features, fe_options_include_file)) {
1062 g_ptr_array_add(errarray, ("does not support include file"));
1063 }
1064 }
1065
1066 if (dp->include_list != NULL && dp->include_list->nb_element > 0) {
1067 nb_include += dp->include_list->nb_element;
1068 if (!am_has_feature(their_features, fe_options_include_list)) {
1069 g_ptr_array_add(errarray, _("does not support include list"));
1070 }
1071 }
1072
1073 if (nb_include > 1 &&
1074 !am_has_feature(their_features, fe_options_multiple_exclude)) {
1075 g_ptr_array_add(errarray, _("does not support multiple include"));
1076 }
1077
1078 if (dp->exclude_optional) {
1079 if (!am_has_feature(their_features, fe_options_optional_exclude)) {
1080 g_ptr_array_add(errarray, _("does not support optional exclude"));
1081 }
1082 }
1083 if (dp->include_optional) {
1084 if (!am_has_feature(their_features, fe_options_optional_include)) {
1085 g_ptr_array_add(errarray, _("does not support optional include"));
1086 }
1087 }
1088
1089 return errarray;
1090 }
1091
1092 char *
optionstr(disk_t * dp)1093 optionstr(
1094 disk_t * dp)
1095 {
1096 char *auth_opt = NULL;
1097 char *kencrypt_opt = "";
1098 char *compress_opt = "";
1099 char *encrypt_opt = stralloc("");
1100 char *decrypt_opt = stralloc("");
1101 char *record_opt = "";
1102 char *index_opt = "";
1103 char *exclude_file = NULL;
1104 char *exclude_list = NULL;
1105 char *include_file = NULL;
1106 char *include_list = NULL;
1107 char *excl_opt = "";
1108 char *incl_opt = "";
1109 char *exc = NULL;
1110 char *result = NULL;
1111 sle_t *excl;
1112 char *qdpname;
1113 char *qname;
1114 am_feature_t *their_features = dp->host->features;
1115
1116 assert(dp != NULL);
1117 assert(dp->host != NULL);
1118
1119 qdpname = quote_string(dp->name);
1120 if (am_has_feature(their_features, fe_options_auth)) {
1121 auth_opt = vstralloc("auth=", dp->auth, ";", NULL);
1122 } else if(strcasecmp(dp->auth, "bsd") == 0) {
1123 if(am_has_feature(their_features, fe_options_bsd_auth))
1124 auth_opt = stralloc("bsd-auth;");
1125 }
1126
1127 switch(dp->compress) {
1128 case COMP_FAST:
1129 compress_opt = "compress-fast;";
1130 break;
1131 case COMP_BEST:
1132 compress_opt = "compress-best;";
1133 break;
1134 case COMP_CUST:
1135 compress_opt = vstralloc("comp-cust=", dp->clntcompprog, ";", NULL);
1136 break;
1137 case COMP_SERVER_FAST:
1138 compress_opt = "srvcomp-fast;";
1139 break;
1140 case COMP_SERVER_BEST:
1141 compress_opt = "srvcomp-best;";
1142 break;
1143 case COMP_SERVER_CUST:
1144 compress_opt = vstralloc("srvcomp-cust=", dp->srvcompprog, ";", NULL);
1145 break;
1146 }
1147
1148 switch(dp->encrypt) {
1149 case ENCRYPT_CUST:
1150 encrypt_opt = newvstralloc(encrypt_opt, "encrypt-cust=",
1151 dp->clnt_encrypt, ";", NULL);
1152 if (dp->clnt_decrypt_opt) {
1153 decrypt_opt = newvstralloc(decrypt_opt, "client-decrypt-option=",
1154 dp->clnt_decrypt_opt, ";", NULL);
1155 }
1156 break;
1157 case ENCRYPT_SERV_CUST:
1158 encrypt_opt = newvstralloc(encrypt_opt, "encrypt-serv-cust=",
1159 dp->srv_encrypt, ";", NULL);
1160 if (dp->srv_decrypt_opt) {
1161 decrypt_opt = newvstralloc(decrypt_opt, "server-decrypt-option=",
1162 dp->srv_decrypt_opt, ";", NULL);
1163 }
1164 break;
1165 }
1166
1167 if (!dp->record) {
1168 record_opt = "no-record;";
1169 }
1170
1171 if (dp->index) {
1172 index_opt = "index;";
1173 }
1174
1175 if (dp->kencrypt) {
1176 kencrypt_opt = "kencrypt;";
1177 }
1178
1179 exclude_file = stralloc("");
1180 if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
1181 for(excl = dp->exclude_file->first; excl != NULL;
1182 excl = excl->next) {
1183 qname = quote_string(excl->name);
1184 exc = newvstralloc( exc, "exclude-file=", qname, ";", NULL);
1185 strappend(exclude_file, exc);
1186 amfree(qname);
1187 }
1188 }
1189 exclude_list = stralloc("");
1190 if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
1191 for(excl = dp->exclude_list->first; excl != NULL;
1192 excl = excl->next) {
1193 qname = quote_string(excl->name);
1194 exc = newvstralloc( exc, "exclude-list=", qname, ";", NULL);
1195 strappend(exclude_list, exc);
1196 amfree(qname);
1197 }
1198 }
1199
1200 include_file = stralloc("");
1201 if (dp->include_file != NULL && dp->include_file->nb_element > 0) {
1202 for(excl = dp->include_file->first; excl != NULL;
1203 excl = excl->next) {
1204 qname = quote_string(excl->name);
1205 exc = newvstralloc(exc, "include-file=", qname, ";", NULL);
1206 strappend(include_file, exc);
1207 amfree(qname);
1208 }
1209 }
1210 include_list = stralloc("");
1211 if (dp->include_list != NULL && dp->include_list->nb_element > 0) {
1212 for(excl = dp->include_list->first; excl != NULL;
1213 excl = excl->next) {
1214 qname = quote_string(excl->name);
1215 exc = newvstralloc(exc, "include-list=", qname, ";", NULL);
1216 strappend(include_list, exc);
1217 amfree(qname);
1218 }
1219 }
1220
1221 if (dp->exclude_optional) {
1222 excl_opt = "exclude-optional;";
1223 }
1224 if (dp->include_optional) {
1225 incl_opt = "include-optional;";
1226 }
1227
1228 result = vstralloc(";",
1229 auth_opt,
1230 kencrypt_opt,
1231 compress_opt,
1232 encrypt_opt,
1233 decrypt_opt,
1234 record_opt,
1235 index_opt,
1236 exclude_file,
1237 exclude_list,
1238 include_file,
1239 include_list,
1240 excl_opt,
1241 incl_opt,
1242 NULL);
1243 amfree(qdpname);
1244 amfree(auth_opt);
1245 amfree(exclude_list);
1246 amfree(exclude_file);
1247 amfree(include_file);
1248 amfree(include_list);
1249 amfree(exc);
1250 amfree(decrypt_opt);
1251 amfree(encrypt_opt);
1252
1253 /* result contains at least 'auth=...' */
1254 return result;
1255 }
1256
1257 typedef struct {
1258 am_feature_t *features;
1259 char *result;
1260 } xml_app_t;
1261
1262 /* A GHFunc (callback for g_hash_table_foreach) */
xml_property(gpointer key_p,gpointer value_p,gpointer user_data_p)1263 static void xml_property(
1264 gpointer key_p,
1265 gpointer value_p,
1266 gpointer user_data_p)
1267 {
1268 char *tmp;
1269 property_t *property = value_p;
1270 xml_app_t *xml_app = user_data_p;
1271 GSList *value;
1272 GString *strbuf;
1273
1274 strbuf = g_string_new(xml_app->result);
1275
1276 tmp = amxml_format_tag("name", (char *)key_p);
1277 g_string_append_printf(strbuf, " <property>\n %s\n", tmp);
1278 g_free(tmp);
1279
1280 // TODO if client have fe_xml_property_priority
1281 if (property->priority
1282 && am_has_feature(xml_app->features, fe_xml_property_priority))
1283 g_string_append(strbuf, " <priority>yes</priority>\n");
1284
1285 for (value = property->values; value != NULL; value = value->next) {
1286 tmp = amxml_format_tag("value", value->data);
1287 g_string_append_printf(strbuf, " %s", tmp);
1288 g_free(tmp);
1289 }
1290 g_string_append_printf(strbuf, "\n </property>\n");
1291
1292 g_free(xml_app->result);
1293 xml_app->result = g_string_free(strbuf, FALSE);
1294 }
1295
1296 char *
xml_optionstr(disk_t * dp,int to_server)1297 xml_optionstr(
1298 disk_t * dp,
1299 int to_server)
1300 {
1301 char *auth_opt;
1302 char *kencrypt_opt;
1303 char *compress_opt;
1304 char *encrypt_opt = stralloc("");
1305 char *decrypt_opt = stralloc("");
1306 char *record_opt;
1307 char *index_opt;
1308 char *data_path_opt = stralloc("");
1309 char *exclude = stralloc("");
1310 char *exclude_file = NULL;
1311 char *exclude_list = NULL;
1312 char *include = stralloc("");
1313 char *include_file = NULL;
1314 char *include_list = NULL;
1315 char *excl_opt = "";
1316 char *incl_opt = "";
1317 char *exc = NULL;
1318 char *script_opt;
1319 char *result = NULL;
1320 sle_t *excl;
1321 char *qdpname;
1322 char *q64name;
1323 am_feature_t *their_features = dp->host->features;
1324
1325 assert(dp != NULL);
1326 assert(dp->host != NULL);
1327
1328 qdpname = quote_string(dp->name);
1329 if (am_has_feature(their_features, fe_options_auth)) {
1330 auth_opt = vstralloc(" <auth>", dp->auth, "</auth>\n", NULL);
1331 } else {
1332 auth_opt = stralloc("");
1333 }
1334
1335 switch(dp->compress) {
1336 case COMP_FAST:
1337 compress_opt = stralloc(" <compress>FAST</compress>\n");
1338 break;
1339 case COMP_BEST:
1340 compress_opt = stralloc(" <compress>BEST</compress>\n");
1341 break;
1342 case COMP_CUST:
1343 compress_opt = vstralloc(" <compress>CUSTOM"
1344 "<custom-compress-program>",
1345 dp->clntcompprog,
1346 "</custom-compress-program>\n"
1347 " </compress>\n", NULL);
1348 break;
1349 case COMP_SERVER_FAST:
1350 compress_opt = stralloc(" <compress>SERVER-FAST</compress>\n");
1351 break;
1352 case COMP_SERVER_BEST:
1353 compress_opt = stralloc(" <compress>SERVER-BEST</compress>\n");
1354 break;
1355 case COMP_SERVER_CUST:
1356 compress_opt = vstralloc(" <compress>SERVER-CUSTOM"
1357 "<custom-compress-program>",
1358 dp->srvcompprog,
1359 "</custom-compress-program>\n"
1360 " </compress>\n", NULL);
1361 break;
1362 default:
1363 compress_opt = stralloc("");
1364 }
1365
1366 switch(dp->encrypt) {
1367 case ENCRYPT_CUST:
1368 if (dp->clnt_decrypt_opt) {
1369 decrypt_opt = newvstralloc(decrypt_opt,
1370 " <decrypt-option>",
1371 dp->clnt_decrypt_opt,
1372 "</decrypt-option>\n", NULL);
1373 }
1374 if (decrypt_opt) {
1375 encrypt_opt = newvstralloc(encrypt_opt,
1376 " <encrypt>CUSTOM"
1377 "<custom-encrypt-program>",
1378 dp->clnt_encrypt,
1379 "</custom-encrypt-program>\n",
1380 decrypt_opt,
1381 " </encrypt>\n", NULL);
1382 }
1383 break;
1384 case ENCRYPT_SERV_CUST:
1385 if (to_server) {
1386 decrypt_opt = newvstralloc(decrypt_opt,
1387 " <decrypt-option>",
1388 dp->srv_decrypt_opt,
1389 "</decrypt-option>\n", NULL);
1390 encrypt_opt = newvstralloc(encrypt_opt,
1391 " <encrypt>SERVER-CUSTOM"
1392 "<custom-encrypt-program>",
1393 dp->srv_encrypt,
1394 "</custom-encrypt-program>\n",
1395 decrypt_opt,
1396 " </encrypt>\n", NULL);
1397 }
1398 break;
1399 }
1400
1401 if (!dp->record) {
1402 record_opt = " <record>NO</record>\n";
1403 } else {
1404 record_opt = " <record>YES</record>\n";
1405 }
1406
1407 if(dp->index) {
1408 index_opt = " <index>YES</index>\n";
1409 } else {
1410 index_opt = "";
1411 }
1412
1413 if (dp->kencrypt) {
1414 kencrypt_opt = " <kencrypt>YES</kencrypt>\n";
1415 } else {
1416 kencrypt_opt = "";
1417 }
1418
1419 if (am_has_feature(their_features, fe_xml_data_path)) {
1420 switch(dp->data_path) {
1421 case DATA_PATH_AMANDA:
1422 amfree(data_path_opt);
1423 data_path_opt = stralloc(" <datapath>AMANDA</datapath>\n");
1424 break;
1425 case DATA_PATH_DIRECTTCP:
1426 { /* dp->dataport_list is not set for selfcheck/sendsize */
1427 if (am_has_feature(their_features, fe_xml_directtcp_list)) {
1428 char *s, *sc;
1429 char *value, *b64value;
1430
1431 amfree(data_path_opt);
1432 data_path_opt = stralloc(" <datapath>DIRECTTCP");
1433 if (dp->dataport_list) {
1434 s = sc = stralloc(dp->dataport_list);
1435 do {
1436 value = s;
1437 s = strchr(s, ';');
1438 if (s) {
1439 *s++ = '\0';
1440 }
1441
1442 b64value = amxml_format_tag("directtcp", value);
1443 vstrextend(&data_path_opt, "\n ", b64value, NULL);
1444 amfree(b64value);
1445 } while (s);
1446 amfree(sc);
1447 strappend(data_path_opt, "\n ");
1448 }
1449 strappend(data_path_opt, "</datapath>\n");
1450 }
1451 }
1452 break;
1453 }
1454 }
1455
1456 exclude_file = stralloc("");
1457 if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
1458 for(excl = dp->exclude_file->first; excl != NULL;
1459 excl = excl->next) {
1460 q64name = amxml_format_tag("file", excl->name);
1461 exc = newvstralloc( exc, " ", q64name, "\n", NULL);
1462 strappend(exclude_file, exc);
1463 amfree(q64name);
1464 }
1465 }
1466 exclude_list = stralloc("");
1467 if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
1468 for(excl = dp->exclude_list->first; excl != NULL;
1469 excl = excl->next) {
1470 q64name = amxml_format_tag("list", excl->name);
1471 exc = newvstralloc(exc, " ", q64name, "\n", NULL);
1472 strappend(exclude_list, exc);
1473 amfree(q64name);
1474 }
1475 }
1476
1477 include_file = stralloc("");
1478 if (dp->include_file != NULL && dp->include_file->nb_element > 0) {
1479 for(excl = dp->include_file->first; excl != NULL;
1480 excl = excl->next) {
1481 q64name = amxml_format_tag("file", excl->name);
1482 exc = newvstralloc( exc, " ", q64name, "\n", NULL);
1483 strappend(include_file, exc);
1484 amfree(q64name);
1485 }
1486 }
1487 include_list = stralloc("");
1488 if (dp->include_list != NULL && dp->include_list->nb_element > 0) {
1489 for(excl = dp->include_list->first; excl != NULL;
1490 excl = excl->next) {
1491 q64name = amxml_format_tag("list", excl->name);
1492 exc = newvstralloc( exc, " ", q64name, "\n", NULL);
1493 strappend(include_list, exc);
1494 amfree(q64name);
1495 }
1496 }
1497
1498 if (dp->exclude_optional) {
1499 excl_opt = " <optional>YES</optional>\n";
1500 }
1501 if (dp->include_optional) {
1502 incl_opt = " <optional>YES</optional>\n";
1503 }
1504
1505 if (dp->exclude_file || dp->exclude_list)
1506 exclude = newvstralloc(exclude,
1507 " <exclude>\n",
1508 exclude_file,
1509 exclude_list,
1510 excl_opt,
1511 " </exclude>\n", NULL);
1512 if (dp->include_file || dp->include_list)
1513 include = newvstralloc(include,
1514 " <include>\n",
1515 include_file,
1516 include_list,
1517 incl_opt,
1518 " </include>\n", NULL);
1519 script_opt = xml_scripts(dp->pp_scriptlist, their_features);
1520 result = vstralloc(auth_opt,
1521 kencrypt_opt,
1522 compress_opt,
1523 encrypt_opt,
1524 record_opt,
1525 index_opt,
1526 data_path_opt,
1527 exclude,
1528 include,
1529 script_opt,
1530 NULL);
1531
1532 amfree(qdpname);
1533 amfree(auth_opt);
1534 amfree(data_path_opt);
1535 amfree(compress_opt);
1536 amfree(exclude);
1537 amfree(exclude_list);
1538 amfree(exclude_file);
1539 amfree(include);
1540 amfree(include_file);
1541 amfree(include_list);
1542 amfree(exc);
1543 amfree(decrypt_opt);
1544 amfree(encrypt_opt);
1545 amfree(script_opt);
1546
1547 /* result contains at least 'auth=...' */
1548 return result;
1549 }
1550
1551 char *
xml_dumptype_properties(disk_t * dp)1552 xml_dumptype_properties(
1553 disk_t *dp)
1554 {
1555 xml_app_t xml_dumptype;
1556
1557 xml_dumptype.result = g_strdup("");
1558 xml_dumptype.features = NULL;
1559 if (dp && dp->config) {
1560 g_hash_table_foreach(dumptype_get_property(dp->config), xml_property,
1561 &xml_dumptype);
1562 }
1563 return xml_dumptype.result;
1564 }
1565
1566 char *
xml_estimate(estimatelist_t estimatelist,am_feature_t * their_features)1567 xml_estimate(
1568 estimatelist_t estimatelist,
1569 am_feature_t *their_features)
1570 {
1571 estimatelist_t el;
1572 char *l = NULL;
1573
1574 if (am_has_feature(their_features, fe_xml_estimatelist)) {
1575 vstrextend(&l, " <estimate>", NULL);
1576 for (el=estimatelist; el != NULL; el = el->next) {
1577 switch (GPOINTER_TO_INT(el->data)) {
1578 case ES_CLIENT : vstrextend(&l, "CLIENT ", NULL); break;
1579 case ES_SERVER : vstrextend(&l, "SERVER ", NULL); break;
1580 case ES_CALCSIZE: vstrextend(&l, "CALCSIZE ", NULL); break;
1581 }
1582 }
1583 vstrextend(&l, "</estimate>", NULL);
1584 } else { /* add the first estimate only */
1585 if (am_has_feature(their_features, fe_xml_estimate)) {
1586 vstrextend(&l, " <estimate>", NULL);
1587 switch (GPOINTER_TO_INT(estimatelist->data)) {
1588 case ES_CLIENT : vstrextend(&l, "CLIENT", NULL); break;
1589 case ES_SERVER : vstrextend(&l, "SERVER", NULL); break;
1590 case ES_CALCSIZE: vstrextend(&l, "CALCSIZE", NULL); break;
1591 }
1592 }
1593 vstrextend(&l, "</estimate>", NULL);
1594 if (GPOINTER_TO_INT(estimatelist->data) == ES_CALCSIZE) {
1595 vstrextend(&l, " <calcsize>YES</calcsize>", NULL);
1596 }
1597 }
1598
1599 return l;
1600 }
1601
1602 char *
clean_dle_str_for_client(char * dle_str,am_feature_t * their_features)1603 clean_dle_str_for_client(
1604 char *dle_str,
1605 am_feature_t *their_features)
1606 {
1607 char *rval_dle_str;
1608 char *hack1, *hack2;
1609 char *pend, *pscript, *pproperty, *eproperty;
1610 int len;
1611
1612 if (!dle_str)
1613 return NULL;
1614
1615 rval_dle_str = stralloc(dle_str);
1616
1617 /* Remove everything between " <encrypt>SERVER-CUSTOM" and "</encrypt>\n"
1618 */
1619 #define SC "</encrypt>\n"
1620 #define SC_LEN strlen(SC)
1621 hack1 = strstr(rval_dle_str, " <encrypt>SERVER-CUSTOM");
1622 if (hack1) {
1623 hack2 = strstr(hack1, SC);
1624 /* +1 is to also move the trailing '\0' */
1625 memmove(hack1, hack2 + SC_LEN, strlen(hack2 + SC_LEN) + 1);
1626 }
1627 #undef SC
1628 #undef SC_LEN
1629
1630 if (!am_has_feature(their_features, fe_dumptype_property)) {
1631 #define SC "</property>\n"
1632 #define SC_LEN strlen(SC)
1633 /* remove all dle properties, they are before backup-program or script
1634 properties */
1635 hack1 = rval_dle_str;
1636 pend = strstr(rval_dle_str, "<backup-program>");
1637 pscript = strstr(rval_dle_str, "<script>");
1638 if (pscript && pscript < pend)
1639 pend = pscript;
1640 if (!pend) /* the complete string */
1641 pend = rval_dle_str + strlen(rval_dle_str);
1642 while (hack1) {
1643 pproperty = strstr(hack1, " <property>");
1644 if (pproperty && pproperty < pend) { /* remove it */
1645 eproperty = strstr(pproperty, SC);
1646 len = eproperty + SC_LEN - pproperty;
1647 memmove(pproperty, eproperty + SC_LEN, strlen(eproperty + SC_LEN) + 1);
1648 pend -= len;
1649 hack1 = pproperty;
1650 } else {
1651 hack1 = NULL;
1652 }
1653 }
1654 } else {
1655 }
1656 #undef SC
1657 #undef SC_LEN
1658
1659 return rval_dle_str;
1660 }
1661
1662
1663 char *
xml_application(disk_t * dp G_GNUC_UNUSED,application_t * application,am_feature_t * their_features)1664 xml_application(
1665 disk_t *dp G_GNUC_UNUSED,
1666 application_t *application,
1667 am_feature_t *their_features)
1668 {
1669 char *plugin;
1670 char *b64plugin;
1671 char *client_name;
1672 xml_app_t xml_app;
1673 proplist_t proplist;
1674
1675 xml_app.features = their_features;
1676 xml_app.result = NULL;
1677 plugin = application_get_plugin(application);
1678 b64plugin = amxml_format_tag("plugin", plugin);
1679 xml_app.result = vstralloc(" <backup-program>\n",
1680 " ", b64plugin, "\n",
1681 NULL);
1682 proplist = application_get_property(application);
1683 g_hash_table_foreach(proplist, xml_property, &xml_app);
1684
1685 client_name = application_get_client_name(application);
1686 if (client_name && strlen(client_name) > 0 &&
1687 am_has_feature(their_features, fe_application_client_name)) {
1688 char *b64client_name = amxml_format_tag("client_name", client_name);
1689 vstrextend(&xml_app.result, " ", b64client_name, "\n", NULL);
1690 }
1691
1692 vstrextend(&xml_app.result, " </backup-program>\n", NULL);
1693
1694 amfree(b64plugin);
1695
1696 return xml_app.result;
1697 }
1698
1699
1700 char *
xml_scripts(identlist_t pp_scriptlist,am_feature_t * their_features)1701 xml_scripts(
1702 identlist_t pp_scriptlist,
1703 am_feature_t *their_features)
1704 {
1705 char *plugin;
1706 char *b64plugin;
1707 char *client_name;
1708 char *xml_scr;
1709 char *xml_scr1;
1710 char *str = "";
1711 char *sep;
1712 char *eo_str;
1713 execute_on_t execute_on;
1714 int execute_where;
1715 proplist_t proplist;
1716 identlist_t pp_iter;
1717 pp_script_t *pp_script;
1718 xml_app_t xml_app;
1719
1720 xml_app.features = their_features;
1721
1722 xml_scr = stralloc("");
1723 for (pp_iter = pp_scriptlist; pp_iter != NULL;
1724 pp_iter = pp_iter->next) {
1725 char *pp_script_name = pp_iter->data;
1726 pp_script = lookup_pp_script(pp_script_name);
1727 g_assert(pp_script != NULL);
1728 plugin = pp_script_get_plugin(pp_script);
1729 b64plugin = amxml_format_tag("plugin", plugin);
1730 xml_scr1 = vstralloc(" <script>\n",
1731 " ", b64plugin, "\n",
1732 NULL);
1733
1734 execute_where = pp_script_get_execute_where(pp_script);
1735 switch (execute_where) {
1736 case ES_CLIENT: str = "CLIENT"; break;
1737 case ES_SERVER: str = "SERVER"; break;
1738 }
1739 xml_scr1 = vstrextend(&xml_scr1, " <execute_where>",
1740 str, "</execute_where>\n", NULL);
1741
1742 execute_on = pp_script_get_execute_on(pp_script);
1743 sep = "";
1744 eo_str = stralloc("");
1745 if (execute_on & EXECUTE_ON_PRE_DLE_AMCHECK) {
1746 eo_str = vstrextend(&eo_str, sep, "PRE-DLE-AMCHECK", NULL);
1747 sep = ",";
1748 }
1749 if (execute_on & EXECUTE_ON_PRE_HOST_AMCHECK) {
1750 eo_str = vstrextend(&eo_str, sep, "PRE-HOST-AMCHECK", NULL);
1751 sep = ",";
1752 }
1753 if (execute_on & EXECUTE_ON_POST_DLE_AMCHECK) {
1754 eo_str = vstrextend(&eo_str, sep, "POST-DLE-AMCHECK", NULL);
1755 sep = ",";
1756 }
1757 if (execute_on & EXECUTE_ON_POST_HOST_AMCHECK) {
1758 eo_str = vstrextend(&eo_str, sep, "POST-HOST-AMCHECK", NULL);
1759 sep = ",";
1760 }
1761 if (execute_on & EXECUTE_ON_PRE_DLE_ESTIMATE) {
1762 eo_str = vstrextend(&eo_str, sep, "PRE-DLE-ESTIMATE", NULL);
1763 sep = ",";
1764 }
1765 if (execute_on & EXECUTE_ON_PRE_HOST_ESTIMATE) {
1766 eo_str = vstrextend(&eo_str, sep, "PRE-HOST-ESTIMATE", NULL);
1767 sep = ",";
1768 }
1769 if (execute_on & EXECUTE_ON_POST_DLE_ESTIMATE) {
1770 eo_str = vstrextend(&eo_str, sep, "POST-DLE-ESTIMATE", NULL);
1771 sep = ",";
1772 }
1773 if (execute_on & EXECUTE_ON_POST_HOST_ESTIMATE) {
1774 eo_str = vstrextend(&eo_str, sep, "POST-HOST-ESTIMATE", NULL);
1775 sep = ",";
1776 }
1777 if (execute_on & EXECUTE_ON_PRE_DLE_BACKUP) {
1778 eo_str = vstrextend(&eo_str, sep, "PRE-DLE-BACKUP", NULL);
1779 sep = ",";
1780 }
1781 if (execute_on & EXECUTE_ON_PRE_HOST_BACKUP) {
1782 eo_str = vstrextend(&eo_str, sep, "PRE-HOST-BACKUP", NULL);
1783 sep = ",";
1784 }
1785 if (execute_on & EXECUTE_ON_POST_DLE_BACKUP) {
1786 eo_str = vstrextend(&eo_str, sep, "POST-DLE-BACKUP", NULL);
1787 sep = ",";
1788 }
1789 if (execute_on & EXECUTE_ON_POST_HOST_BACKUP) {
1790 eo_str = vstrextend(&eo_str, sep, "POST-HOST-BACKUP", NULL);
1791 sep = ",";
1792 }
1793 if (execute_on & EXECUTE_ON_PRE_RECOVER) {
1794 eo_str = vstrextend(&eo_str, sep, "PRE-RECOVER", NULL);
1795 sep = ",";
1796 }
1797 if (execute_on & EXECUTE_ON_POST_RECOVER) {
1798 eo_str = vstrextend(&eo_str, sep, "POST-RECOVER", NULL);
1799 sep = ",";
1800 }
1801 if (execute_on & EXECUTE_ON_PRE_LEVEL_RECOVER) {
1802 eo_str = vstrextend(&eo_str, sep, "PRE-LEVEL-RECOVER", NULL);
1803 sep = ",";
1804 }
1805 if (execute_on & EXECUTE_ON_POST_LEVEL_RECOVER) {
1806 eo_str = vstrextend(&eo_str, sep, "POST-LEVEL-RECOVER", NULL);
1807 sep = ",";
1808 }
1809 if (execute_on & EXECUTE_ON_INTER_LEVEL_RECOVER) {
1810 eo_str = vstrextend(&eo_str, sep, "INTER-LEVEL-RECOVER", NULL);
1811 sep = ",";
1812 }
1813 if (execute_on != 0)
1814 xml_scr1 = vstrextend(&xml_scr1,
1815 " <execute_on>", eo_str,
1816 "</execute_on>\n", NULL);
1817 amfree(eo_str);
1818 proplist = pp_script_get_property(pp_script);
1819 xml_app.result = stralloc("");
1820 g_hash_table_foreach(proplist, xml_property, &xml_app);
1821
1822 client_name = pp_script_get_client_name(pp_script);
1823 if (client_name && strlen(client_name) > 0 &&
1824 am_has_feature(their_features, fe_script_client_name)) {
1825 char *b64client_name = amxml_format_tag("client_name",
1826 client_name);
1827 vstrextend(&xml_app.result, " ", b64client_name, "\n", NULL);
1828 }
1829
1830 xml_scr = vstrextend(&xml_scr, xml_scr1, xml_app.result, " </script>\n", NULL);
1831 amfree(b64plugin);
1832 amfree(xml_app.result);
1833 amfree(xml_scr1);
1834 }
1835 return xml_scr;
1836 }
1837
1838
1839 void
disable_skip_disk(disklist_t * origqp)1840 disable_skip_disk(
1841 disklist_t *origqp)
1842 {
1843 disk_t *dp;
1844
1845 for (dp = origqp->head; dp != NULL; dp = dp->next) {
1846 if (dp->ignore || dp->strategy == DS_SKIP)
1847 dp->todo = 0;
1848 }
1849 }
1850
1851
1852 char *
match_disklist(disklist_t * origqp,gboolean exact_match,int sargc,char ** sargv)1853 match_disklist(
1854 disklist_t *origqp,
1855 gboolean exact_match,
1856 int sargc,
1857 char ** sargv)
1858 {
1859 char *prevhost = NULL;
1860 char *errstr = NULL;
1861 int i;
1862 int match_a_host;
1863 int match_a_disk;
1864 int prev_match;
1865 disk_t *dp_skip;
1866 disk_t *dp;
1867 char **new_sargv = NULL;
1868
1869 if(sargc <= 0)
1870 return NULL;
1871
1872 if (exact_match) {
1873 new_sargv = g_new0(char *, sargc+1);
1874 for (i=0; i<sargc; i++) {
1875 if (*sargv[i] == '=') {
1876 new_sargv[i] = g_strdup(sargv[i]);
1877 } else {
1878 new_sargv[i] = g_strconcat("=", sargv[i], NULL);
1879 }
1880 }
1881 sargv = new_sargv;
1882 }
1883
1884
1885 for(dp = origqp->head; dp != NULL; dp = dp->next) {
1886 if(dp->todo == 1)
1887 dp->todo = -1;
1888 }
1889
1890 prev_match = 0;
1891 for(i=0;i<sargc;i++) {
1892 match_a_host = 0;
1893 for(dp = origqp->head; dp != NULL; dp = dp->next) {
1894 if(match_host(sargv[i], dp->host->hostname))
1895 match_a_host = 1;
1896 }
1897 match_a_disk = 0;
1898 dp_skip = NULL;
1899 for(dp = origqp->head; dp != NULL; dp = dp->next) {
1900 if(prevhost != NULL &&
1901 match_host(prevhost, dp->host->hostname) &&
1902 (match_disk(sargv[i], dp->name) ||
1903 (dp->device && match_disk(sargv[i], dp->device)))) {
1904 if(match_a_host) {
1905 error(_("Argument %s cannot be both a host and a disk"),sargv[i]);
1906 /*NOTREACHED*/
1907 }
1908 else {
1909 if(dp->todo == -1) {
1910 dp->todo = 1;
1911 match_a_disk = 1;
1912 prev_match = 0;
1913 } else if (dp->todo == 0) {
1914 match_a_disk = 1;
1915 prev_match = 0;
1916 dp_skip = dp;
1917 } else { /* dp->todo == 1 */
1918 match_a_disk = 1;
1919 prev_match = 0;
1920 }
1921 }
1922 }
1923 }
1924 if(!match_a_disk) {
1925 if(match_a_host == 1) {
1926 if(prev_match == 1) { /* all disk of the previous host */
1927 for(dp = origqp->head; dp != NULL; dp = dp->next) {
1928 if(match_host(prevhost,dp->host->hostname))
1929 if(dp->todo == -1) {
1930 dp->todo = 1;
1931 match_a_disk = 1;
1932 }
1933 }
1934 if (!match_a_disk) {
1935 char *errstr1;
1936 errstr1 = vstrallocf(_("All disks on host '%s' are ignored or have strategy \"skip\".\n"), prevhost);
1937 vstrextend(&errstr, errstr1, NULL);
1938 amfree(errstr1);
1939 }
1940 }
1941 prevhost = sargv[i];
1942 prev_match = 1;
1943 }
1944 else {
1945 char *errstr1;
1946 if (strchr(sargv[i], (int)'\\')) {
1947 errstr1 = vstrallocf(_("Argument '%s' matches neither a host nor a disk; quoting may not be correct.\n"), sargv[i]);
1948 } else {
1949 errstr1 = vstrallocf(_("Argument '%s' matches neither a host nor a disk.\n"), sargv[i]);
1950 }
1951 vstrextend(&errstr, errstr1, NULL);
1952 amfree(errstr1);
1953 prev_match = 0;
1954 }
1955 } else if (dp_skip) {
1956 char *errstr1;
1957 if (dp_skip->strategy == DS_SKIP) {
1958 errstr1 = vstrallocf(_("Argument '%s' matches a disk with strategy \"skip\".\n"), sargv[i]);
1959 } else {
1960 errstr1 = vstrallocf(_("Argument '%s' matches a disk marked \"ignore\".\n"), sargv[i]);
1961 }
1962 vstrextend(&errstr, errstr1, NULL);
1963 amfree(errstr1);
1964 prev_match = 0;
1965 }
1966 }
1967
1968 if(prev_match == 1) { /* all disk of the previous host */
1969 match_a_disk = 0;
1970 for(dp = origqp->head; dp != NULL; dp = dp->next) {
1971 if(match_host(prevhost,dp->host->hostname))
1972 if(dp->todo == -1) {
1973 dp->todo = 1;
1974 match_a_disk = 1;
1975 }
1976 }
1977 if (!match_a_disk) {
1978 char *errstr1;
1979 errstr1 = vstrallocf(_("All disks on host '%s' are ignored or have strategy \"skip\".\n"), prevhost);
1980 vstrextend(&errstr, errstr1, NULL);
1981 amfree(errstr1);
1982 }
1983 }
1984
1985 for(dp = origqp->head; dp != NULL; dp = dp->next) {
1986 if(dp->todo == -1)
1987 dp->todo = 0;
1988 }
1989
1990 if (new_sargv) {
1991 for (i=0; i<sargc; i++)
1992 g_free(new_sargv[i]);
1993 g_free(new_sargv);
1994 }
1995 return errstr;
1996 }
1997
1998 gboolean
match_dumpfile(dumpfile_t * file,gboolean exact_match,int sargc,char ** sargv)1999 match_dumpfile(
2000 dumpfile_t *file,
2001 gboolean exact_match,
2002 int sargc,
2003 char ** sargv)
2004 {
2005 disk_t d;
2006 am_host_t h;
2007 disklist_t dl;
2008
2009 /* rather than try to reproduce the adaptive matching logic in
2010 * match_disklist, this simply creates a new, fake disklist with one
2011 * element in it, and calls match_disklist directly */
2012
2013 bzero(&h, sizeof(h));
2014 h.hostname = file->name;
2015 h.disks = &d;
2016
2017 bzero(&d, sizeof(d));
2018 d.host = &h;
2019 d.hostname = file->name;
2020 d.name = file->disk;
2021 d.device = file->disk;
2022 d.todo = 1;
2023
2024 dl.head = dl.tail = &d;
2025
2026 (void)match_disklist(&dl, exact_match, sargc, sargv);
2027 return d.todo;
2028 }
2029
2030 netif_t *
disklist_netifs(void)2031 disklist_netifs(void)
2032 {
2033 return all_netifs;
2034 }
2035
2036 #ifdef TEST
2037
2038 static void dump_disk(const disk_t *);
2039 static void dump_disklist(const disklist_t *);
2040 int main(int, char *[]);
2041
2042 static void
dump_disk(const disk_t * dp)2043 dump_disk(
2044 const disk_t * dp)
2045 {
2046 g_printf(_(" DISK %s (HOST %s, LINE %d) TYPE %s NAME %s SPINDLE %d\n"),
2047 dp->name, dp->host->hostname, dp->line, dp->dtype_name,
2048 dp->name == NULL? "(null)": dp->name,
2049 dp->spindle);
2050 }
2051
2052 static void
dump_disklist(const disklist_t * lst)2053 dump_disklist(
2054 const disklist_t * lst)
2055 {
2056 const disk_t *dp, *prev;
2057 const am_host_t *hp;
2058
2059 if(hostlist == NULL) {
2060 g_printf(_("DISKLIST not read in\n"));
2061 return;
2062 }
2063
2064 g_printf(_("DISKLIST BY HOSTNAME:\n"));
2065
2066 for(hp = hostlist; hp != NULL; hp = hp->next) {
2067 char *if_name = NULL;
2068 if (hp->netif && hp->netif->config)
2069 if_name = interface_name(hp->netif->config);
2070
2071 g_printf(_("HOST %s INTERFACE %s\n"),
2072 hp->hostname,
2073 if_name ? _("(null)") : if_name);
2074 for(dp = hp->disks; dp != NULL; dp = dp->hostnext)
2075 dump_disk(dp);
2076 putchar('\n');
2077 }
2078
2079
2080 g_printf(_("DISKLIST IN FILE ORDER:\n"));
2081
2082 prev = NULL;
2083 for(dp = lst->head; dp != NULL; prev = dp, dp = dp->next) {
2084 dump_disk(dp);
2085 /* check pointers */
2086 if(dp->prev != prev) g_printf(_("*** prev pointer mismatch!\n"));
2087 if(dp->next == NULL && lst->tail != dp) g_printf(_("tail mismatch!\n"));
2088 }
2089 }
2090
2091 int
main(int argc,char ** argv)2092 main(
2093 int argc,
2094 char ** argv)
2095 {
2096 char *conffile;
2097 char *conf_diskfile;
2098 disklist_t lst;
2099 int result;
2100
2101 /*
2102 * Configure program for internationalization:
2103 * 1) Only set the message locale for now.
2104 * 2) Set textdomain for all amanda related programs to "amanda"
2105 * We don't want to be forced to support dozens of message catalogs.
2106 */
2107 setlocale(LC_MESSAGES, "C");
2108 textdomain("amanda");
2109
2110 safe_fd(-1, 0);
2111
2112 set_pname("diskfile");
2113
2114 dbopen(DBG_SUBDIR_SERVER);
2115
2116 /* Don't die when child closes pipe */
2117 signal(SIGPIPE, SIG_IGN);
2118
2119 if (argc>1) {
2120 config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]);
2121 } else {
2122 config_init(CONFIG_INIT_USE_CWD, NULL)
2123 }
2124
2125 if (config_errors(NULL) >= CFGERR_WARNINGS) {
2126 config_print_errors();
2127 if (config_errors(NULL) >= CFGERR_ERRORS) {
2128 g_critical(_("errors processing config file"));
2129 }
2130 }
2131
2132 conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
2133 result = read_diskfile(conf_diskfile, &lst);
2134 if(result == CFGERR_OK) {
2135 dump_disklist(&lst);
2136 } else {
2137 config_print_errors();
2138 }
2139 amfree(conf_diskfile);
2140 amfree(conffile);
2141 amfree(config_dir);
2142
2143 return result;
2144 }
2145 #endif /* TEST */
2146