#include "fsusage.h"
#include "diskfile.h"
#include "tapefile.h"
-#include "changer.h"
#include "packet.h"
#include "security.h"
#include "protocol.h"
#include "clock.h"
-#include "version.h"
#include "amindex.h"
-#include "token.h"
-#include "taperscan.h"
#include "server_util.h"
#include "pipespawn.h"
#include "amfeatures.h"
#include "device.h"
#include "property.h"
#include "timestamp.h"
+#include "amxml.h"
+#include "physmem.h"
+#include <getopt.h>
#define BUFFER_SIZE 32768
void
usage(void)
{
- error(_("Usage: amcheck%s [-am] [-w] [-sclt] [-M <address>] <conf> [host [disk]* ]* [-o configoption]*"), versionsuffix());
+ g_printf(_("Usage: amcheck [--version] [-am] [-w] [-sclt] [-M <address>] [--client-verbose] [-o configoption]* <conf> [host [disk]* ]*\n"));
+ exit(1);
/*NOTREACHED*/
}
static char *displayunit;
static long int unitdivisor;
+static int client_verbose = FALSE;
+static struct option long_options[] = {
+ {"client-verbose", 0, NULL, 1},
+ {"version" , 0, NULL, 2},
+ {NULL, 0, NULL, 0}
+};
+
int
main(
int argc,
int do_clientchk, client_probs;
int do_localchk, do_tapechk, server_probs;
pid_t clientchk_pid, serverchk_pid;
- int opt, tempfd, mainfd;
- ssize_t size;
+ int tempfd, mainfd;
+ size_t size;
amwait_t retstat;
pid_t pid;
extern int optind;
struct passwd *pw;
uid_t uid_me;
char *errstr;
- config_overwrites_t *cfg_ovr;
+ config_overrides_t *cfg_ovr;
+ char *mailer;
/*
* Configure program for internationalization:
g_snprintf(pid_str, SIZEOF(pid_str), "%ld", (long)getpid());
- erroutput_type = ERR_INTERACTIVE;
+ add_amanda_log_handler(amanda_log_stderr);
our_features = am_init_feature_set();
our_feature_string = am_feature_to_string(our_features);
- uid_me = getuid();
+ uid_me = geteuid();
alwaysmail = mailout = overwrite = 0;
do_localchk = do_tapechk = do_clientchk = 0;
server_probs = client_probs = 0;
tempfd = mainfd = -1;
- parse_conf(argc, argv, &new_argc, &new_argv);
- my_argc = new_argc;
- my_argv = new_argv;
-
/* process arguments */
- cfg_ovr = new_config_overwrites(argc/2);
- while((opt = getopt(argc, argv, "M:mawsclto:")) != EOF) {
- switch(opt) {
- case 'M': mailto=stralloc(optarg);
+ cfg_ovr = new_config_overrides(argc/2);
+ while (1) {
+ int option_index = 0;
+ int c;
+ c = getopt_long (argc, argv, "M:mawsclto:", long_options, &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch(c) {
+ case 1: client_verbose = TRUE;
+ break;
+ case 2: printf("amcheck-%s\n", VERSION);
+ return(0);
+ break;
+ case 'M': if (mailto) {
+ g_printf(_("Multiple -M options\n"));
+ exit(1);
+ }
+ mailto=stralloc(optarg);
if(!validate_mailto(mailto)){
g_printf(_("Invalid characters in mail address\n"));
exit(1);
}
/*FALLTHROUGH*/
case 'm':
-#ifdef MAILER
mailout = 1;
-#else
- g_printf(_("You can't use -%c because configure didn't "
- "find a mailer./usr/bin/mail not found\n"),
- opt);
- exit(1);
-#endif
break;
case 'a':
-#ifdef MAILER
mailout = 1;
alwaysmail = 1;
-#else
- g_printf(_("You can't use -%c because configure didn't "
- "find a mailer./usr/bin/mail not found\n"),
- opt);
- exit(1);
-#endif
break;
case 's': do_localchk = do_tapechk = 1;
break;
break;
case 'w': overwrite = 1;
break;
- case 'o': add_config_overwrite_opt(cfg_ovr, optarg);
+ case 'o': add_config_override_opt(cfg_ovr, optarg);
break;
case 't': do_tapechk = 1;
break;
if(overwrite)
do_tapechk = 1;
- config_init(CONFIG_INIT_EXPLICIT_NAME|CONFIG_INIT_FATAL,
- argv[0]);
- apply_config_overwrites(cfg_ovr);
- dbrename(config_name, DBG_SUBDIR_SERVER);
+ set_config_overrides(cfg_ovr);
+ config_init(CONFIG_INIT_EXPLICIT_NAME, argv[0]);
+ dbrename(get_config_name(), DBG_SUBDIR_SERVER);
+ conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
+ read_diskfile(conf_diskfile, &origq);
+ disable_skip_disk(&origq);
+ amfree(conf_diskfile);
+
+ if (config_errors(NULL) >= CFGERR_WARNINGS) {
+ config_print_errors();
+ if (config_errors(NULL) >= CFGERR_ERRORS) {
+ g_critical(_("errors processing config file"));
+ }
+ }
+
+ mailer = getconf_str(CNF_MAILER);
+ if ((!mailer || *mailer == '\0') && mailout == 1) {
+ if (alwaysmail == 1) {
+ g_printf(_("You can't use -a because a mailer is not defined\n"));
+ } else {
+ g_printf(_("You can't use -m because a mailer is not defined\n"));
+ }
+ exit(1);
+ }
if(mailout && !mailto &&
(getconf_seen(CNF_MAILTO)==0 || strlen(getconf_str(CNF_MAILTO)) == 0)) {
g_printf(_("\nWARNING:No mail address configured in amanda.conf.\n"));
conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
- conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
- if(read_diskfile(conf_diskfile, &origq) < 0) {
- error(_("could not load disklist %s. Make sure it exists and has correct permissions"), conf_diskfile);
- /*NOTREACHED*/
- }
errstr = match_disklist(&origq, argc-1, argv+1);
if (errstr) {
g_printf(_("%s"),errstr);
amfree(errstr);
}
- amfree(conf_diskfile);
/*
* Make sure we are running as the dump user. Don't use
char *wait_msg = NULL;
wait_msg = vstrallocf(_("parent: reaped bogus pid %ld\n"), (long)pid);
- if (fullwrite(mainfd, wait_msg, strlen(wait_msg)) < 0) {
+ if (full_write(mainfd, wait_msg, strlen(wait_msg)) < strlen(wait_msg)) {
error(_("write main file: %s"), strerror(errno));
/*NOTREACHED*/
}
/*NOTREACHED*/
}
- while((size = fullread(tempfd, buffer, SIZEOF(buffer))) > 0) {
- if (fullwrite(mainfd, buffer, (size_t)size) < 0) {
+ while((size = full_read(tempfd, buffer, SIZEOF(buffer))) > 0) {
+ if (full_write(mainfd, buffer, size) < size) {
error(_("write main file: %s"), strerror(errno));
/*NOTREACHED*/
}
}
- if(size < 0) {
+ if(errno != 0) {
error(_("read temp file: %s"), strerror(errno));
/*NOTREACHED*/
}
aclose(tempfd);
}
- version_string = vstrallocf(_("\n(brought to you by Amanda %s)\n"), version());
- if (fullwrite(mainfd, version_string, strlen(version_string)) < 0) {
+ version_string = vstrallocf(_("\n(brought to you by Amanda %s)\n"), VERSION);
+ if (full_write(mainfd, version_string, strlen(version_string)) < strlen(version_string)) {
error(_("write main file: %s"), strerror(errno));
/*NOTREACHED*/
}
our_features = NULL;
/* send mail if requested, but only if there were problems */
-#ifdef MAILER
-
-#define MAILTO_LIMIT 10
if((server_probs || client_probs || alwaysmail) && mailout) {
int mailfd;
int errfd;
FILE *ferr;
char *subject;
- char **a;
+ char **a, **b;
+ GPtrArray *pipeargs;
amwait_t retstat;
- ssize_t r;
- ssize_t w;
+ size_t r;
+ size_t w;
char *err = NULL;
char *extra_info = NULL;
char *line = NULL;
_("%s AMANDA PROBLEM: FIX BEFORE RUN, IF POSSIBLE"),
getconf_str(CNF_ORG));
}
- /*
- * Variable arg lists are hard to deal with when we do not know
- * ourself how many args are involved. Split the address list
- * and hope there are not more than 9 entries.
- *
- * Remember that split() returns the original input string in
- * argv[0], so we have to skip over that.
- */
- a = (char **) alloc((MAILTO_LIMIT + 1) * SIZEOF(char *));
- memset(a, 0, (MAILTO_LIMIT + 1) * SIZEOF(char *));
if(mailto) {
- a[1] = mailto;
+ a = (char **) g_new0(char *, 2);
+ a[1] = stralloc(mailto);
a[2] = NULL;
} else {
- r = (ssize_t)split(getconf_str(CNF_MAILTO), a, MAILTO_LIMIT, " ");
- a[r + 1] = NULL;
+ /* (note that validate_mailto doesn't allow any quotes, so this
+ * is really just splitting regular old strings) */
+ a = split_quoted_strings(getconf_str(CNF_MAILTO));
}
if((nullfd = open("/dev/null", O_RDWR)) < 0) {
error("nullfd: /dev/null: %s", strerror(errno));
/*NOTREACHED*/
}
- pipespawn(MAILER, STDIN_PIPE | STDERR_PIPE,
- &mailfd, &nullfd, &errfd,
- MAILER,
- "-s", subject,
- a[1], a[2], a[3], a[4],
- a[5], a[6], a[7], a[8], a[9],
- NULL);
+
+ /* assemble the command line for the mailer */
+ pipeargs = g_ptr_array_sized_new(4);
+ g_ptr_array_add(pipeargs, mailer);
+ g_ptr_array_add(pipeargs, "-s");
+ g_ptr_array_add(pipeargs, subject);
+ for (b = a; *b; b++)
+ g_ptr_array_add(pipeargs, *b);
+ g_ptr_array_add(pipeargs, NULL);
+
+ pipespawnv(mailer, STDIN_PIPE | STDERR_PIPE, 0,
+ &mailfd, &nullfd, &errfd,
+ (char **)pipeargs->pdata);
+
+ g_ptr_array_free(pipeargs, FALSE);
amfree(subject);
+ amfree(mailto);
+ g_strfreev(a);
+
/*
* There is the potential for a deadlock here since we are writing
* to the process and then reading stderr, but in the normal case,
* cases, the pipe will break and we will exit out of the loop.
*/
signal(SIGPIPE, SIG_IGN);
- while((r = fullread(mainfd, buffer, SIZEOF(buffer))) > 0) {
- if((w = fullwrite(mailfd, buffer, (size_t)r)) != (ssize_t)r) {
- if(w < 0 && errno == EPIPE) {
+ while((r = full_read(mainfd, buffer, SIZEOF(buffer))) > 0) {
+ if((w = full_write(mailfd, buffer, r)) != r) {
+ if(errno == EPIPE) {
strappend(extra_info, _("EPIPE writing to mail process\n"));
break;
- } else if(w < 0) {
+ } else if(errno != 0) {
error(_("mailfd write: %s"), strerror(errno));
/*NOTREACHED*/
} else {
fputs(extra_info, stderr);
amfree(extra_info);
}
- error(_("error running mailer %s: %s"), MAILER, err?err:"(unknown)");
+ error(_("error running mailer %s: %s"), mailer, err?err:"(unknown)");
/*NOTREACHED*/
}
}
-#endif
- free_new_argv(new_argc, new_argv);
- free_server_config();
dbclose();
return (server_probs || client_probs);
int pgmbad = 0;
char *quoted;
- pgm = vstralloc(dir, "/", pgm, versionsuffix(), NULL);
+ pgm = vstralloc(dir, "/", pgm, NULL);
quoted = quote_string(pgm);
if(stat(pgm, &statbuf) == -1) {
g_fprintf(outf, _("ERROR: program %s: does not exist\n"),
/* check that the tape is a valid amanda tape
Returns TRUE if all tests passed; FALSE otherwise. */
static gboolean test_tape_status(FILE * outf) {
- int tape_status;
- Device * device;
- GValue property_value;
- char * label = NULL;
- char * tapename = NULL;
- ReadLabelStatusFlags label_status;
-
- bzero(&property_value, sizeof(property_value));
-
- tapename = getconf_str(CNF_TAPEDEV);
- g_return_val_if_fail(tapename != NULL, FALSE);
-
- device_api_init();
-
- if (!getconf_seen(CNF_TPCHANGER) && getconf_int(CNF_RUNTAPES) != 1) {
- g_fprintf(outf,
- _("WARNING: if a tape changer is not available, runtapes "
- "must be set to 1\n"));
- g_fprintf(outf, _("Change the value of the \"runtapes\" parameter in "
- "amanda.conf or configure a tape changer\n"));
+ int outfd;
+ int nullfd = -1;
+ pid_t devpid;
+ char *amcheck_device = NULL;
+ gchar **args;
+ amwait_t wait_status;
+ gboolean success;
+
+ if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+ return FALSE;
}
-
- tape_status = taper_scan(NULL, &label, &datestamp, &tapename, NULL,
- FILE_taperscan_output_callback, outf,
- NULL, NULL);
- if (tape_status < 0) {
- tape_t *exptape = lookup_last_reusable_tape(0);
- g_fprintf(outf, _(" (expecting "));
- if(exptape != NULL) g_fprintf(outf, _("tape %s or "), exptape->label);
- g_fprintf(outf, _("a new tape)\n"));
- amfree(label);
- return FALSE;
+
+ fflush(outf);
+ outfd = fileno(outf);
+
+ amcheck_device = vstralloc(amlibexecdir, "/", "amcheck-device", NULL);
+ args = get_config_options(overwrite? 3 : 2);
+ args[0] = amcheck_device; /* steal the reference */
+ args[1] = g_strdup(get_config_name());
+ if (overwrite)
+ args[2] = g_strdup("-w");
+
+ /* run libexecdir/amcheck-device.pl, capturing STDERR and STDOUT to outf */
+ devpid = pipespawnv(amcheck_device, 0, 0,
+ &nullfd, &outfd, &outfd,
+ (char **)args);
+
+ /* and immediately wait for it to die */
+ waitpid(devpid, &wait_status, 0);
+
+ if (WIFSIGNALED(wait_status)) {
+ g_fprintf(outf, _("amcheck-device terminated with signal %d"),
+ WTERMSIG(wait_status));
+ success = FALSE;
+ } else if (WIFEXITED(wait_status)) {
+ success = (WEXITSTATUS(wait_status) == 0);
+ } else {
+ success = FALSE;
}
- device = device_open(tapename);
+ g_strfreev(args);
+ close(nullfd);
- if (device == NULL) {
- g_fprintf(outf, "ERROR: Could not open tape device.\n");
- amfree(label);
- return FALSE;
- }
-
- device_set_startup_properties_from_config(device);
- label_status = device_read_label(device);
-
- if (tape_status == 3 &&
- !(label_status & READ_LABEL_STATUS_VOLUME_UNLABELED)) {
- if (label_status == READ_LABEL_STATUS_SUCCESS) {
- g_fprintf(outf, "WARNING: Volume was unlabeled, but now "
- "is labeled \"%s\".\n", device->volume_label);
- }
- } else if (label_status != READ_LABEL_STATUS_SUCCESS && tape_status != 3) {
- char * errstr =
- g_english_strjoinv_and_free
- (g_flags_nick_to_strv(label_status &
- (~READ_LABEL_STATUS_VOLUME_UNLABELED),
- READ_LABEL_STATUS_FLAGS_TYPE), "or");
- g_fprintf(outf, "WARNING: Reading label the second time failed: "
- "One of %s.\n", errstr);
- g_free(errstr);
- } else if (tape_status != 3 &&
- (device->volume_label == NULL || label == NULL ||
- strcmp(device->volume_label, label) != 0)) {
- g_fprintf(outf, "WARNING: Label mismatch on re-read: "
- "Got %s first, then %s.\n", label, device->volume_label);
- }
-
- /* If we can't get this property, it's not an error. Maybe the device
- * doesn't support this property, or needs an actual volume to know
- * for sure. */
- if (device_property_get(device, PROPERTY_MEDIUM_TYPE, &property_value)) {
- g_assert(G_VALUE_TYPE(&property_value) == MEDIA_ACCESS_MODE_TYPE);
- if (g_value_get_enum(&property_value) ==
- MEDIA_ACCESS_MODE_WRITE_ONLY) {
- g_fprintf(outf, "WARNING: Media access mode is WRITE_ONLY, "
- "dumps will be thrown away.\n");
- }
- }
-
- if (overwrite) {
- char *timestamp = get_undef_timestamp();
- if (!device_start(device, ACCESS_WRITE, label, timestamp)) {
- if (tape_status == 3) {
- g_fprintf(outf, "ERROR: Could not label brand new tape.\n");
- } else {
- g_fprintf(outf,
- "ERROR: tape %s label ok, but is not writable.\n",
- label);
- }
- amfree(timestamp);
- amfree(label);
- g_object_unref(device);
- return FALSE;
- } else { /* Write succeeded. */
- if (tape_status != 3) {
- g_fprintf(outf, "Tape %s is writable; rewrote label.\n", label);
- } else {
- g_fprintf(outf, "Wrote label %s to brand new tape.\n", label);
- }
- }
- amfree(timestamp);
- } else { /* !overwrite */
- g_fprintf(outf, "NOTE: skipping tape-writable test\n");
- if (tape_status == 3) {
- g_fprintf(outf,
- "Found a brand new tape, will label it %s.\n",
- label);
- } else {
- g_fprintf(outf, "Tape %s label ok\n", label);
- }
- }
- g_object_unref(device);
- amfree(label);
- return TRUE;
+ return success;
}
pid_t
{
struct fs_usage fsusage;
FILE *outf = NULL;
- holdingdisk_t *hdp;
pid_t pid G_GNUC_UNUSED;
int confbad = 0, tapebad = 0, disklow = 0, logbad = 0;
int userbad = 0, infobad = 0, indexbad = 0, pgmbad = 0;
tapetype_t *tp = NULL;
char *quoted;
int res;
- intmax_t kb_avail;
+ intmax_t kb_avail, kb_needed;
+ off_t tape_size;
+ gboolean printed_small_part_size_warning = FALSE;
+ char *small_part_size_warning =
+ _(" This may create > 1000 parts, severely degrading backup/restore performance.\n"
+ " See http://wiki.zmanda.com/index.php/Splitsize_too_small for more information.\n");
switch(pid = fork()) {
case -1:
startclock();
+ /* server does not need root privileges, and the access() calls below use the real userid,
+ * so totally drop privileges at this point (making the userid equal to the dumpuser) */
+ set_root_privs(-1);
+
if((outf = fdopen(fd, "w")) == NULL) {
error(_("fdopen %d: %s"), fd, strerror(errno));
/*NOTREACHED*/
strerror(errno));
confbad = 1;
}
-#if !defined(LPRCMD)
- g_fprintf(outf, _("ERROR:lbl-templ set but no LPRCMD defined. You should reconfigure amanda\n and make sure it finds a lpr or lp command.\n"));
+#if !defined(HAVE_LPR_CMD)
+ g_fprintf(outf, _("ERROR: lbl-templ set but no LPR command defined. You should reconfigure amanda\n and make sure it finds a lpr or lp command.\n"));
confbad = 1;
#endif
}
if (getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED) <
getconf_int(CNF_FLUSH_THRESHOLD_DUMPED)) {
- g_fprintf(outf, _("WARNING: flush_threshold_dumped (%d) must be less than or equal to flush_threshold_scheduled (%d).\n"),
+ g_fprintf(outf, _("WARNING: flush-threshold-dumped (%d) must be less than or equal to flush-threshold-scheduled (%d).\n"),
getconf_int(CNF_FLUSH_THRESHOLD_DUMPED),
getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED));
}
if (getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED) <
getconf_int(CNF_TAPERFLUSH)) {
- g_fprintf(outf, _("WARNING: taperflush (%d) must be less than or equal to flush_threshold_scheduled (%d).\n"),
+ g_fprintf(outf, _("WARNING: taperflush (%d) must be less than or equal to flush-threshold-scheduled (%d).\n"),
getconf_int(CNF_TAPERFLUSH),
getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED));
}
if (getconf_int(CNF_TAPERFLUSH) > 0 &&
- !getconf_boolean(CNF_AUTOFLUSH)) {
- g_fprintf(outf, _("WARNING: autoflush must be set to 'yes' if taperflush (%d) is greater that 0.\n"),
+ !getconf_no_yes_all(CNF_AUTOFLUSH)) {
+ g_fprintf(outf, _("WARNING: autoflush must be set to 'yes' or 'all' if taperflush (%d) is greater that 0.\n"),
getconf_int(CNF_TAPERFLUSH));
}
g_fprintf(outf, _("ERROR: Cannot resolve `localhost': %s\n"), gai_strerror(res));
confbad = 1;
}
+
+ if (!getconf_seen(CNF_TAPETYPE)) {
+ g_fprintf(outf,
+ _("ERROR: no tapetype specified; you must give a value for "
+ "the 'tapetype' parameter\n"));
+ confbad = 1;
+ }
}
/*
char *holdfile;
char * tapename;
struct stat statbuf;
-
+ guint64 part_size, part_cache_max_size, tape_size;
+ part_cache_type_t part_cache_type;
+ char *part_cache_dir;
+
tapefile = config_dir_relative(getconf_str(CNF_TAPELIST));
/*
* XXX There Really Ought to be some error-checking here... dhw
amfree(quoted);
}
else if(stat(tapefile, &statbuf) == -1) {
- quoted = quote_string(tape_dir);
- g_fprintf(outf, _("ERROR: tapelist %s (%s), "
- "you must create an empty file.\n"),
- quoted, strerror(errno));
- tapebad = 1;
- amfree(quoted);
- }
- else {
+ if (errno != ENOENT) {
+ quoted = quote_string(tape_dir);
+ g_fprintf(outf, _("ERROR: tapelist %s (%s), "
+ "you must create an empty file.\n"),
+ quoted, strerror(errno));
+ tapebad = 1;
+ amfree(quoted);
+ } else {
+ g_fprintf(outf, _("NOTE: tapelist will be created on the next run.\n"));
+ }
+ } else {
tapebad |= check_tapefile(outf, tapefile);
if (tapebad == 0 && read_tapelist(tapefile)) {
quoted = quote_string(tapefile);
do_tapechk = 0;
}
}
+
+ /* check tapetype-based splitting parameters */
+ part_size = tapetype_get_part_size(tp);
+ part_cache_type = tapetype_get_part_cache_type(tp);
+ part_cache_dir = tapetype_get_part_cache_dir(tp);
+ part_cache_max_size = tapetype_get_part_cache_max_size(tp);
+
+ if (!tapetype_seen(tp, TAPETYPE_PART_SIZE)) {
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_TYPE)) {
+ g_fprintf(outf, "ERROR: part-cache-type specified, but no part-size\n");
+ tapebad = 1;
+ }
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_DIR)) {
+ g_fprintf(outf, "ERROR: part-cache-dir specified, but no part-size\n");
+ tapebad = 1;
+ }
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ g_fprintf(outf, "ERROR: part-cache-max-size specified, but no part-size\n");
+ tapebad = 1;
+ }
+ } else {
+ switch (part_cache_type) {
+ case PART_CACHE_TYPE_DISK:
+ if (!tapetype_seen(tp, TAPETYPE_PART_CACHE_DIR)
+ || !part_cache_dir || !*part_cache_dir) {
+ g_fprintf(outf,
+ "ERROR: part-cache-type is DISK, but no part-cache-dir specified\n");
+ tapebad = 1;
+ } else {
+ if(get_fs_usage(part_cache_dir, NULL, &fsusage) == -1) {
+ g_fprintf(outf, "ERROR: part-cache-dir '%s': %s\n",
+ part_cache_dir, strerror(errno));
+ tapebad = 1;
+ } else {
+ kb_avail = fsusage.fsu_bavail_top_bit_set?
+ 0 : fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize;
+ kb_needed = part_size;
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ kb_needed = part_cache_max_size;
+ }
+ if (kb_avail < kb_needed) {
+ g_fprintf(outf,
+ "ERROR: part-cache-dir has %ju %sB available, but needs %ju %sB\n",
+ kb_avail/(uintmax_t)unitdivisor, displayunit,
+ kb_needed/(uintmax_t)unitdivisor, displayunit);
+ tapebad = 1;
+ }
+ }
+ }
+ break;
+
+ case PART_CACHE_TYPE_MEMORY:
+ kb_avail = physmem_total() / 1024;
+ kb_needed = part_size;
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ kb_needed = part_cache_max_size;
+ }
+ if (kb_avail < kb_needed) {
+ g_fprintf(outf,
+ "ERROR: system has %ju %sB memory, but part cache needs %ju %sB\n",
+ kb_avail/(uintmax_t)unitdivisor, displayunit,
+ kb_needed/(uintmax_t)unitdivisor, displayunit);
+ tapebad = 1;
+ }
+
+ /* FALL THROUGH */
+
+ case PART_CACHE_TYPE_NONE:
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_DIR)) {
+ g_fprintf(outf,
+ "ERROR: part-cache-dir specified, but part-cache-type is not DISK\n");
+ tapebad = 1;
+ }
+ break;
+ }
+ }
+
+ if (tapetype_seen(tp, TAPETYPE_PART_SIZE) && part_size == 0
+ && part_cache_type != PART_CACHE_TYPE_NONE) {
+ g_fprintf(outf,
+ "ERROR: part_size is zero, but part-cache-type is not 'none'\n");
+ tapebad = 1;
+ }
+
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ if (part_cache_type == PART_CACHE_TYPE_NONE) {
+ g_fprintf(outf,
+ "ERROR: part-cache-max-size is specified but no part cache is in use\n");
+ tapebad = 1;
+ }
+
+ if (part_cache_max_size > part_size) {
+ g_fprintf(outf,
+ "WARNING: part-cache-max-size is greater than part-size\n");
+ }
+ }
+
+ tape_size = tapetype_get_length(tp);
+ if (part_size && part_size * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: part-size of %ju %sB < 0.1%% of tape length.\n"),
+ (uintmax_t)part_size/(uintmax_t)unitdivisor, displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
+ } else if (part_cache_max_size && part_cache_max_size * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: part-cache-max-size of %ju %sB < 0.1%% of tape length.\n"),
+ (uintmax_t)part_cache_max_size/(uintmax_t)unitdivisor, displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
+ }
}
/* check available disk space */
if(do_localchk) {
- for(hdp = getconf_holdingdisks(); hdp != NULL; hdp = holdingdisk_next(hdp)) {
+ identlist_t il;
+ holdingdisk_t *hdp;
+
+ for (il = getconf_identlist(CNF_HOLDINGDISK);
+ il != NULL;
+ il = il->next) {
+ hdp = lookup_holdingdisk(il->data);
quoted = quote_string(holdingdisk_get_diskdir(hdp));
if(get_fs_usage(holdingdisk_get_diskdir(hdp), NULL, &fsusage) == -1) {
g_fprintf(outf, _("ERROR: holding dir %s (%s), "
}
amfree(quoted);
- if(access(logfile, F_OK) == 0) {
+ if(logbad == 0 && access(logfile, F_OK) == 0) {
testtape = 0;
logbad = 2;
if(access(logfile, W_OK) != 0) {
olddir = vstralloc(conf_logdir, "/oldlog", NULL);
quoted = quote_string(olddir);
- if (stat(olddir,&stat_old) == 0) { /* oldlog exist */
+ if (logbad == 0 && stat(olddir,&stat_old) == 0) { /* oldlog exist */
if(!(S_ISDIR(stat_old.st_mode))) {
g_fprintf(outf, _("ERROR: oldlog directory %s is not a directory\n"),
quoted);
g_fprintf(outf, _("Remove the entry and create a new directory\n"));
logbad = 1;
}
- if(access(olddir, W_OK) == -1) {
+ if(logbad == 0 && access(olddir, W_OK) == -1) {
g_fprintf(outf, _("ERROR: oldlog dir %s: not writable\n"), quoted);
g_fprintf(outf, _("Check permissions\n"));
logbad = 1;
}
}
- else if(lstat(olddir,&stat_old) == 0) {
+ else if(logbad == 0 && lstat(olddir,&stat_old) == 0) {
g_fprintf(outf, _("ERROR: oldlog directory %s is not a directory\n"),
quoted);
g_fprintf(outf, _("Remove the entry and create a new directory\n"));
}
amfree(quoted);
- if (testtape) {
+ if (logbad == 0 && testtape) {
logfile = newvstralloc(logfile, conf_logdir, "/amdump", NULL);
if (access(logfile, F_OK) == 0) {
testtape = 0;
g_fprintf(outf, _("WARNING: skipping tape test because amdump or amflush seem to be running\n"));
g_fprintf(outf, _("WARNING: if they are not, you must run amcleanup\n"));
} else if (logbad == 2) {
- g_fprintf(outf, _("WARNING: amdump or amflush seem to be running\n"));
- g_fprintf(outf, _("WARNING: if they are not, you must run amcleanup\n"));
+ g_fprintf(outf, _("NOTE: amdump or amflush seem to be running\n"));
+ g_fprintf(outf, _("NOTE: if they are not, you must run amcleanup\n"));
+
+ /* we skipped the tape checks, but this is just a NOTE and
+ * should not result in a nonzero exit status, so reset logbad to 0 */
+ logbad = 0;
} else {
g_fprintf(outf, _("NOTE: skipping tape checks\n"));
}
char *host;
char *disk;
int conf_tapecycle, conf_runspercycle;
+ identlist_t pp_scriptlist;
conf_tapecycle = getconf_int(CNF_TAPECYCLE);
conf_runspercycle = getconf_int(CNF_RUNSPERCYCLE);
if ( dp->encrypt == ENCRYPT_SERV_CUST ) {
if ( dp->srv_encrypt[0] == '\0' ) {
g_fprintf(outf, _("ERROR: server encryption program not specified\n"));
- g_fprintf(outf, _("Specify \"server_custom_encrypt\" in the dumptype\n"));
+ g_fprintf(outf, _("Specify \"server-custom-encrypt\" in the dumptype\n"));
pgmbad = 1;
}
else if(access(dp->srv_encrypt, X_OK) == -1) {
if ( dp->srvcompprog[0] == '\0' ) {
g_fprintf(outf, _("ERROR: server custom compression program "
"not specified\n"));
- g_fprintf(outf, _("Specify \"server_custom_compress\" in "
+ g_fprintf(outf, _("Specify \"server-custom-compress\" in "
"the dumptype\n"));
pgmbad = 1;
}
}
}
+ /* check deprecated splitting parameters */
+ if (dumptype_seen(dp->config, DUMPTYPE_TAPE_SPLITSIZE)
+ || dumptype_seen(dp->config, DUMPTYPE_SPLIT_DISKBUFFER)
+ || dumptype_seen(dp->config, DUMPTYPE_FALLBACK_SPLITSIZE)) {
+ tape_size = tapetype_get_length(tp);
+ if (dp->tape_splitsize > tape_size) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: tape-splitsize > tape size\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ if (dp->tape_splitsize && dp->fallback_splitsize * 1024 > physmem_total()) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: fallback-splitsize > total available memory\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ if (dp->tape_splitsize && dp->fallback_splitsize > tape_size) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: fallback-splitsize > tape size\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+
+ /* also check for part sizes that are too small */
+ if (dp->tape_splitsize && dp->tape_splitsize * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: %s %s: tape-splitsize of %ju %sB < 0.1%% of tape length.\n"),
+ hostp->hostname, dp->name,
+ (uintmax_t)dp->tape_splitsize/(uintmax_t)unitdivisor,
+ displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
+ }
+
+ /* fallback splitsize will be used if split_diskbuffer is empty or NULL */
+ if (dp->tape_splitsize != 0 && dp->fallback_splitsize != 0 &&
+ (dp->split_diskbuffer == NULL ||
+ dp->split_diskbuffer[0] == '\0') &&
+ dp->fallback_splitsize * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: %s %s: fallback-splitsize of %ju %sB < 0.1%% of tape length.\n"),
+ hostp->hostname, dp->name,
+ (uintmax_t)dp->fallback_splitsize/(uintmax_t)unitdivisor,
+ displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
+ }
+ }
+
+ if (dp->data_path == DATA_PATH_DIRECTTCP) {
+ if (dp->compress != COMP_NONE) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: Can't compress directtcp data-path\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ if (dp->encrypt != ENCRYPT_NONE) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: Can't encrypt directtcp data-path\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ if (dp->to_holdingdisk == HOLD_REQUIRED) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: Holding disk can't be use for directtcp data-path\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ }
+
+ for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
+ pp_scriptlist = pp_scriptlist->next) {
+ pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data);
+ g_assert(pp_script != NULL);
+ if (pp_script_get_execute_where(pp_script) == ES_CLIENT &&
+ pp_script_get_execute_on(pp_script) & EXECUTE_ON_PRE_HOST_BACKUP) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: Can't run pre-host-backup script on client\n"),
+ hostp->hostname, dp->name);
+ } else if (pp_script_get_execute_where(pp_script) == ES_CLIENT &&
+ pp_script_get_execute_on(pp_script) & EXECUTE_ON_POST_HOST_BACKUP) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: Can't run post-host-backup script on client\n"),
+ hostp->hostname, dp->name);
+ }
+ }
+
amfree(disk);
remove_disk(&origq, dp);
}
g_fprintf(outf, _("Server check took %s seconds\n"), walltime_str(curclock()));
fflush(outf);
+ g_debug("userbad: %d", userbad);
+ g_debug("confbad: %d", confbad);
+ g_debug("tapebad: %d", tapebad);
+ g_debug("disklow: %d", disklow);
+ g_debug("logbad: %d", logbad);
+ g_debug("infobad: %d", infobad);
+ g_debug("indexbad: %d", indexbad);
+ g_debug("pgmbad: %d", pgmbad);
exit(userbad \
|| confbad \
int disk_count;
const security_driver_t *secdrv;
char number[NUM_STR_SIZE];
+ estimate_t estimate;
if(hostp->up != HOST_READY) {
return;
}
- if (strcmp(hostp->hostname,"localhost") == 0) {
- g_fprintf(outf,
- _("WARNING: Usage of fully qualified hostname recommended for Client %s.\n"),
- hostp->hostname);
- }
-
/*
* The first time through here we send a "noop" request. This will
* return the feature list from the client if it supports that.
has_hostname ? hostp->hostname : "",
has_hostname ? ";" : "",
has_config ? "config=" : "",
- has_config ? config_name : "",
+ has_config ? get_config_name() : "",
has_config ? ";" : "",
"\n",
NULL);
req_len += 256; /* room for non-disk answers */
for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
char *l;
+ char *es;
size_t l_len;
- char *o;
+ char *o = NULL;
char *calcsize;
- char *qname;
- char *qdevice;
+ char *qname, *b64disk;
+ char *qdevice, *b64device = NULL;
+ GPtrArray *errarray;
+ guint i;
if(dp->up != DISK_READY || dp->todo != 1) {
continue;
}
- o = optionstr(dp, hostp->features, outf);
- if (o == NULL) {
- remote_errors++;
+ qname = quote_string(dp->name);
+
+ errarray = validate_optionstr(dp);
+ if (errarray->len > 0) {
+ for (i=0; i < errarray->len; i++) {
+ g_fprintf(outf, _("ERROR: %s:%s %s\n"),
+ hostp->hostname, qname,
+ (char *)g_ptr_array_index(errarray, i));
+ }
+ g_ptr_array_free(errarray, TRUE);
+ amfree(qname);
+ remote_errors++;
continue;
+ } else if (am_has_feature(hostp->features, fe_req_xml)) {
+ o = xml_optionstr(dp, 0);
+ } else {
+ o = optionstr(dp);
}
- qname = quote_string(dp->name);
+
+ b64disk = amxml_format_tag("disk", dp->name);
qdevice = quote_string(dp->device);
+ if (dp->device)
+ b64device = amxml_format_tag("diskdevice", dp->device);
if ((dp->name && qname[0] == '"') ||
(dp->device && qdevice[0] == '"')) {
if(!am_has_feature(hostp->features, fe_interface_quoted_text)) {
"specify a diskdevice in the disklist"
" or don't specify a diskdevice in the disklist.\n"));
}
+
+ if (dp->data_path != DATA_PATH_AMANDA &&
+ !am_has_feature(hostp->features, fe_xml_data_path)) {
+ g_fprintf(outf,
+ _("ERROR: Client %s does not support %s data-path\n"),
+ hostp->hostname, data_path_to_string(dp->data_path));
+ } else if (dp->data_path == DATA_PATH_DIRECTTCP &&
+ !am_has_feature(hostp->features, fe_xml_directtcp_list)) {
+ g_fprintf(outf,
+ _("ERROR: Client %s does not support directtcp data-path\n"),
+ hostp->hostname);
+ }
}
- if(strcmp(dp->program,"DUMP") == 0 ||
- strcmp(dp->program,"GNUTAR") == 0) {
+ if (dp->program &&
+ (strcmp(dp->program,"DUMP") == 0 ||
+ strcmp(dp->program,"GNUTAR") == 0)) {
if(strcmp(dp->program, "DUMP") == 0 &&
!am_has_feature(hostp->features, fe_program_dump)) {
g_fprintf(outf, _("ERROR: %s:%s does not support DUMP.\n"),
g_fprintf(outf, _("You must upgrade amanda on the client to use GNUTAR "
"or you can use another program.\n"));
}
- if(dp->estimate == ES_CALCSIZE &&
+ estimate = (estimate_t)GPOINTER_TO_INT(dp->estimatelist->data);
+ if(estimate == ES_CALCSIZE &&
!am_has_feature(hostp->features, fe_calcsize_estimate)) {
g_fprintf(outf, _("ERROR: %s:%s does not support CALCSIZE for "
"estimate, using CLIENT.\n"),
hostp->hostname, qname);
g_fprintf(outf, _("You must upgrade amanda on the client to use "
"CALCSIZE for estimate or don't use CALCSIZE for estimate.\n"));
- dp->estimate = ES_CLIENT;
+ estimate = ES_CLIENT;
}
- if(dp->estimate == ES_CALCSIZE &&
+ if(estimate == ES_CALCSIZE &&
am_has_feature(hostp->features, fe_selfcheck_calcsize))
calcsize = "CALCSIZE ";
else
remote_errors++;
}
}
- if(dp->device) {
- l = vstralloc(calcsize,
- dp->program, " ",
- qname, " ",
- qdevice,
- " 0 OPTIONS |",
- o,
- "\n",
- NULL);
- }
- else {
- l = vstralloc(calcsize,
- dp->program, " ",
- qname,
- " 0 OPTIONS |",
- o,
- "\n",
- NULL);
+ if (am_has_feature(hostp->features, fe_req_xml)) {
+ l = vstralloc("<dle>\n"
+ " <program>",
+ dp->program,
+ "</program>\n", NULL);
+ es = xml_estimate(dp->estimatelist, hostp->features);
+ vstrextend(&l, es, "\n", NULL);
+ amfree(es);
+ vstrextend(&l, " ", b64disk, "\n", NULL);
+ if (dp->device)
+ vstrextend(&l, " ", b64device, "\n", NULL);
+ vstrextend(&l, o, "</dle>\n", NULL);
+ } else {
+ if (dp->device) {
+ l = vstralloc(calcsize,
+ dp->program, " ",
+ qname, " ",
+ qdevice,
+ " 0 OPTIONS |",
+ o,
+ "\n",
+ NULL);
+ } else {
+ l = vstralloc(calcsize,
+ dp->program, " ",
+ qname,
+ " 0 OPTIONS |",
+ o,
+ "\n",
+ NULL);
+ }
}
} else {
- if(!am_has_feature(hostp->features, fe_program_backup_api)) {
- g_fprintf(outf, _("ERROR: %s:%s does not support BACKUP-API.\n"),
+ if (!am_has_feature(hostp->features, fe_program_application_api) ||
+ !am_has_feature(hostp->features, fe_req_xml)) {
+ g_fprintf(outf, _("ERROR: %s:%s does not support APPLICATION-API.\n"),
hostp->hostname, qname);
g_fprintf(outf, _("Dumptype configuration is not GNUTAR or DUMP."
" It is case sensitive\n"));
- }
- if(dp->device) {
- l = vstralloc("BACKUP ",
- dp->program,
- " ",
- qname,
- " ",
- qdevice,
- " 0 OPTIONS |",
- o,
- "\n",
- NULL);
+ remote_errors++;
+ l = stralloc("");
} else {
- l = vstralloc("BACKUP ",
- dp->program,
- " ",
- qname,
- " 0 OPTIONS |",
- o,
- "\n",
- NULL);
+ l = vstralloc("<dle>\n"
+ " <program>APPLICATION</program>\n", NULL);
+ if (dp->application) {
+ application_t *application;
+ char *xml_app;
+
+ application = lookup_application(dp->application);
+ if (!application) {
+ g_fprintf(outf,
+ _("ERROR: application '%s' not found.\n"), dp->application);
+ } else {
+ char *client_name = application_get_client_name(application);
+ if (client_name && strlen(client_name) > 0 &&
+ !am_has_feature(hostp->features, fe_application_client_name)) {
+ g_fprintf(outf,
+ _("WARNING: %s:%s does not support client-name in application.\n"),
+ hostp->hostname, qname);
+ }
+ xml_app = xml_application(dp, application, hostp->features);
+ vstrextend(&l, xml_app, NULL);
+ amfree(xml_app);
+ }
+ }
+ if (dp->pp_scriptlist) {
+ if (!am_has_feature(hostp->features, fe_pp_script)) {
+ g_fprintf(outf,
+ _("ERROR: %s:%s does not support SCRIPT-API.\n"),
+ hostp->hostname, qname);
+ } else {
+ identlist_t pp_scriptlist;
+ for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
+ pp_scriptlist = pp_scriptlist->next) {
+ pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data);
+ char *client_name = pp_script_get_client_name(pp_script);;
+ if (client_name && strlen(client_name) > 0 &&
+ !am_has_feature(hostp->features, fe_script_client_name)) {
+ g_fprintf(outf,
+ _("WARNING: %s:%s does not support client-name in script.\n"),
+ hostp->hostname, dp->name);
+ }
+ }
+ }
+ }
+ es = xml_estimate(dp->estimatelist, hostp->features);
+ vstrextend(&l, es, "\n", NULL);
+ amfree(es);
+ vstrextend(&l, " ", b64disk, "\n", NULL);
+ if (dp->device)
+ vstrextend(&l, " ", b64device, "\n", NULL);
+ vstrextend(&l, o, "</dle>\n", NULL);
}
}
amfree(qname);
amfree(qdevice);
+ amfree(b64disk);
+ amfree(b64device);
l_len = strlen(l);
amfree(o);
return;
}
- secdrv = security_getdriver(hostp->disks->security_driver);
+ secdrv = security_getdriver(hostp->disks->auth);
if (secdrv == NULL) {
fprintf(stderr, _("Could not find security driver \"%s\" for host \"%s\". auth for this dle is invalid\n"),
- hostp->disks->security_driver, hostp->hostname);
+ hostp->disks->auth, hostp->hostname);
} else {
protocol_sendreq(hostp->hostname, secdrv, amhost_get_security_conf,
req, conf_ctimeout, handle_result, hostp);
int fd)
{
am_host_t *hostp;
- disk_t *dp;
+ disk_t *dp, *dp1;
int hostcount;
pid_t pid;
int userbad = 0;
g_fprintf(outf, _("\nAmanda Backup Client Hosts Check\n"));
g_fprintf(outf, "--------------------------------\n");
+ run_server_global_scripts(EXECUTE_ON_PRE_AMCHECK, get_config_name());
protocol_init();
hostcount = remote_errors = 0;
for(dp = origq.head; dp != NULL; dp = dp->next) {
hostp = dp->host;
if(hostp->up == HOST_READY && dp->todo == 1) {
+ run_server_host_scripts(EXECUTE_ON_PRE_HOST_AMCHECK,
+ get_config_name(), hostp);
+ for(dp1 = hostp->disks; dp1 != NULL; dp1 = dp1->hostnext) {
+ run_server_dle_scripts(EXECUTE_ON_PRE_DLE_AMCHECK,
+ get_config_name(), dp1, -1);
+ }
start_host(hostp);
hostcount++;
protocol_check();
}
protocol_run();
+ run_server_global_scripts(EXECUTE_ON_POST_AMCHECK, get_config_name());
g_fprintf(outf, plural(_("Client check: %d host checked in %s seconds."),
_("Client check: %d hosts checked in %s seconds."),
char *t;
int ch;
int tch;
+ gboolean printed_hostname = FALSE;
hostp = (am_host_t *)datap;
hostp->up = HOST_READY;
if(strncmp_const(line, "OPTIONS ") == 0) {
t = strstr(line, "features=");
- if(t != NULL && (isspace((int)t[-1]) || t[-1] == ';')) {
+ if(t != NULL && (g_ascii_isspace((int)t[-1]) || t[-1] == ';')) {
+ char *u = strchr(t, ';');
+ if (u)
+ *u = '\0';
t += SIZEOF("features=")-1;
am_release_feature_set(hostp->features);
if((hostp->features = am_string_to_feature(t)) == NULL) {
- g_fprintf(outf, _("ERROR: %s: bad features value: %s\n"),
- hostp->hostname, line);
+ g_fprintf(outf, _("ERROR: %s: bad features value: '%s'\n"),
+ hostp->hostname, t);
g_fprintf(outf, _("The amfeature in the reply packet is invalid\n"));
+ remote_errors++;
+ hostp->up = HOST_DONE;
}
+ if (u)
+ *u = ';';
}
continue;
}
+ if (client_verbose && !printed_hostname) {
+ g_fprintf(outf, "HOST %s\n", hostp->hostname);
+ printed_hostname = TRUE;
+ }
+
if(strncmp_const(line, "OK ") == 0) {
+ if (client_verbose) {
+ g_fprintf(outf, "%s\n", line);
+ }
continue;
}
}
}
start_host(hostp);
- if(hostp->up == HOST_DONE)
+ if(hostp->up == HOST_DONE) {
security_close_connection(sech, hostp->hostname);
+ for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
+ run_server_dle_scripts(EXECUTE_ON_POST_DLE_AMCHECK,
+ get_config_name(), dp, -1);
+ }
+ run_server_host_scripts(EXECUTE_ON_POST_HOST_AMCHECK,
+ get_config_name(), hostp);
+ }
/* try to clean up any defunct processes, since Amanda doesn't wait() for
them explicitly */
while(waitpid(-1, NULL, WNOHANG)> 0);