X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famcheck.c;h=fdbd8cfb74f3729e52106196edc1223b03c91fbd;hb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;hp=4498cd7a6bf77a04830c3ae677fe3817dcb6f11c;hpb=d3b2175e084f88c8736ad7073eacbf4670147aec;p=debian%2Famanda diff --git a/server-src/amcheck.c b/server-src/amcheck.c index 4498cd7..fdbd8cf 100644 --- a/server-src/amcheck.c +++ b/server-src/amcheck.c @@ -31,10 +31,10 @@ #include "amanda.h" #include "util.h" #include "conffile.h" -#include "statfs.h" +#include "columnar.h" +#include "fsusage.h" #include "diskfile.h" #include "tapefile.h" -#include "tapeio.h" #include "changer.h" #include "packet.h" #include "security.h" @@ -47,6 +47,9 @@ #include "server_util.h" #include "pipespawn.h" #include "amfeatures.h" +#include "device.h" +#include "property.h" +#include "timestamp.h" #define BUFFER_SIZE 32768 @@ -63,18 +66,16 @@ void usage(void); pid_t start_client_checks(int fd); pid_t start_server_check(int fd, int do_localchk, int do_tapechk); int main(int argc, char **argv); +int check_tapefile(FILE *outf, char *tapefile); int test_server_pgm(FILE *outf, char *dir, char *pgm, int suid, uid_t dumpuid); void usage(void) { - error("Usage: amcheck%s [-am] [-w] [-sclt] [-M
] [host [disk]* ]* [-o configoption]*", versionsuffix()); + error(_("Usage: amcheck%s [-am] [-w] [-sclt] [-M
] [host [disk]* ]* [-o configoption]*"), versionsuffix()); /*NOTREACHED*/ } -static unsigned long malloc_hist_1, malloc_size_1; -static unsigned long malloc_hist_2, malloc_size_2; - static am_feature_t *our_features = NULL; static char *our_feature_string = NULL; static char *displayunit; @@ -102,19 +103,30 @@ main( int mailout; int alwaysmail; char *tempfname = NULL; - char *conffile; char *conf_diskfile; char *dumpuser; struct passwd *pw; uid_t uid_me; - int new_argc, my_argc; - char **new_argv, **my_argv; char *errstr; + config_overwrites_t *cfg_ovr; + + /* + * Configure program for internationalization: + * 1) Only set the message locale for now. + * 2) Set textdomain for all amanda related programs to "amanda" + * We don't want to be forced to support dozens of message catalogs. + */ + setlocale(LC_MESSAGES, "C"); + textdomain("amanda"); safe_fd(-1, 0); safe_cd(); set_pname("amcheck"); + /* drop root privileges */ + if (!set_root_privs(0)) { + error(_("amcheck must be run setuid root")); + } /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); @@ -122,18 +134,14 @@ main( dbopen(DBG_SUBDIR_SERVER); memset(buffer, 0, sizeof(buffer)); - malloc_size_1 = malloc_inuse(&malloc_hist_1); - snprintf(pid_str, SIZEOF(pid_str), "%ld", (long)getpid()); + g_snprintf(pid_str, SIZEOF(pid_str), "%ld", (long)getpid()); erroutput_type = ERR_INTERACTIVE; our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); - if(geteuid() == 0) { - seteuid(getuid()); - } uid_me = getuid(); alwaysmail = mailout = overwrite = 0; @@ -141,17 +149,14 @@ main( 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 */ - while((opt = getopt(my_argc, my_argv, "M:mawsclt")) != EOF) { + cfg_ovr = new_config_overwrites(argc/2); + while((opt = getopt(argc, argv, "M:mawsclto:")) != EOF) { switch(opt) { case 'M': mailto=stralloc(optarg); if(!validate_mailto(mailto)){ - printf("Invalid characters in mail address\n"); + g_printf(_("Invalid characters in mail address\n")); exit(1); } /*FALLTHROUGH*/ @@ -159,7 +164,8 @@ main( #ifdef MAILER mailout = 1; #else - printf("You can't use -%c because configure didn't find a mailer.\n", + g_printf(_("You can't use -%c because configure didn't " + "find a mailer./usr/bin/mail not found\n"), opt); exit(1); #endif @@ -169,7 +175,8 @@ main( mailout = 1; alwaysmail = 1; #else - printf("You can't use -%c because configure didn't find a mailer.\n", + g_printf(_("You can't use -%c because configure didn't " + "find a mailer./usr/bin/mail not found\n"), opt); exit(1); #endif @@ -182,6 +189,8 @@ main( break; case 'w': overwrite = 1; break; + case 'o': add_config_overwrite_opt(cfg_ovr, optarg); + break; case 't': do_tapechk = 1; break; case '?': @@ -189,8 +198,8 @@ main( usage(); } } - my_argc -= optind, my_argv += optind; - if(my_argc < 1) usage(); + argc -= optind, argv += optind; + if(argc < 1) usage(); if ((do_localchk | do_clientchk | do_tapechk) == 0) { @@ -201,27 +210,20 @@ main( if(overwrite) do_tapechk = 1; - config_name = stralloc(*my_argv); - - config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); - conffile = stralloc2(config_dir, CONFFILE_NAME); - if(read_conffile(conffile)) { - error("errors processing config file \"%s\"", conffile); - /*NOTREACHED*/ - } - + config_init(CONFIG_INIT_EXPLICIT_NAME|CONFIG_INIT_FATAL, + argv[0]); + apply_config_overwrites(cfg_ovr); dbrename(config_name, DBG_SUBDIR_SERVER); - report_bad_conf_arg(); - - amfree(conffile); if(mailout && !mailto && (getconf_seen(CNF_MAILTO)==0 || strlen(getconf_str(CNF_MAILTO)) == 0)) { - printf("\nNo mail address configured in amanda.conf\n"); + g_printf(_("\nWARNING:No mail address configured in amanda.conf.\n")); + g_printf(_("To receive dump results by email configure the " + "\"mailto\" parameter in amanda.conf\n")); if(alwaysmail) - printf("When using -a option please specify -Maddress also\n\n"); + g_printf(_("When using -a option please specify -Maddress also\n\n")); else - printf("Use -Maddress instead of -m\n\n"); + g_printf(_("Use -Maddress instead of -m\n\n")); exit(1); } if(mailout && !mailto) @@ -229,58 +231,59 @@ main( if(getconf_seen(CNF_MAILTO) && strlen(getconf_str(CNF_MAILTO)) > 0) { if(!validate_mailto(getconf_str(CNF_MAILTO))){ - printf("\nMail address in amanda.conf has invalid characters"); - printf("\nNo email will be sent\n"); + g_printf(_("\nMail address in amanda.conf has invalid characters")); + g_printf(_("\nNo email will be sent\n")); mailout = 0; } } else { - printf("\nNo mail address configured in amanda.conf\n"); + g_printf(_("\nNo mail address configured in amanda.conf\n")); if(alwaysmail) - printf("When using -a option please specify -Maddress also\n\n"); + g_printf(_("When using -a option please specify -Maddress also\n\n")); else - printf("Use -Maddress instead of -m\n\n"); + g_printf(_("Use -Maddress instead of -m\n\n")); exit(1); } } conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT); - conf_diskfile = getconf_str(CNF_DISKFILE); - if (*conf_diskfile == '/') { - conf_diskfile = stralloc(conf_diskfile); - } else { - conf_diskfile = stralloc2(config_dir, conf_diskfile); - } + conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); if(read_diskfile(conf_diskfile, &origq) < 0) { - error("could not load disklist %s", conf_diskfile); + error(_("could not load disklist %s. Make sure it exists and has correct permissions"), conf_diskfile); /*NOTREACHED*/ } - errstr = match_disklist(&origq, my_argc-1, my_argv+1); + errstr = match_disklist(&origq, argc-1, argv+1); if (errstr) { - printf("%s",errstr); + g_printf(_("%s"),errstr); amfree(errstr); } amfree(conf_diskfile); /* - * Make sure we are running as the dump user. + * Make sure we are running as the dump user. Don't use + * check_running_as(..) here, because we want to produce more + * verbose error messages. */ dumpuser = getconf_str(CNF_DUMPUSER); if ((pw = getpwnam(dumpuser)) == NULL) { - error("cannot look up dump user \"%s\"", dumpuser); + error(_("amanda.conf has dump user configured to \"%s\", but that user does not exist."), dumpuser); /*NOTREACHED*/ } uid_dumpuser = pw->pw_uid; if ((pw = getpwuid(uid_me)) == NULL) { - error("cannot look up my own uid (%ld)", (long)uid_me); + error(_("cannot get username for running user, uid %ld is not in your user database."), + (long)uid_me); /*NOTREACHED*/ } +#ifdef CHECK_USERID if (uid_me != uid_dumpuser) { - error("running as user \"%s\" instead of \"%s\"", - pw->pw_name, dumpuser); + error(_("running as user \"%s\" instead of \"%s\".\n" + "Change user to \"%s\" or change dump user to \"%s\" in amanda.conf"), + pw->pw_name, dumpuser, dumpuser, pw->pw_name); /*NOTREACHED*/ } +#endif displayunit = getconf_str(CNF_DISPLAYUNIT); unitdivisor = getconf_unit_divisor(); @@ -297,7 +300,7 @@ main( /* we need the temp file */ tempfname = vstralloc(AMANDA_TMPDIR, "/amcheck.temp.", pid_str, NULL); if((tempfd = open(tempfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) { - error("could not open %s: %s", tempfname, strerror(errno)); + error(_("could not open temporary amcheck output file %s: %s. Check permissions"), tempfname, strerror(errno)); /*NOTREACHED*/ } unlink(tempfname); /* so it goes away on close */ @@ -308,7 +311,7 @@ main( /* the main fd is a file too */ mainfname = vstralloc(AMANDA_TMPDIR, "/amcheck.main.", pid_str, NULL); if((mainfd = open(mainfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) { - error("could not open %s: %s", mainfname, strerror(errno)); + error(_("could not open amcheck server output file %s: %s. Check permissions"), mainfname, strerror(errno)); /*NOTREACHED*/ } unlink(mainfname); /* so it goes away on close */ @@ -346,14 +349,11 @@ main( server_probs = WIFSIGNALED(retstat) || WEXITSTATUS(retstat); serverchk_pid = 0; } else { - char number[NUM_STR_SIZE]; char *wait_msg = NULL; - snprintf(number, SIZEOF(number), "%ld", (long)pid); - wait_msg = vstralloc("parent: reaped bogus pid ", number, "\n", - NULL); + wait_msg = vstrallocf(_("parent: reaped bogus pid %ld\n"), (long)pid); if (fullwrite(mainfd, wait_msg, strlen(wait_msg)) < 0) { - error("write main file: %s", strerror(errno)); + error(_("write main file: %s"), strerror(errno)); /*NOTREACHED*/ } amfree(wait_msg); @@ -364,43 +364,33 @@ main( if(do_clientchk && (do_localchk || do_tapechk)) { if(lseek(tempfd, (off_t)0, 0) == (off_t)-1) { - error("seek temp file: %s", strerror(errno)); + error(_("seek temp file: %s"), strerror(errno)); /*NOTREACHED*/ } while((size = fullread(tempfd, buffer, SIZEOF(buffer))) > 0) { if (fullwrite(mainfd, buffer, (size_t)size) < 0) { - error("write main file: %s", strerror(errno)); + error(_("write main file: %s"), strerror(errno)); /*NOTREACHED*/ } } if(size < 0) { - error("read temp file: %s", strerror(errno)); + error(_("read temp file: %s"), strerror(errno)); /*NOTREACHED*/ } aclose(tempfd); } - version_string = vstralloc("\n", - "(brought to you by Amanda ", version(), ")\n", - NULL); + version_string = vstrallocf(_("\n(brought to you by Amanda %s)\n"), version()); if (fullwrite(mainfd, version_string, strlen(version_string)) < 0) { - error("write main file: %s", strerror(errno)); + error(_("write main file: %s"), strerror(errno)); /*NOTREACHED*/ } amfree(version_string); - amfree(config_dir); - amfree(config_name); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { - malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); - } - /* send mail if requested, but only if there were problems */ #ifdef MAILER @@ -419,22 +409,20 @@ main( char *err = NULL; char *extra_info = NULL; char *line = NULL; - int ret; int rc; - int sig; - char number[NUM_STR_SIZE]; fflush(stdout); if(lseek(mainfd, (off_t)0, SEEK_SET) == (off_t)-1) { - error("lseek main file: %s", strerror(errno)); + error(_("lseek main file: %s"), strerror(errno)); /*NOTREACHED*/ } if(alwaysmail && !(server_probs || client_probs)) { - subject = stralloc2(getconf_str(CNF_ORG), - " AMCHECK REPORT: NO PROBLEMS FOUND"); + subject = vstrallocf(_("%s AMCHECK REPORT: NO PROBLEMS FOUND"), + getconf_str(CNF_ORG)); } else { - subject = stralloc2(getconf_str(CNF_ORG), - " AMANDA PROBLEM: FIX BEFORE RUN, IF POSSIBLE"); + subject = vstrallocf( + _("%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 @@ -475,13 +463,13 @@ main( while((r = fullread(mainfd, buffer, SIZEOF(buffer))) > 0) { if((w = fullwrite(mailfd, buffer, (size_t)r)) != (ssize_t)r) { if(w < 0 && errno == EPIPE) { - strappend(extra_info, "EPIPE writing to mail process\n"); + strappend(extra_info, _("EPIPE writing to mail process\n")); break; } else if(w < 0) { - error("mailfd write: %s", strerror(errno)); + error(_("mailfd write: %s"), strerror(errno)); /*NOTREACHED*/ } else { - error("mailfd write: wrote " SSIZE_T_FMT " instead of " SIZE_T_FMT, w, r); + error(_("mailfd write: wrote %zd instead of %zd"), w, r); /*NOTREACHED*/ } } @@ -489,7 +477,7 @@ main( aclose(mailfd); ferr = fdopen(errfd, "r"); if (!ferr) { - error("Can't fdopen: %s", strerror(errno)); + error(_("Can't fdopen: %s"), strerror(errno)); /*NOTREACHED*/ } for(; (line = agets(ferr)) != NULL; free(line)) { @@ -502,22 +490,12 @@ main( errfd = -1; rc = 0; while (wait(&retstat) != -1) { - if (WIFSIGNALED(retstat)) { - ret = 0; - rc = sig = WTERMSIG(retstat); - } else { - sig = 0; - rc = ret = WEXITSTATUS(retstat); - } - if (rc != 0) { - if (ret == 0) { - strappend(err, "got signal "); - ret = sig; - } else { - strappend(err, "returned "); - } - snprintf(number, SIZEOF(number), "%d", ret); - strappend(err, number); + if (!WIFEXITED(retstat) || WEXITSTATUS(retstat) != 0) { + char *mailer_error = str_exit_status("mailer", retstat); + strappend(err, mailer_error); + amfree(mailer_error); + + rc = 1; } } if (rc != 0) { @@ -525,27 +503,49 @@ main( fputs(extra_info, stderr); amfree(extra_info); } - error("error running mailer %s: %s", MAILER, err); + 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 nslots, backwards, found, got_match, tapedays; -char *datestamp; -char *first_match_label = NULL, *first_match = NULL, *found_device = NULL; -char *label; -char *searchlabel, *labelstr; -tape_t *tp; -FILE *errf = NULL; +static char *datestamp; +static FILE *errf = NULL; + +int check_tapefile( + FILE *outf, + char *tapefile) +{ + struct stat statbuf; + char *quoted; + int tapebad = 0; + + if (stat(tapefile, &statbuf) == 0) { + if (!S_ISREG(statbuf.st_mode)) { + quoted = quote_string(tapefile); + g_fprintf(outf, _("ERROR: tapelist %s: should be a regular file.\n"), + quoted); + tapebad = 1; + amfree(quoted); + } else if (access(tapefile, F_OK) != 0) { + quoted = quote_string(tapefile); + g_fprintf(outf, _("ERROR: can't access tapelist %s\n"), quoted); + tapebad = 1; + amfree(quoted); + } else if (access(tapefile, W_OK) != 0) { + quoted = quote_string(tapefile); + g_fprintf(outf, _("ERROR: tapelist %s: not writable\n"), quoted); + tapebad = 1; + amfree(quoted); + } + } + return tapebad; +} int test_server_pgm( @@ -562,76 +562,199 @@ test_server_pgm( pgm = vstralloc(dir, "/", pgm, versionsuffix(), NULL); quoted = quote_string(pgm); if(stat(pgm, &statbuf) == -1) { - fprintf(outf, "ERROR: program %s: does not exist\n", + g_fprintf(outf, _("ERROR: program %s: does not exist\n"), quoted); pgmbad = 1; } else if (!S_ISREG(statbuf.st_mode)) { - fprintf(outf, "ERROR: program %s: not a file\n", + g_fprintf(outf, _("ERROR: program %s: not a file\n"), quoted); pgmbad = 1; } else if (access(pgm, X_OK) == -1) { - fprintf(outf, "ERROR: program %s: not executable\n", + g_fprintf(outf, _("ERROR: program %s: not executable\n"), quoted); pgmbad = 1; +#ifndef SINGLE_USERID } else if (suid \ && dumpuid != 0 && (statbuf.st_uid != 0 || (statbuf.st_mode & 04000) == 0)) { - fprintf(outf, "ERROR: program %s: not setuid-root\n", + g_fprintf(outf, _("ERROR: program %s: not setuid-root\n"), quoted); pgmbad = 1; +#else + /* Quiet unused parameter warnings */ + (void)suid; + (void)dumpuid; +#endif /* SINGLE_USERID */ } amfree(quoted); amfree(pgm); return pgmbad; } +/* 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")); + } + + 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; + } + + device = device_open(tapename); + + 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; +} + pid_t start_server_check( int fd, int do_localchk, int do_tapechk) { - char *tapename; - generic_fs_stats_t fs; + struct fs_usage fsusage; FILE *outf = NULL; holdingdisk_t *hdp; - pid_t pid; + pid_t pid G_GNUC_UNUSED; int confbad = 0, tapebad = 0, disklow = 0, logbad = 0; int userbad = 0, infobad = 0, indexbad = 0, pgmbad = 0; int testtape = do_tapechk; tapetype_t *tp = NULL; char *quoted; int res; - struct addrinfo *gaires; - struct addrinfo hints; + intmax_t kb_avail; switch(pid = fork()) { case -1: - error("could not fork server check: %s", strerror(errno)); - /*NOTREACHED*/ - + error(_("could not spawn a process for checking the server: %s"), strerror(errno)); + g_assert_not_reached(); + case 0: break; - + default: return pid; } - + dup2(fd, 1); dup2(fd, 2); - + set_pname("amcheck-server"); - + startclock(); if((outf = fdopen(fd, "w")) == NULL) { - error("fdopen %d: %s", fd, strerror(errno)); + error(_("fdopen %d: %s"), fd, strerror(errno)); /*NOTREACHED*/ } errf = outf; - fprintf(outf, "Amanda Tape Server Host Check\n"); - fprintf(outf, "-----------------------------\n"); + g_fprintf(outf, _("Amanda Tape Server Host Check\n")); + g_fprintf(outf, "-----------------------------\n"); if (do_localchk || testtape) { tp = lookup_tapetype(getconf_str(CNF_TAPETYPE)); @@ -646,57 +769,52 @@ start_server_check( char *lbl_templ; ColumnSpec = getconf_str(CNF_COLUMNSPEC); - if(SetColumDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { - fprintf(outf, "ERROR: %s\n", errstr); + if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) { + g_fprintf(outf, _("ERROR: %s\n"), errstr); amfree(errstr); confbad = 1; } lbl_templ = tapetype_get_lbl_templ(tp); if(strcmp(lbl_templ, "") != 0) { - if(strchr(lbl_templ, '/') == NULL) { - lbl_templ = stralloc2(config_dir, lbl_templ); - } else { - lbl_templ = stralloc(lbl_templ); - } + lbl_templ = config_dir_relative(lbl_templ); if(access(lbl_templ, R_OK) == -1) { - fprintf(outf, - "ERROR: cannot access lbl_templ file %s: %s\n", + g_fprintf(outf, + _("ERROR: cannot read label template (lbl-templ) file %s: %s. Check permissions\n"), lbl_templ, strerror(errno)); confbad = 1; } #if !defined(LPRCMD) - fprintf(outf, "ERROR: lbl_templ set but no LPRCMD defined, you should reconfigure amanda\n and make sure it find a lpr or lp command.\n"); + 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")); confbad = 1; #endif } - /* Double-check that 'localhost' resolves properly */ -#ifdef WORKING_IPV6 - hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL; - hints.ai_family = AF_UNSPEC; -#else - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET; -#endif - hints.ai_socktype = 0; - hints.ai_protocol = 0; - hints.ai_addrlen = 0; - hints.ai_addr = NULL; - hints.ai_canonname = NULL; - hints.ai_next = NULL; - res = getaddrinfo("localhost", NULL, &hints, &gaires); -#ifdef WORKING_IPV6 - if (res != 0) { - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_UNSPEC; - res = getaddrinfo("localhost", NULL, &hints, &gaires); + 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"), + getconf_int(CNF_FLUSH_THRESHOLD_DUMPED), + getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED)); } -#endif - if (res != 0) { - fprintf(outf, _("ERROR: Cannot resolve `localhost': %s\n"), gai_strerror(res)); + + 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"), + 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_int(CNF_TAPERFLUSH)); + } + + /* Double-check that 'localhost' resolves properly */ + if ((res = resolve_hostname("localhost", 0, NULL, NULL) != 0)) { + g_fprintf(outf, _("ERROR: Cannot resolve `localhost': %s\n"), gai_strerror(res)); + confbad = 1; } - if (gaires) freeaddrinfo(gaires); } /* @@ -706,30 +824,32 @@ start_server_check( /* * entreprise version will do planner/dumper suid check */ - if(access(libexecdir, X_OK) == -1) { - quoted = quote_string(libexecdir); - fprintf(outf, "ERROR: program dir %s: not accessible\n", + if(access(amlibexecdir, X_OK) == -1) { + quoted = quote_string(amlibexecdir); + g_fprintf(outf, _("ERROR: Directory %s containing Amanda tools is not accessible\n."), quoted); + g_fprintf(outf, _("Check permissions\n")); pgmbad = 1; amfree(quoted); } else { - if(test_server_pgm(outf, libexecdir, "planner", 1, uid_dumpuser)) + if(test_server_pgm(outf, amlibexecdir, "planner", 1, uid_dumpuser)) pgmbad = 1; - if(test_server_pgm(outf, libexecdir, "dumper", 1, uid_dumpuser)) + if(test_server_pgm(outf, amlibexecdir, "dumper", 1, uid_dumpuser)) pgmbad = 1; - if(test_server_pgm(outf, libexecdir, "driver", 0, uid_dumpuser)) + if(test_server_pgm(outf, amlibexecdir, "driver", 0, uid_dumpuser)) pgmbad = 1; - if(test_server_pgm(outf, libexecdir, "taper", 0, uid_dumpuser)) + if(test_server_pgm(outf, amlibexecdir, "taper", 0, uid_dumpuser)) pgmbad = 1; - if(test_server_pgm(outf, libexecdir, "amtrmidx", 0, uid_dumpuser)) + if(test_server_pgm(outf, amlibexecdir, "amtrmidx", 0, uid_dumpuser)) pgmbad = 1; - if(test_server_pgm(outf, libexecdir, "amlogroll", 0, uid_dumpuser)) + if(test_server_pgm(outf, amlibexecdir, "amlogroll", 0, uid_dumpuser)) pgmbad = 1; } if(access(sbindir, X_OK) == -1) { quoted = quote_string(sbindir); - fprintf(outf, "ERROR: program dir %s: not accessible\n", + g_fprintf(outf, _("ERROR: Directory %s containing Amanda tools is not accessible\n"), sbindir); + g_fprintf(outf, _("Check permissions\n")); pgmbad = 1; amfree(quoted); } else { @@ -744,8 +864,9 @@ start_server_check( } if(access(COMPRESS_PATH, X_OK) == -1) { quoted = quote_string(COMPRESS_PATH); - fprintf(outf, "WARNING: %s is not executable, server-compression and indexing will not work\n", - quoted); + g_fprintf(outf, _("WARNING: %s is not executable, server-compression " + "and indexing will not work. \n"),quoted); + g_fprintf(outf, _("Check permissions\n")); amfree(quoted); } } @@ -758,19 +879,15 @@ start_server_check( */ if(do_localchk || do_tapechk) { - char *conf_tapelist; char *tapefile; + char *newtapefile; char *tape_dir; char *lastslash; char *holdfile; + char * tapename; struct stat statbuf; - conf_tapelist=getconf_str(CNF_TAPELIST); - if (*conf_tapelist == '/') { - tapefile = stralloc(conf_tapelist); - } else { - tapefile = stralloc2(config_dir, conf_tapelist); - } + tapefile = config_dir_relative(getconf_str(CNF_TAPELIST)); /* * XXX There Really Ought to be some error-checking here... dhw */ @@ -783,45 +900,49 @@ start_server_check( } if(access(tape_dir, W_OK) == -1) { quoted = quote_string(tape_dir); - fprintf(outf, "ERROR: tapelist dir %s: not writable.\n", quoted); + g_fprintf(outf, _("ERROR: tapelist dir %s: not writable.\nCheck permissions\n"), + quoted); tapebad = 1; amfree(quoted); } else if(stat(tapefile, &statbuf) == -1) { quoted = quote_string(tape_dir); - fprintf(outf, "ERROR: tapelist %s (%s), " - "you must create an empty file.\n", + g_fprintf(outf, _("ERROR: tapelist %s (%s), " + "you must create an empty file.\n"), quoted, strerror(errno)); tapebad = 1; amfree(quoted); } - else if(!S_ISREG(statbuf.st_mode)) { - quoted = quote_string(tapefile); - fprintf(outf, "ERROR: tapelist %s: should be a regular file.\n", - quoted); - tapebad = 1; - amfree(quoted); - } - else if(access(tapefile, F_OK) != 0) { - quoted = quote_string(tapefile); - fprintf(outf, "ERROR: can't access tapelist %s\n", quoted); - tapebad = 1; - amfree(quoted); - } else if(access(tapefile, F_OK) == 0 && access(tapefile, W_OK) != 0) { - quoted = quote_string(tapefile); - fprintf(outf, "ERROR: tapelist %s: not writable\n", quoted); - tapebad = 1; - amfree(quoted); - } else if(read_tapelist(tapefile)) { - quoted = quote_string(tapefile); - fprintf(outf, "ERROR: tapelist %s: parse error\n", quoted); - tapebad = 1; - amfree(quoted); + else { + tapebad |= check_tapefile(outf, tapefile); + if (tapebad == 0 && read_tapelist(tapefile)) { + quoted = quote_string(tapefile); + g_fprintf(outf, _("ERROR: tapelist %s: parse error\n"), quoted); + tapebad = 1; + amfree(quoted); + } + newtapefile = stralloc2(tapefile, ".new"); + tapebad |= check_tapefile(outf, newtapefile); + amfree(newtapefile); + newtapefile = stralloc2(tapefile, ".amlabel"); + tapebad |= check_tapefile(outf, newtapefile); + amfree(newtapefile); + newtapefile = stralloc2(tapefile, ".amlabel.new"); + tapebad |= check_tapefile(outf, newtapefile); + amfree(newtapefile); + newtapefile = stralloc2(tapefile, ".yesterday"); + tapebad |= check_tapefile(outf, newtapefile); + amfree(newtapefile); + newtapefile = stralloc2(tapefile, ".yesterday.new"); + tapebad |= check_tapefile(outf, newtapefile); + amfree(newtapefile); } - holdfile = vstralloc(config_dir, "/", "hold", NULL); + holdfile = config_dir_relative("hold"); if(access(holdfile, F_OK) != -1) { quoted = quote_string(holdfile); - fprintf(outf, "WARNING: hold file %s exists\n", holdfile); + g_fprintf(outf, _("WARNING: hold file %s exists."), holdfile); + g_fprintf(outf, _("Amdump will sleep as long as this file exists.\n")); + g_fprintf(outf, _("You might want to delete the existing hold file\n")); amfree(quoted); } amfree(tapefile); @@ -830,89 +951,92 @@ start_server_check( tapename = getconf_str(CNF_TAPEDEV); if (tapename == NULL) { if (getconf_str(CNF_TPCHANGER) == NULL) { - fprintf(outf, "WARNING: No tapedev or tpchanger specified\n"); + g_fprintf(outf, _("WARNING:Parameter \"tapedev\" or \"tpchanger\" not specified in amanda.conf.\n")); testtape = 0; do_tapechk = 0; } - } else if (strncmp_const(tapename, "null:") == 0) { - fprintf(outf, - "WARNING: tapedev is %s, dumps will be thrown away\n", - tapename); - testtape = 0; - do_tapechk = 0; } } /* check available disk space */ if(do_localchk) { - for(hdp = holdingdisks; hdp != NULL; hdp = hdp->next) { + for(hdp = getconf_holdingdisks(); hdp != NULL; hdp = holdingdisk_next(hdp)) { quoted = quote_string(holdingdisk_get_diskdir(hdp)); - if(get_fs_stats(holdingdisk_get_diskdir(hdp), &fs) == -1) { - fprintf(outf, "ERROR: holding dir %s (%s), " - "you must create a directory.\n", + if(get_fs_usage(holdingdisk_get_diskdir(hdp), NULL, &fsusage) == -1) { + g_fprintf(outf, _("ERROR: holding dir %s (%s), " + "you must create a directory.\n"), quoted, strerror(errno)); disklow = 1; + amfree(quoted); + continue; } - else if(access(holdingdisk_get_diskdir(hdp), W_OK) == -1) { - fprintf(outf, "ERROR: holding disk %s: not writable: %s.\n", + + /* do the division first to avoid potential integer overflow */ + if (fsusage.fsu_bavail_top_bit_set) + kb_avail = 0; + else + kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize; + + if(access(holdingdisk_get_diskdir(hdp), W_OK) == -1) { + g_fprintf(outf, _("ERROR: holding disk %s: not writable: %s.\n"), quoted, strerror(errno)); + g_fprintf(outf, _("Check permissions\n")); disklow = 1; } else if(access(holdingdisk_get_diskdir(hdp), X_OK) == -1) { - fprintf(outf, "ERROR: holding disk %s: not searcheable: %s.\n", + g_fprintf(outf, _("ERROR: holding disk %s: not searcheable: %s.\n"), quoted, strerror(errno)); - disklow = 1; - } - else if(fs.avail == (off_t)-1) { - fprintf(outf, - "WARNING: holding disk %s: " - "available space unknown (" OFF_T_FMT" KB requested)\n", - quoted, (OFF_T_FMT_TYPE)holdingdisk_get_disksize(hdp)); + g_fprintf(outf, _("Check permissions of ancestors of %s\n"), quoted); disklow = 1; } else if(holdingdisk_get_disksize(hdp) > (off_t)0) { - if(fs.avail < holdingdisk_get_disksize(hdp)) { - fprintf(outf, - "WARNING: holding disk %s: " - "only " OFF_T_FMT " %sB free (" - OFF_T_FMT " %sB requested)\n", quoted, - (OFF_T_FMT_TYPE)(fs.avail / (off_t)unitdivisor), + if(kb_avail == 0) { + g_fprintf(outf, + _("WARNING: holding disk %s: " + "no space available (%lld %sB requested)\n"), quoted, + (long long)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor), + displayunit); + disklow = 1; + } + else if(kb_avail < holdingdisk_get_disksize(hdp)) { + g_fprintf(outf, + _("WARNING: holding disk %s: " + "only %lld %sB available (%lld %sB requested)\n"), quoted, + (long long)(kb_avail / (off_t)unitdivisor), displayunit, - (OFF_T_FMT_TYPE)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor), + (long long)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor), displayunit); disklow = 1; } else { - fprintf(outf, - "Holding disk %s: " OFF_T_FMT - " %sB disk space available," - " using " OFF_T_FMT " %sB as requested\n", + g_fprintf(outf, + _("Holding disk %s: %lld %sB disk space available," + " using %lld %sB as requested\n"), quoted, - (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor), + (long long)(kb_avail / (off_t)unitdivisor), displayunit, - (OFF_T_FMT_TYPE)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor), + (long long)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor), displayunit); } } else { - if((fs.avail + holdingdisk_get_disksize(hdp)) < (off_t)0) { - fprintf(outf, - "WARNING: holding disk %s: " - "only " OFF_T_FMT " %sB free, using nothing\n", - quoted, (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor), + if(kb_avail < -holdingdisk_get_disksize(hdp)) { + g_fprintf(outf, + _("WARNING: holding disk %s: " + "only %lld %sB free, using nothing\n"), + quoted, (long long)(kb_avail / (off_t)unitdivisor), displayunit); + g_fprintf(outf, _("WARNING: Not enough free space specified in amanda.conf\n")); disklow = 1; } else { - fprintf(outf, - "Holding disk %s: " - OFF_T_FMT " %sB disk space available, using " - OFF_T_FMT " %sB\n", + g_fprintf(outf, + _("Holding disk %s: %lld %sB disk space available, using %lld %sB\n"), quoted, - (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor), + (long long)(kb_avail/(off_t)unitdivisor), displayunit, - (OFF_T_FMT_TYPE)((fs.avail + holdingdisk_get_disksize(hdp)) / (off_t)unitdivisor), + (long long)((kb_avail + holdingdisk_get_disksize(hdp)) / (off_t)unitdivisor), displayunit); } } @@ -929,22 +1053,17 @@ start_server_check( struct stat stat_old; struct stat statbuf; - conf_logdir = getconf_str(CNF_LOGDIR); - if (*conf_logdir == '/') { - conf_logdir = stralloc(conf_logdir); - } else { - conf_logdir = stralloc2(config_dir, conf_logdir); - } + conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR)); logfile = vstralloc(conf_logdir, "/log", NULL); quoted = quote_string(conf_logdir); if(stat(conf_logdir, &statbuf) == -1) { - fprintf(outf, "ERROR: logdir %s (%s), you must create directory.\n", + g_fprintf(outf, _("ERROR: logdir %s (%s), you must create directory.\n"), quoted, strerror(errno)); disklow = 1; } else if(access(conf_logdir, W_OK) == -1) { - fprintf(outf, "ERROR: log dir %s: not writable\n", quoted); + g_fprintf(outf, _("ERROR: log dir %s: not writable\n"), quoted); logbad = 1; } amfree(quoted); @@ -954,7 +1073,7 @@ start_server_check( logbad = 2; if(access(logfile, W_OK) != 0) { quoted = quote_string(logfile); - fprintf(outf, "ERROR: log file %s: not writable\n", quoted); + g_fprintf(outf, _("ERROR: log file %s: not writable\n"), quoted); amfree(quoted); } } @@ -963,18 +1082,21 @@ start_server_check( quoted = quote_string(olddir); if (stat(olddir,&stat_old) == 0) { /* oldlog exist */ if(!(S_ISDIR(stat_old.st_mode))) { - fprintf(outf, "ERROR: oldlog directory %s is not a directory\n", + 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) { - fprintf(outf, "ERROR: oldlog dir %s: not writable\n", quoted); + 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) { - fprintf(outf, "ERROR: oldlog directory %s is not a directory\n", + 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; } amfree(quoted); @@ -993,86 +1115,15 @@ start_server_check( } if (testtape) { - /* check that the tape is a valid amanda tape */ - int tape_status; - - tapedays = getconf_int(CNF_TAPECYCLE); - labelstr = getconf_str(CNF_LABELSTR); - tapename = getconf_str(CNF_TAPEDEV); - - if (!getconf_seen(CNF_TPCHANGER) && getconf_int(CNF_RUNTAPES) != 1) { - fprintf(outf, - "WARNING: if a tape changer is not available, runtapes must be set to 1\n"); - } - - tape_status = taper_scan(NULL, &label, &datestamp, &tapename, - FILE_taperscan_output_callback, outf); - if (tapename) { - if (tape_access(tapename,F_OK) == -1) { - fprintf(outf, "ERROR: Can't access device %s: %s\n", tapename, - strerror(errno)); - tapebad = 1; - } - if (tape_access(tapename,R_OK) == -1) { - fprintf(outf, "ERROR: Can't read device %s: %s\n", tapename, - strerror(errno)); - tapebad = 1; - } - if (tape_access(tapename,W_OK) == -1) { - fprintf(outf, "ERROR: Can't write to device %s: %s\n", tapename, - strerror(errno)); - tapebad = 1; - } - } - if (tape_status < 0) { - tape_t *exptape = lookup_last_reusable_tape(0); - fprintf(outf, " (expecting "); - if(exptape != NULL) fprintf(outf, "tape %s or ", exptape->label); - fprintf(outf, "a new tape)\n"); - tapebad = 1; - } else { - if (overwrite) { - char *wrlabel_status; - wrlabel_status = tape_wrlabel(tapename, "X", label, - (unsigned)(tapetype_get_blocksize(tp) * 1024)); - if (wrlabel_status != NULL) { - if (tape_status == 3) { - fprintf(outf, - "ERROR: Could not label brand new tape: %s\n", - wrlabel_status); - } else { - fprintf(outf, - "ERROR: tape %s label ok, but is not writable (%s)\n", - label, wrlabel_status); - } - tapebad = 1; - } else { - if (tape_status != 3) { - fprintf(outf, "Tape %s is writable; rewrote label.\n", label); - } else { - fprintf(outf, "Wrote label %s to brand new tape.\n", label); - } - } - } else { - fprintf(outf, "NOTE: skipping tape-writable test\n"); - if (tape_status == 3) { - fprintf(outf, - "Found a brand new tape, will label it %s.\n", - label); - } else { - fprintf(outf, "Tape %s label ok\n", label); - } - } - } - amfree(tapename); + tapebad = !test_tape_status(outf); } else if (do_tapechk) { - fprintf(outf, "WARNING: skipping tape test because amdump or amflush seem to be running\n"); - fprintf(outf, "WARNING: if they are not, you must run amcleanup\n"); + 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) { - fprintf(outf, "WARNING: amdump or amflush seem to be running\n"); - fprintf(outf, "WARNING: if they are not, you must run amcleanup\n"); + 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")); } else { - fprintf(outf, "NOTE: skipping tape checks\n"); + g_fprintf(outf, _("NOTE: skipping tape checks\n")); } /* @@ -1100,83 +1151,73 @@ start_server_check( conf_runspercycle = getconf_int(CNF_RUNSPERCYCLE); if(conf_tapecycle <= conf_runspercycle) { - fprintf(outf, "WARNING: tapecycle (%d) <= runspercycle (%d).\n", + g_fprintf(outf, _("WARNING: tapecycle (%d) <= runspercycle (%d).\n"), conf_tapecycle, conf_runspercycle); } - conf_infofile = getconf_str(CNF_INFOFILE); - if (*conf_infofile == '/') { - conf_infofile = stralloc(conf_infofile); - } else { - conf_infofile = stralloc2(config_dir, conf_infofile); - } + conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE)); + conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR)); - conf_indexdir = getconf_str(CNF_INDEXDIR); - if (*conf_indexdir == '/') { - conf_indexdir = stralloc(conf_indexdir); - } else { - conf_indexdir = stralloc2(config_dir, conf_indexdir); - } - -#if TEXTDB quoted = quote_string(conf_infofile); if(stat(conf_infofile, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: conf info dir %s does not exist\n", + g_fprintf(outf, _("NOTE: conf info dir %s does not exist\n"), quoted); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: conf info dir %s (%s)\n", + g_fprintf(outf, _("ERROR: conf info dir %s (%s)\n"), quoted, strerror(errno)); infobad = 1; } amfree(conf_infofile); } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: info dir %s: not a directory\n", quoted); + g_fprintf(outf, _("ERROR: info dir %s: not a directory\n"), quoted); + g_fprintf(outf, _("Remove the entry and create a new directory\n")); amfree(conf_infofile); infobad = 1; } else if (access(conf_infofile, W_OK) == -1) { - fprintf(outf, "ERROR: info dir %s: not writable\n", quoted); + g_fprintf(outf, _("ERROR: info dir %s: not writable\n"), quoted); + g_fprintf(outf, _("Check permissions\n")); amfree(conf_infofile); infobad = 1; } else { char *errmsg = NULL; if (check_infofile(conf_infofile, &origq, &errmsg) == -1) { - fprintf(outf, "ERROR: Can't copy infofile: %s\n", errmsg); + g_fprintf(outf, "ERROR: Can't copy infofile: %s\n", errmsg); infobad = 1; amfree(errmsg); } strappend(conf_infofile, "/"); } amfree(quoted); -#endif while(!empty(origq)) { hostp = origq.head->host; host = sanitise_filename(hostp->hostname); -#if TEXTDB if(conf_infofile) { hostinfodir = newstralloc2(hostinfodir, conf_infofile, host); quoted = quote_string(hostinfodir); if(stat(hostinfodir, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: host info dir %s does not exist\n", + g_fprintf(outf, _("NOTE: host info dir %s does not exist\n"), quoted); - fprintf(outf, - "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, + _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: host info dir %s (%s)\n", + g_fprintf(outf, _("ERROR: host info dir %s (%s)\n"), quoted, strerror(errno)); infobad = 1; } amfree(hostinfodir); } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: info dir %s: not a directory\n", + g_fprintf(outf, _("ERROR: info dir %s: not a directory\n"), quoted); + g_fprintf(outf, _("Remove the entry and create a new directory\n")); amfree(hostinfodir); infobad = 1; } else if (access(hostinfodir, W_OK) == -1) { - fprintf(outf, "ERROR: info dir %s: not writable\n", quoted); + g_fprintf(outf, _("ERROR: info dir %s: not writable\n"), quoted); + g_fprintf(outf, _("Check permissions\n")); amfree(hostinfodir); infobad = 1; } else { @@ -1184,10 +1225,8 @@ start_server_check( } amfree(quoted); } -#endif for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { disk = sanitise_filename(dp->name); -#if TEXTDB if(hostinfodir) { char *quotedif; @@ -1197,39 +1236,42 @@ start_server_check( quotedif = quote_string(infofile); if(stat(diskdir, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: info dir %s does not exist\n", + g_fprintf(outf, _("NOTE: info dir %s does not exist\n"), quoted); - fprintf(outf, - "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, + _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: info dir %s (%s)\n", + g_fprintf(outf, _("ERROR: info dir %s (%s)\n"), quoted, strerror(errno)); infobad = 1; } } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: info dir %s: not a directory\n", + g_fprintf(outf, _("ERROR: info dir %s: not a directory\n"), quoted); + g_fprintf(outf, _("Remove the entry and create a new directory\n")); infobad = 1; } else if (access(diskdir, W_OK) == -1) { - fprintf(outf, "ERROR: info dir %s: not writable\n", + g_fprintf(outf, _("ERROR: info dir %s: not writable\n"), quoted); + g_fprintf(outf,_("Check permissions\n")); infobad = 1; } else if(stat(infofile, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: info file %s does not exist\n", + g_fprintf(outf, _("NOTE: info file %s does not exist\n"), quotedif); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: info dir %s (%s)\n", + g_fprintf(outf, _("ERROR: info dir %s (%s)\n"), quoted, strerror(errno)); infobad = 1; } } else if (!S_ISREG(statbuf.st_mode)) { - fprintf(outf, "ERROR: info file %s: not a file\n", + g_fprintf(outf, _("ERROR: info file %s: not a file\n"), quotedif); + g_fprintf(outf, _("Remove the entry and create a new file\n")); infobad = 1; } else if (access(infofile, R_OK) == -1) { - fprintf(outf, "ERROR: info file %s: not readable\n", + g_fprintf(outf, _("ERROR: info file %s: not readable\n"), quotedif); infobad = 1; } @@ -1237,28 +1279,28 @@ start_server_check( amfree(quoted); amfree(infofile); } -#endif if(dp->index) { if(! indexdir_checked) { quoted = quote_string(conf_indexdir); if(stat(conf_indexdir, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: index dir %s does not exist\n", + g_fprintf(outf, _("NOTE: index dir %s does not exist\n"), quoted); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: index dir %s (%s)\n", + g_fprintf(outf, _("ERROR: index dir %s (%s)\n"), quoted, strerror(errno)); indexbad = 1; } amfree(conf_indexdir); } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: index dir %s: not a directory\n", + g_fprintf(outf, _("ERROR: index dir %s: not a directory\n"), quoted); + g_fprintf(outf, _("Remove the entry and create a new directory\n")); amfree(conf_indexdir); indexbad = 1; } else if (access(conf_indexdir, W_OK) == -1) { - fprintf(outf, "ERROR: index dir %s: not writable\n", + g_fprintf(outf, _("ERROR: index dir %s: not writable\n"), quoted); amfree(conf_indexdir); indexbad = 1; @@ -1274,22 +1316,23 @@ start_server_check( quoted = quote_string(hostindexdir); if(stat(hostindexdir, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: index dir %s does not exist\n", + g_fprintf(outf, _("NOTE: index dir %s does not exist\n"), quoted); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: index dir %s (%s)\n", + g_fprintf(outf, _("ERROR: index dir %s (%s)\n"), quoted, strerror(errno)); indexbad = 1; } amfree(hostindexdir); } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: index dir %s: not a directory\n", + g_fprintf(outf, _("ERROR: index dir %s: not a directory\n"), quoted); + g_fprintf(outf, _("Remove the entry and create a new directory\n")); amfree(hostindexdir); indexbad = 1; } else if (access(hostindexdir, W_OK) == -1) { - fprintf(outf, "ERROR: index dir %s: not writable\n", + g_fprintf(outf, _("ERROR: index dir %s: not writable\n"), quoted); amfree(hostindexdir); indexbad = 1; @@ -1304,20 +1347,21 @@ start_server_check( quoted = quote_string(diskdir); if(stat(diskdir, &statbuf) == -1) { if (errno == ENOENT) { - fprintf(outf, "NOTE: index dir %s does not exist\n", + g_fprintf(outf, _("NOTE: index dir %s does not exist\n"), quoted); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + g_fprintf(outf, _("NOTE: it will be created on the next run.\n")); } else { - fprintf(outf, "ERROR: index dir %s (%s)\n", + g_fprintf(outf, _("ERROR: index dir %s (%s)\n"), quoted, strerror(errno)); indexbad = 1; } } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: index dir %s: not a directory\n", + g_fprintf(outf, _("ERROR: index dir %s: not a directory\n"), quoted); + g_fprintf(outf, _("Remove the entry and create a new directory\n")); indexbad = 1; } else if (access(diskdir, W_OK) == -1) { - fprintf(outf, "ERROR: index dir %s: is not writable\n", + g_fprintf(outf, _("ERROR: index dir %s: is not writable\n"), quoted); indexbad = 1; } @@ -1328,26 +1372,33 @@ start_server_check( if ( dp->encrypt == ENCRYPT_SERV_CUST ) { if ( dp->srv_encrypt[0] == '\0' ) { - fprintf(outf, "ERROR: server encryption program not specified\n"); + g_fprintf(outf, _("ERROR: server encryption program not specified\n")); + g_fprintf(outf, _("Specify \"server_custom_encrypt\" in the dumptype\n")); pgmbad = 1; } else if(access(dp->srv_encrypt, X_OK) == -1) { - fprintf(outf, "ERROR: %s is not executable, server encryption will not work\n", + g_fprintf(outf, _("ERROR: %s is not executable, server encryption will not work\n"), dp->srv_encrypt ); + g_fprintf(outf, _("Check file type\n")); pgmbad = 1; } } if ( dp->compress == COMP_SERVER_CUST ) { if ( dp->srvcompprog[0] == '\0' ) { - fprintf(outf, "ERROR: server custom compression program not specified\n"); + g_fprintf(outf, _("ERROR: server custom compression program " + "not specified\n")); + g_fprintf(outf, _("Specify \"server_custom_compress\" in " + "the dumptype\n")); pgmbad = 1; } else if(access(dp->srvcompprog, X_OK) == -1) { quoted = quote_string(dp->srvcompprog); - fprintf(outf, "ERROR: %s is not executable, server custom compression will not work\n", + g_fprintf(outf, _("ERROR: %s is not executable, server custom " + "compression will not work\n"), quoted); amfree(quoted); + g_fprintf(outf, _("Check file type\n")); pgmbad = 1; } } @@ -1366,20 +1417,11 @@ start_server_check( } amfree(datestamp); - amfree(label); - amfree(config_dir); - amfree(config_name); - fprintf(outf, "Server check took %s seconds\n", walltime_str(curclock())); + g_fprintf(outf, _("Server check took %s seconds\n"), walltime_str(curclock())); fflush(outf); - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { - malloc_list(fd, malloc_hist_1, malloc_hist_2); - } - exit(userbad \ || confbad \ || tapebad \ @@ -1424,8 +1466,8 @@ start_host( } if (strcmp(hostp->hostname,"localhost") == 0) { - fprintf(outf, - "WARNING: Usage of fully qualified hostname recommended for Client %s.\n", + g_fprintf(outf, + _("WARNING: Usage of fully qualified hostname recommended for Client %s.\n"), hostp->hostname); } @@ -1449,40 +1491,46 @@ start_host( if(!am_has_feature(hostp->features, fe_selfcheck_req) && !am_has_feature(hostp->features, fe_selfcheck_req_device)) { - fprintf(outf, - "ERROR: Client %s does not support selfcheck REQ packet.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support selfcheck REQ packet.\n"), hostp->hostname); + g_fprintf(outf, _("Client might be of a very old version\n")); } if(!am_has_feature(hostp->features, fe_selfcheck_rep)) { - fprintf(outf, - "ERROR: Client %s does not support selfcheck REP packet.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support selfcheck REP packet.\n"), hostp->hostname); + g_fprintf(outf, _("Client might be of a very old version\n")); } if(!am_has_feature(hostp->features, fe_sendsize_req_options) && !am_has_feature(hostp->features, fe_sendsize_req_no_options) && !am_has_feature(hostp->features, fe_sendsize_req_device)) { - fprintf(outf, - "ERROR: Client %s does not support sendsize REQ packet.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support sendsize REQ packet.\n"), hostp->hostname); + g_fprintf(outf, _("Client might be of a very old version\n")); } if(!am_has_feature(hostp->features, fe_sendsize_rep)) { - fprintf(outf, - "ERROR: Client %s does not support sendsize REP packet.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support sendsize REP packet.\n"), hostp->hostname); + g_fprintf(outf, _("Client might be of a very old version\n")); } if(!am_has_feature(hostp->features, fe_sendbackup_req) && !am_has_feature(hostp->features, fe_sendbackup_req_device)) { - fprintf(outf, - "ERROR: Client %s does not support sendbackup REQ packet.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support sendbackup REQ packet.\n"), hostp->hostname); + g_fprintf(outf, _("Client might be of a very old version\n")); } if(!am_has_feature(hostp->features, fe_sendbackup_rep)) { - fprintf(outf, - "ERROR: Client %s does not support sendbackup REP packet.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support sendbackup REP packet.\n"), hostp->hostname); + g_fprintf(outf, _("Client might be of a very old version\n")); } - snprintf(number, SIZEOF(number), "%d", hostp->maxdumps); + g_snprintf(number, SIZEOF(number), "%d", hostp->maxdumps); req = vstralloc("SERVICE ", "selfcheck", "\n", "OPTIONS ", has_features ? "features=" : "", @@ -1524,45 +1572,64 @@ start_host( if ((dp->name && qname[0] == '"') || (dp->device && qdevice[0] == '"')) { if(!am_has_feature(hostp->features, fe_interface_quoted_text)) { - fprintf(outf, - "WARNING: %s:%s:%s host does not support quoted text\n", + g_fprintf(outf, + _("WARNING: %s:%s:%s host does not support quoted text\n"), hostp->hostname, qname, qdevice); + g_fprintf(outf, _("You must upgrade amanda on the client to " + "specify a quoted text/device in the disklist, " + "or don't use quoted text for the device.\n")); } } if(dp->device) { if(!am_has_feature(hostp->features, fe_selfcheck_req_device)) { - fprintf(outf, - "ERROR: %s:%s (%s): selfcheck does not support device.\n", + g_fprintf(outf, + _("ERROR: %s:%s (%s): selfcheck does not support device.\n"), hostp->hostname, qname, dp->device); + g_fprintf(outf, _("You must upgrade amanda on the client to " + "specify a diskdevice in the disklist " + "or don't specify a diskdevice in the disklist.\n")); } if(!am_has_feature(hostp->features, fe_sendsize_req_device)) { - fprintf(outf, - "ERROR: %s:%s (%s): sendsize does not support device.\n", + g_fprintf(outf, + _("ERROR: %s:%s (%s): sendsize does not support device.\n"), hostp->hostname, qname, dp->device); + g_fprintf(outf, _("You must upgrade amanda on the client to " + "specify a diskdevice in the disklist" + " or don't specify a diskdevice in the disklist.\n")); } if(!am_has_feature(hostp->features, fe_sendbackup_req_device)) { - fprintf(outf, - "ERROR: %s:%s (%s): sendbackup does not support device.\n", + g_fprintf(outf, + _("ERROR: %s:%s (%s): sendbackup does not support device.\n"), hostp->hostname, qname, dp->device); + g_fprintf(outf, _("You must upgrade amanda on the client to " + "specify a diskdevice in the disklist" + " or don't specify a diskdevice in the disklist.\n")); } } if(strcmp(dp->program,"DUMP") == 0 || strcmp(dp->program,"GNUTAR") == 0) { if(strcmp(dp->program, "DUMP") == 0 && !am_has_feature(hostp->features, fe_program_dump)) { - fprintf(outf, "ERROR: %s:%s does not support DUMP.\n", + g_fprintf(outf, _("ERROR: %s:%s does not support DUMP.\n"), hostp->hostname, qname); + g_fprintf(outf, _("You must upgrade amanda on the client to use DUMP " + "or you can use another program.\n")); } if(strcmp(dp->program, "GNUTAR") == 0 && !am_has_feature(hostp->features, fe_program_gnutar)) { - fprintf(outf, "ERROR: %s:%s does not support GNUTAR.\n", + g_fprintf(outf, _("ERROR: %s:%s does not support GNUTAR.\n"), hostp->hostname, qname); + 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 && !am_has_feature(hostp->features, fe_calcsize_estimate)) { - fprintf(outf, "ERROR: %s:%s does not support CALCSIZE for estimate, using CLIENT.\n", + 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; } if(dp->estimate == ES_CALCSIZE && @@ -1573,21 +1640,28 @@ start_host( if(dp->compress == COMP_CUST && !am_has_feature(hostp->features, fe_options_compress_cust)) { - fprintf(outf, - "ERROR: Client %s does not support custom compression.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support custom compression.\n"), hostp->hostname); + g_fprintf(outf, _("You must upgrade amanda on the client to " + "use custom compression\n")); + g_fprintf(outf, _("Otherwise you can use the default client " + "compression program.\n")); } if(dp->encrypt == ENCRYPT_CUST ) { if ( !am_has_feature(hostp->features, fe_options_encrypt_cust)) { - fprintf(outf, - "ERROR: Client %s does not support data encryption.\n", + g_fprintf(outf, + _("ERROR: Client %s does not support data encryption.\n"), hostp->hostname); + g_fprintf(outf, _("You must upgrade amanda on the client to use encryption program.\n")); remote_errors++; } else if ( dp->compress == COMP_SERVER_FAST || dp->compress == COMP_SERVER_BEST || dp->compress == COMP_SERVER_CUST ) { - fprintf(outf, - "ERROR: %s: Client encryption with server compression is not supported. See amanda.conf(5) for detail.\n", hostp->hostname); + g_fprintf(outf, + _("ERROR: %s: Client encryption with server compression " + "is not supported. See amanda.conf(5) for detail.\n"), + hostp->hostname); remote_errors++; } } @@ -1612,8 +1686,10 @@ start_host( } } else { if(!am_has_feature(hostp->features, fe_program_backup_api)) { - fprintf(outf, "ERROR: %s:%s does not support BACKUP-API.\n", + g_fprintf(outf, _("ERROR: %s:%s does not support BACKUP-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 ", @@ -1671,12 +1747,12 @@ start_host( secdrv = security_getdriver(hostp->disks->security_driver); if (secdrv == NULL) { - error("could not find security driver '%s' for host '%s'", + fprintf(stderr, _("Could not find security driver \"%s\" for host \"%s\". auth for this dle is invalid\n"), hostp->disks->security_driver, hostp->hostname); - /*NOTREACHED*/ + } else { + protocol_sendreq(hostp->hostname, secdrv, amhost_get_security_conf, + req, conf_ctimeout, handle_result, hostp); } - protocol_sendreq(hostp->hostname, secdrv, amhost_get_security_conf, - req, conf_ctimeout, handle_result, hostp); amfree(req); @@ -1695,7 +1771,7 @@ start_client_checks( switch(pid = fork()) { case -1: - error("could not fork client check: %s", strerror(errno)); + error(_("INTERNAL ERROR:could not fork client check: %s"), strerror(errno)); /*NOTREACHED*/ case 0: @@ -1713,13 +1789,13 @@ start_client_checks( startclock(); if((outf = fdopen(fd, "w")) == NULL) { - error("fdopen %d: %s", fd, strerror(errno)); + error(_("fdopen %d: %s"), fd, strerror(errno)); /*NOTREACHED*/ } errf = outf; - fprintf(outf, "\nAmanda Backup Client Hosts Check\n"); - fprintf(outf, "--------------------------------\n"); + g_fprintf(outf, _("\nAmanda Backup Client Hosts Check\n")); + g_fprintf(outf, "--------------------------------\n"); protocol_init(); @@ -1736,22 +1812,15 @@ start_client_checks( protocol_run(); - fprintf(outf, - "Client check: %d host%s checked in %s seconds, %d problem%s found\n", - hostcount, (hostcount == 1) ? "" : "s", - walltime_str(curclock()), - remote_errors, (remote_errors == 1) ? "" : "s"); + g_fprintf(outf, plural(_("Client check: %d host checked in %s seconds."), + _("Client check: %d hosts checked in %s seconds."), + hostcount), + hostcount, walltime_str(curclock())); + g_fprintf(outf, plural(_(" %d problem found.\n"), + _(" %d problems found.\n"), remote_errors), + remote_errors); fflush(outf); - amfree(config_dir); - amfree(config_name); - - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { - malloc_list(fd, malloc_hist_1, malloc_hist_2); - } - exit(userbad || remote_errors > 0); /*NOTREACHED*/ return 0; @@ -1775,8 +1844,8 @@ handle_result( hostp->up = HOST_READY; if (pkt == NULL) { - fprintf(outf, - "WARNING: %s: selfcheck request failed: %s\n", hostp->hostname, + g_fprintf(outf, + _("WARNING: %s: selfcheck request failed: %s\n"), hostp->hostname, security_geterror(sech)); remote_errors++; hostp->up = HOST_DONE; @@ -1784,7 +1853,7 @@ handle_result( } #if 0 - fprintf(errf, "got response from %s:\n----\n%s----\n\n", + g_fprintf(errf, _("got response from %s:\n----\n%s----\n\n"), hostp->hostname, pkt->body); #endif @@ -1804,8 +1873,9 @@ handle_result( t += SIZEOF("features=")-1; am_release_feature_set(hostp->features); if((hostp->features = am_string_to_feature(t)) == NULL) { - fprintf(outf, "ERROR: %s: bad features value: %s\n", + g_fprintf(outf, _("ERROR: %s: bad features value: %s\n"), hostp->hostname, line); + g_fprintf(outf, _("The amfeature in the reply packet is invalid\n")); } } @@ -1827,7 +1897,7 @@ handle_result( if(!((hostp->features == NULL) && (pkt->type == P_NAK) && ((strcmp(t - 1, "unknown service: noop") == 0) || (strcmp(t - 1, "noop: invalid service") == 0)))) { - fprintf(outf, "ERROR: %s%s: %s\n", + g_fprintf(outf, _("ERROR: %s%s: %s\n"), (pkt->type == P_NAK) ? "NAK " : "", hostp->hostname, t - 1); @@ -1837,7 +1907,7 @@ handle_result( continue; } - fprintf(outf, "ERROR: %s: unknown response: %s\n", + g_fprintf(outf, _("ERROR: %s: unknown response: %s\n"), hostp->hostname, line); remote_errors++; hostp->up = HOST_DONE; @@ -1847,8 +1917,7 @@ handle_result( * The client does not support the features list, so give it an * empty one. */ - dbprintf(("%s: no feature set from host %s\n", - debug_prefix_time(NULL), hostp->hostname)); + dbprintf(_("no feature set from host %s\n"), hostp->hostname); hostp->features = am_set_default_feature_set(); } for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { @@ -1859,4 +1928,7 @@ handle_result( start_host(hostp); if(hostp->up == HOST_DONE) security_close_connection(sech, hostp->hostname); + /* try to clean up any defunct processes, since Amanda doesn't wait() for + them explicitly */ + while(waitpid(-1, NULL, WNOHANG)> 0); }