X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fselfcheck.c;h=e044a6cd50fbc6febd1aad01a2f253d2bab5ea48;hb=refs%2Ftags%2Fupstream%2F3.3.1;hp=49306d481efac38b7ba2776b6268c4f212ed0cff;hpb=1194fb66aa28d9929c3f2bef3cc6c1c3f40a60a4;p=debian%2Famanda diff --git a/client-src/selfcheck.c b/client-src/selfcheck.c index 49306d4..e044a6c 100644 --- a/client-src/selfcheck.c +++ b/client-src/selfcheck.c @@ -25,14 +25,13 @@ * University of Maryland at College Park */ /* - * $Id: selfcheck.c,v 1.76 2006/01/14 04:37:18 paddy_s Exp $ + * $Id: selfcheck.c 10421 2008-03-06 18:48:30Z martineau $ * * do self-check and send back any error messages */ #include "amanda.h" -#include "statfs.h" -#include "version.h" +#include "fsusage.h" #include "getfsent.h" #include "amandates.h" #include "clock.h" @@ -40,6 +39,10 @@ #include "pipespawn.h" #include "amfeatures.h" #include "client_util.h" +#include "conffile.h" +#include "amandad.h" +#include "amxml.h" +#include "base64.h" #ifdef SAMBA_CLIENT #include "findpass.h" @@ -59,45 +62,59 @@ int need_runtar=0; int need_gnutar=0; int need_compress_path=0; int need_calcsize=0; -int program_is_wrapper=0; +int need_global_check=0; +int program_is_application_api=0; +static char *amandad_auth = NULL; static am_feature_t *our_features = NULL; static char *our_feature_string = NULL; static g_option_t *g_options = NULL; /* local functions */ -int main P((int argc, char **argv)); - -static void check_options P((char *program, char *calcprog, char *disk, char *amdevice, option_t *options)); -static void check_disk P((char *program, char *calcprog, char *disk, char *amdevice, int level, char *optstr)); -static void check_overall P((void)); -static void check_access P((char *filename, int mode)); -static void check_file P((char *filename, int mode)); -static void check_dir P((char *dirname, int mode)); -static void check_suid P((char *filename)); -static void check_space P((char *dir, long kbytes)); - -int main(argc, argv) -int argc; -char **argv; +int main(int argc, char **argv); + +static void check_options(dle_t *dle); +static void check_disk(dle_t *dle); +static void check_overall(void); +static int check_file_exist(char *filename); +static void check_space(char *dir, off_t kbytes); +static void print_platform(void); + +int +main( + int argc, + char ** argv) { - int level; char *line = NULL; - char *program = NULL; - char *calcprog = NULL; - char *disk = NULL; - char *amdevice = NULL; + char *qdisk = NULL; + char *qamdevice = NULL; char *optstr = NULL; char *err_extra = NULL; char *s, *fp; int ch; - unsigned long malloc_hist_1, malloc_size_1; - unsigned long malloc_hist_2, malloc_size_2; - option_t *options; + dle_t *dle; + int level; + GSList *errlist; + level_t *alevel; + + if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) { + printf("selfcheck-%s\n", VERSION); + return (0); + } /* initialize */ + /* + * 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); + openbsd_fd_inform(); safe_cd(); set_pname("selfcheck"); @@ -105,22 +122,35 @@ char **argv; /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); - malloc_size_1 = malloc_inuse(&malloc_hist_1); - - erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG); - dbopen(); + add_amanda_log_handler(amanda_log_stderr); + add_amanda_log_handler(amanda_log_syslog); + dbopen(DBG_SUBDIR_CLIENT); startclock(); - dbprintf(("%s: version %s\n", get_pname(), version())); + dbprintf(_("version %s\n"), VERSION); + g_printf("OK version %s\n", VERSION); + print_platform(); + + if(argc > 2 && strcmp(argv[1], "amandad") == 0) { + amandad_auth = stralloc(argv[2]); + } + + config_init(CONFIG_INIT_CLIENT, NULL); + /* (check for config errors comes later) */ + + check_running_as(RUNNING_AS_CLIENT_LOGIN); our_features = am_init_feature_set(); our_feature_string = am_feature_to_string(our_features); /* handle all service requests */ + /*@ignore@*/ for(; (line = agets(stdin)) != NULL; free(line)) { -#define sc "OPTIONS " - if(strncmp(line, sc, sizeof(sc)-1) == 0) { -#undef sc + /*@end@*/ + if (line[0] == '\0') + continue; + + if(strncmp_const(line, "OPTIONS ") == 0) { g_options = parse_g_options(line+8, 1); if(!g_options->hostname) { g_options->hostname = alloc(MAX_HOSTNAME_LENGTH+1); @@ -128,18 +158,39 @@ char **argv; g_options->hostname[MAX_HOSTNAME_LENGTH] = '\0'; } - printf("OPTIONS "); + g_printf("OPTIONS "); if(am_has_feature(g_options->features, fe_rep_options_features)) { - printf("features=%s;", our_feature_string); + g_printf("features=%s;", our_feature_string); } if(am_has_feature(g_options->features, fe_rep_options_hostname)) { - printf("hostname=%s;", g_options->hostname); + g_printf("hostname=%s;", g_options->hostname); } - printf("\n"); + g_printf("\n"); fflush(stdout); + + if (g_options->config) { + /* overlay this configuration on the existing (nameless) configuration */ + config_init(CONFIG_INIT_CLIENT | CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_OVERLAY, + g_options->config); + + dbrename(get_config_name(), DBG_SUBDIR_CLIENT); + } + + /* check for any config errors now */ + if (config_errors(&errlist) >= CFGERR_ERRORS) { + char *errstr = config_errors_to_error_string(errlist); + g_printf("%s\n", errstr); + dbclose(); + return 1; + } + + if (am_has_feature(g_options->features, fe_req_xml)) { + break; + } continue; } + dle = alloc_dle(); s = line; ch = *s++; @@ -147,42 +198,46 @@ char **argv; if (ch == '\0') { goto err; /* no program */ } - program = s - 1; + dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; /* terminate the program name */ - program_is_wrapper = 0; - if(strcmp(program,"DUMPER")==0) { - program_is_wrapper = 1; + dle->program_is_application_api = 0; + if(strcmp(dle->program,"APPLICATION")==0) { + dle->program_is_application_api = 1; skip_whitespace(s, ch); /* find dumper name */ if (ch == '\0') { goto err; /* no program */ } - program = s - 1; + dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; /* terminate the program name */ } - if(strncmp(program, "CALCSIZE", 8) == 0) { + if(strncmp_const(dle->program, "CALCSIZE") == 0) { skip_whitespace(s, ch); /* find program name */ if (ch == '\0') { goto err; /* no program */ } - calcprog = s - 1; + dle->program = s - 1; skip_non_whitespace(s, ch); s[-1] = '\0'; + dle->estimatelist = g_slist_append(dle->estimatelist, + GINT_TO_POINTER(ES_CALCSIZE)); } else { - calcprog = NULL; + dle->estimatelist = g_slist_append(dle->estimatelist, + GINT_TO_POINTER(ES_CLIENT)); } skip_whitespace(s, ch); /* find disk name */ if (ch == '\0') { goto err; /* no disk */ } - disk = s - 1; - skip_non_whitespace(s, ch); + qdisk = s - 1; + skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the disk name */ + dle->disk = unquote_string(qdisk); skip_whitespace(s, ch); /* find the device or level */ if (ch == '\0') { @@ -190,44 +245,42 @@ char **argv; } if(!isdigit((int)s[-1])) { fp = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the device */ - amdevice = stralloc(fp); + qamdevice = stralloc(fp); + dle->device = unquote_string(qamdevice); skip_whitespace(s, ch); /* find level number */ } else { - amdevice = stralloc(disk); + dle->device = stralloc(dle->disk); + qamdevice = stralloc(qdisk); } /* find level number */ if (ch == '\0' || sscanf(s - 1, "%d", &level) != 1) { goto err; /* bad level */ } + alevel = g_new0(level_t, 1); + alevel->level = level; + dle->levellist = g_slist_append(dle->levellist, alevel); skip_integer(s, ch); skip_whitespace(s, ch); -#define sc "OPTIONS " - if (ch && strncmp (s - 1, sc, sizeof(sc)-1) == 0) { - s += sizeof(sc)-1; - ch = s[-1]; -#undef sc + if (ch && strncmp_const_skip(s - 1, "OPTIONS ", s, ch) == 0) { skip_whitespace(s, ch); /* find the option string */ if(ch == '\0') { goto err; /* bad options string */ } optstr = s - 1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; /* terminate the options */ - options = parse_options(optstr, disk, amdevice, g_options->features, 1); - check_options(program, calcprog, disk, amdevice, options); - check_disk(program, calcprog, disk, amdevice, level, &optstr[2]); - free_sl(options->exclude_file); - free_sl(options->exclude_list); - free_sl(options->include_file); - free_sl(options->include_list); - amfree(options->auth); - amfree(options->str); - amfree(options); + parse_options(optstr, dle, g_options->features, 1); + /*@ignore@*/ + + check_options(dle); + check_disk(dle); + + /*@end@*/ } else if (ch == '\0') { /* check all since no option */ need_samba=1; @@ -244,109 +297,119 @@ char **argv; need_gnutar=1; need_compress_path=1; need_calcsize=1; - check_disk(program, calcprog, disk, amdevice, level, ""); + need_global_check=1; + /*@ignore@*/ + check_disk(dle); + /*@end@*/ } else { goto err; /* bad syntax */ } - amfree(amdevice); + amfree(qamdevice); + } + if (g_options == NULL) { + g_printf(_("ERROR [Missing OPTIONS line in selfcheck input]\n")); + error(_("Missing OPTIONS line in selfcheck input\n")); + /*NOTREACHED*/ + } + + if (am_has_feature(g_options->features, fe_req_xml)) { + char *errmsg = NULL; + dle_t *dles, *dle, *dle_next; + + dles = amxml_parse_node_FILE(stdin, &errmsg); + if (errmsg) { + err_extra = errmsg; + goto err; + } + if (merge_dles_properties(dles, 1) == 0) { + goto checkoverall; + } + for (dle = dles; dle != NULL; dle = dle->next) { + run_client_scripts(EXECUTE_ON_PRE_HOST_AMCHECK, g_options, dle, + stdout); + } + for (dle = dles; dle != NULL; dle = dle->next) { + check_options(dle); + run_client_scripts(EXECUTE_ON_PRE_DLE_AMCHECK, g_options, dle, + stdout); + check_disk(dle); + run_client_scripts(EXECUTE_ON_POST_DLE_AMCHECK, g_options, dle, + stdout); + } + for (dle = dles; dle != NULL; dle = dle->next) { + run_client_scripts(EXECUTE_ON_POST_HOST_AMCHECK, g_options, dle, + stdout); + } + for (dle = dles; dle != NULL; dle = dle_next) { + dle_next = dle->next; + free_dle(dle); + } } +checkoverall: check_overall(); amfree(line); amfree(our_feature_string); am_release_feature_set(our_features); our_features = NULL; - am_release_feature_set(g_options->features); - g_options->features = NULL; - amfree(g_options->str); - amfree(g_options->hostname); - amfree(g_options); - - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { -#if defined(USE_DBMALLOC) - extern int dbfd; - - malloc_list(dbfd(), malloc_hist_1, malloc_hist_2); -#endif - } + free_g_options(g_options); dbclose(); return 0; err: - printf("ERROR [BOGUS REQUEST PACKET]\n"); - dbprintf(("%s: REQ packet is bogus%s%s\n", - debug_prefix_time(NULL), - err_extra ? ": " : "", - err_extra ? err_extra : "")); + if (err_extra) { + g_printf(_("ERROR [FORMAT ERROR IN REQUEST PACKET %s]\n"), err_extra); + dbprintf(_("REQ packet is bogus: %s\n"), err_extra); + } else { + g_printf(_("ERROR [FORMAT ERROR IN REQUEST PACKET]\n")); + dbprintf(_("REQ packet is bogus\n")); + } dbclose(); return 1; } static void -check_options(program, calcprog, disk, amdevice, options) - char *program, *calcprog, *disk, *amdevice; - option_t *options; +check_options( + dle_t *dle) { - char *myprogram = program; - - if(strcmp(myprogram,"CALCSIZE") == 0) { - int nb_exclude = 0; - int nb_include = 0; - char *file_exclude = NULL; - char *file_include = NULL; - - if(options->exclude_file) nb_exclude += options->exclude_file->nb_element; - if(options->exclude_list) nb_exclude += options->exclude_list->nb_element; - if(options->include_file) nb_include += options->include_file->nb_element; - if(options->include_list) nb_include += options->include_list->nb_element; - - if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 1); - if(nb_include > 0) file_include = build_include(disk, amdevice, options, 1); - - amfree(file_exclude); - amfree(file_include); - + if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE) { need_calcsize=1; - myprogram = calcprog; } - if(strcmp(myprogram,"GNUTAR") == 0) { + if (strcmp(dle->program,"GNUTAR") == 0) { need_gnutar=1; - if(amdevice[0] == '/' && amdevice[1] == '/') { - if(options->exclude_file && options->exclude_file->nb_element > 1) { - printf("ERROR [samba support only one exclude file]\n"); + if(dle->device && dle->device[0] == '/' && dle->device[1] == '/') { + if(dle->exclude_file && dle->exclude_file->nb_element > 1) { + g_printf(_("ERROR [samba support only one exclude file]\n")); } - if(options->exclude_list && options->exclude_list->nb_element > 0 && - options->exclude_optional==0) { - printf("ERROR [samba does not support exclude list]\n"); + if (dle->exclude_list && dle->exclude_list->nb_element > 0 && + dle->exclude_optional==0) { + g_printf(_("ERROR [samba does not support exclude list]\n")); } - if(options->include_file && options->include_file->nb_element > 0) { - printf("ERROR [samba does not support include file]\n"); + if (dle->include_file && dle->include_file->nb_element > 0) { + g_printf(_("ERROR [samba does not support include file]\n")); } - if(options->include_list && options->include_list->nb_element > 0 && - options->include_optional==0) { - printf("ERROR [samba does not support include list]\n"); + if (dle->include_list && dle->include_list->nb_element > 0 && + dle->include_optional==0) { + g_printf(_("ERROR [samba does not support include list]\n")); } need_samba=1; - } - else { + } else { int nb_exclude = 0; int nb_include = 0; char *file_exclude = NULL; char *file_include = NULL; - if(options->exclude_file) nb_exclude += options->exclude_file->nb_element; - if(options->exclude_list) nb_exclude += options->exclude_list->nb_element; - if(options->include_file) nb_include += options->include_file->nb_element; - if(options->include_list) nb_include += options->include_list->nb_element; + if (dle->exclude_file) nb_exclude += dle->exclude_file->nb_element; + if (dle->exclude_list) nb_exclude += dle->exclude_list->nb_element; + if (dle->include_file) nb_include += dle->include_file->nb_element; + if (dle->include_list) nb_include += dle->include_list->nb_element; - if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 1); - if(nb_include > 0) file_include = build_include(disk, amdevice, options, 1); + if (nb_exclude > 0) file_exclude = build_exclude(dle, 1); + if (nb_include > 0) file_include = build_include(dle, 1); amfree(file_exclude); amfree(file_include); @@ -355,18 +418,18 @@ check_options(program, calcprog, disk, amdevice, options) } } - if(strcmp(myprogram,"DUMP") == 0) { - if(options->exclude_file && options->exclude_file->nb_element > 0) { - printf("ERROR [DUMP does not support exclude file]\n"); + if (strcmp(dle->program,"DUMP") == 0) { + if (dle->exclude_file && dle->exclude_file->nb_element > 0) { + g_printf(_("ERROR [DUMP does not support exclude file]\n")); } - if(options->exclude_list && options->exclude_list->nb_element > 0) { - printf("ERROR [DUMP does not support exclude list]\n"); + if (dle->exclude_list && dle->exclude_list->nb_element > 0) { + g_printf(_("ERROR [DUMP does not support exclude list]\n")); } - if(options->include_file && options->include_file->nb_element > 0) { - printf("ERROR [DUMP does not support include file]\n"); + if (dle->include_file && dle->include_file->nb_element > 0) { + g_printf(_("ERROR [DUMP does not support include file]\n")); } - if(options->include_list && options->include_list->nb_element > 0) { - printf("ERROR [DUMP does not support include list]\n"); + if (dle->include_list && dle->include_list->nb_element > 0) { + g_printf(_("ERROR [DUMP does not support include list]\n")); } #ifdef USE_RUNDUMP need_rundump=1; @@ -374,352 +437,563 @@ check_options(program, calcprog, disk, amdevice, options) #ifndef AIX_BACKUP #ifdef VDUMP #ifdef DUMP - if (strcmp(amname_to_fstype(amdevice), "advfs") == 0) + if (dle->device && strcmp(amname_to_fstype(dle->device), "advfs") == 0) #else if (1) #endif { need_vdump=1; need_rundump=1; - if (options->createindex) + if (dle->create_index) need_vrestore=1; } else #endif /* VDUMP */ #ifdef XFSDUMP #ifdef DUMP - if (strcmp(amname_to_fstype(amdevice), "xfs") == 0) + if (dle->device && strcmp(amname_to_fstype(dle->device), "xfs") == 0) #else if (1) #endif { need_xfsdump=1; need_rundump=1; - if (options->createindex) + if (dle->create_index) need_xfsrestore=1; } else #endif /* XFSDUMP */ #ifdef VXDUMP #ifdef DUMP - if (strcmp(amname_to_fstype(amdevice), "vxfs") == 0) + if (dle->device && strcmp(amname_to_fstype(dle->device), "vxfs") == 0) #else if (1) #endif { need_vxdump=1; - if (options->createindex) + if (dle->create_index) need_vxrestore=1; } else #endif /* VXDUMP */ { need_dump=1; - if (options->createindex) + if (dle->create_index) need_restore=1; } #else /* AIX backup program */ need_dump=1; - if (options->createindex) + if (dle->create_index) need_restore=1; #endif } - if(program_is_wrapper==1) { - } - if(options->compress == COMPR_BEST || options->compress == COMPR_FAST || options->compress == COMPR_CUST) + if ((dle->compress == COMP_BEST) || (dle->compress == COMP_FAST) + || (dle->compress == COMP_CUST)) { need_compress_path=1; + } + if (dle->auth && amandad_auth) { + if (strcasecmp(dle->auth, amandad_auth) != 0) { + g_fprintf(stdout,_("ERROR [client configured for auth=%s while server requested '%s']\n"), + amandad_auth, dle->auth); + if (strcmp(dle->auth, "ssh") == 0) { + g_fprintf(stderr, _("ERROR [The auth in ~/.ssh/authorized_keys " + "should be \"--auth=ssh\", or use another auth " + " for the DLE]\n")); + } + else { + g_fprintf(stderr, _("ERROR [The auth in the inetd/xinetd configuration " + " must be the same as the DLE]\n")); + } + } + } } -static void check_disk(program, calcprog, disk, amdevice, level, optstr) -char *program, *calcprog, *disk, *amdevice; -int level; -char *optstr; +static void +check_disk( + dle_t *dle) { char *device = NULL; char *err = NULL; - char *user_and_password = NULL, *domain = NULL; + char *user_and_password = NULL; + char *domain = NULL; char *share = NULL, *subdir = NULL; - int lpass = 0; - int amode; + size_t lpass = 0; + int amode = R_OK; int access_result; char *access_type; char *extra_info = NULL; - char *myprogram = program; - - if(strcmp(myprogram,"CALCSIZE") == 0) { - if(amdevice[0] == '/' && amdevice[1] == '/') { - err = vstralloc("Can't use CALCSIZE for samba estimate,", - " use CLIENT: ", - amdevice, - NULL); - goto common_exit; - } - myprogram = calcprog; - } - - dbprintf(("%s: checking disk %s\n", debug_prefix_time(NULL), disk)); - - if (strcmp(myprogram, "GNUTAR") == 0) { - if(amdevice[0] == '/' && amdevice[1] == '/') { -#ifdef SAMBA_CLIENT - int nullfd, checkerr; - int passwdfd; - char *pwtext; - int pwtext_len; - int checkpid; - amwait_t retstat; - char number[NUM_STR_SIZE]; - int wpid; - int ret, sig, rc; - char *line; - char *sep; - FILE *ferr; - char *pw_fd_env; - int errdos; - - parsesharename(amdevice, &share, &subdir); - if (!share) { - err = stralloc2("cannot parse for share/subdir disk entry ", amdevice); - goto common_exit; - } - if ((subdir) && (SAMBA_VERSION < 2)) { - err = vstralloc("subdirectory specified for share '", - amdevice, - "' but samba not v2 or better", - NULL); - goto common_exit; - } - if ((user_and_password = findpass(share, &domain)) == NULL) { - err = stralloc2("cannot find password for ", amdevice); - goto common_exit; - } - lpass = strlen(user_and_password); - if ((pwtext = strchr(user_and_password, '%')) == NULL) { - err = stralloc2("password field not \'user%pass\' for ", amdevice); - goto common_exit; - } - *pwtext++ = '\0'; - pwtext_len = strlen(pwtext); - if ((device = makesharename(share, 0)) == NULL) { - err = stralloc2("cannot make share name of ", share); + char *qdisk = NULL; + char *qamdevice = NULL; + char *qdevice = NULL; + + if (dle->disk) { + need_global_check=1; + qdisk = quote_string(dle->disk); + qamdevice = quote_string(dle->device); + device = stralloc("nodevice"); + dbprintf(_("checking disk %s\n"), qdisk); + if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE) { + if (dle->device[0] == '/' && dle->device[1] == '/') { + err = vstrallocf( + _("Can't use CALCSIZE for samba estimate, use CLIENT: %s"), + dle->device); goto common_exit; } + } - if ((nullfd = open("/dev/null", O_RDWR)) == -1) { - err = stralloc2("Cannot access /dev/null : ", strerror(errno)); - goto common_exit; - } + if (strcmp(dle->program, "GNUTAR")==0) { + if(dle->device[0] == '/' && dle->device[1] == '/') { + #ifdef SAMBA_CLIENT + int nullfd, checkerr; + int passwdfd; + char *pwtext; + size_t pwtext_len; + pid_t checkpid; + amwait_t retstat; + pid_t wpid; + int rc; + char *line; + char *sep; + FILE *ferr; + char *pw_fd_env; + int errdos; + + parsesharename(dle->device, &share, &subdir); + if (!share) { + err = vstrallocf( + _("cannot parse for share/subdir disk entry %s"), + dle->device); + goto common_exit; + } + if ((subdir) && (SAMBA_VERSION < 2)) { + err = vstrallocf(_("subdirectory specified for share '%s' but, samba is not v2 or better"), + dle->device); + goto common_exit; + } + if ((user_and_password = findpass(share, &domain)) == NULL) { + err = vstrallocf(_("cannot find password for %s"), + dle->device); + goto common_exit; + } + lpass = strlen(user_and_password); + if ((pwtext = strchr(user_and_password, '%')) == NULL) { + err = vstrallocf( + _("password field not \'user%%pass\' for %s"), + dle->device); + goto common_exit; + } + *pwtext++ = '\0'; + pwtext_len = (size_t)strlen(pwtext); + amfree(device); + if ((device = makesharename(share, 0)) == NULL) { + err = vstrallocf(_("cannot make share name of %s"), share); + goto common_exit; + } - if (pwtext_len > 0) { - pw_fd_env = "PASSWD_FD"; - } else { - pw_fd_env = "dummy_PASSWD_FD"; - } - checkpid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE, - &nullfd, &nullfd, &checkerr, - pw_fd_env, &passwdfd, - "smbclient", - device, - *user_and_password ? "-U" : skip_argument, - *user_and_password ? user_and_password : skip_argument, - "-E", - domain ? "-W" : skip_argument, - domain ? domain : skip_argument, + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + err = vstrallocf(_("Cannot access /dev/null : %s"), + strerror(errno)); + goto common_exit; + } + + if (pwtext_len > 0) { + pw_fd_env = "PASSWD_FD"; + } else { + pw_fd_env = "dummy_PASSWD_FD"; + } + checkpid = pipespawn(SAMBA_CLIENT, STDERR_PIPE|PASSWD_PIPE, 0, + &nullfd, &nullfd, &checkerr, + pw_fd_env, &passwdfd, + "smbclient", + device, + *user_and_password ? "-U" : skip_argument, + *user_and_password ? user_and_password + : skip_argument, + "-E", + domain ? "-W" : skip_argument, + domain ? domain : skip_argument, #if SAMBA_VERSION >= 2 - subdir ? "-D" : skip_argument, - subdir ? subdir : skip_argument, + subdir ? "-D" : skip_argument, + subdir ? subdir : skip_argument, #endif - "-c", "quit", - NULL); - if (domain) { - memset(domain, '\0', strlen(domain)); + "-c", "quit", + NULL); + checkpid = checkpid; amfree(domain); - } - aclose(nullfd); - if (pwtext_len > 0 && fullwrite(passwdfd, pwtext, pwtext_len) < 0) { - err = vstralloc("password write failed: ", - amdevice, - ": ", - strerror(errno), - NULL); + aclose(nullfd); + /*@ignore@*/ + if ((pwtext_len > 0) && + full_write(passwdfd, pwtext, pwtext_len) < pwtext_len) { + err = vstrallocf(_("password write failed: %s: %s"), + dle->device, strerror(errno)); + aclose(passwdfd); + goto common_exit; + } + /*@end@*/ + memset(user_and_password, '\0', (size_t)lpass); + amfree(user_and_password); aclose(passwdfd); - goto common_exit; - } - memset(user_and_password, '\0', lpass); - amfree(user_and_password); - aclose(passwdfd); - ferr = fdopen(checkerr, "r"); - sep = ""; - errdos = 0; - for(sep = ""; (line = agets(ferr)) != NULL; free(line)) { - strappend(extra_info, sep); - strappend(extra_info, line); - sep = ": "; - if(strstr(line, "ERRDOS") != NULL) { - errdos = 1; + ferr = fdopen(checkerr, "r"); + if (!ferr) { + g_printf(_("ERROR [Can't fdopen: %s]\n"), strerror(errno)); + error(_("Can't fdopen: %s"), strerror(errno)); + /*NOTREACHED*/ } - } - afclose(ferr); - checkerr = -1; - rc = 0; - while ((wpid = wait(&retstat)) != -1) { - if (WIFSIGNALED(retstat)) { - ret = 0; - rc = sig = WTERMSIG(retstat); - } else { - sig = 0; - rc = ret = WEXITSTATUS(retstat); + sep = ""; + errdos = 0; + for(sep = ""; (line = agets(ferr)) != NULL; free(line)) { + if (line[0] == '\0') + continue; + strappend(extra_info, sep); + strappend(extra_info, line); + sep = ": "; + if(strstr(line, "ERRDOS") != NULL) { + errdos = 1; + } + } + afclose(ferr); + checkerr = -1; + rc = 0; + sep = ""; + while ((wpid = wait(&retstat)) != -1) { + if (!WIFEXITED(retstat) || WEXITSTATUS(retstat) != 0) { + char *exitstr = str_exit_status("smbclient", retstat); + strappend(err, sep); + strappend(err, exitstr); + sep = "\n"; + amfree(exitstr); + + rc = 1; + } } - if (rc != 0) { - strappend(err, sep); - if (ret == 0) { - strappend(err, "got signal "); - ret = sig; + if (errdos != 0 || rc != 0) { + if (extra_info) { + err = newvstrallocf(err, + _("samba access error: %s: %s %s"), + dle->device, extra_info, err); + amfree(extra_info); } else { - strappend(err, "returned "); + err = newvstrallocf(err, + _("samba access error: %s: %s"), + dle->device, err); } - snprintf(number, sizeof(number), "%d", ret); - strappend(err, number); } - } - if (errdos != 0 || rc != 0) { - err = newvstralloc(err, - "samba access error: ", - amdevice, - ": ", - extra_info ? extra_info : "", - err, - NULL); - amfree(extra_info); - } #else - err = stralloc2("This client is not configured for samba: ", disk); + err = vstrallocf( + _("This client is not configured for samba: %s"), + qdisk); #endif - goto common_exit; - } - amode = F_OK; - device = amname_to_dirname(amdevice); - } else if (strcmp(program, "DUMP") == 0) { - if(amdevice[0] == '/' && amdevice[1] == '/') { - err = vstralloc("The DUMP program cannot handle samba shares,", - " use GNUTAR: ", - disk, - NULL); - goto common_exit; - } + goto common_exit; + } + amode = F_OK; + amfree(device); + device = amname_to_dirname(dle->device); + } else if (strcmp(dle->program, "DUMP") == 0) { + if(dle->device[0] == '/' && dle->device[1] == '/') { + err = vstrallocf( + _("The DUMP program cannot handle samba shares, use GNUTAR: %s"), + qdisk); + goto common_exit; + } #ifdef VDUMP /* { */ #ifdef DUMP /* { */ - if (strcmp(amname_to_fstype(amdevice), "advfs") == 0) -#else /* }{ */ - if (1) + if (strcmp(amname_to_fstype(dle->device), "advfs") == 0) +#else /* }{*/ + if (1) #endif /* } */ - { - device = amname_to_dirname(amdevice); - amode = F_OK; - } else + { + amfree(device); + device = amname_to_dirname(dle->device); + amode = F_OK; + } else #endif /* } */ - { - device = amname_to_devname(amdevice); + { + amfree(device); + device = amname_to_devname(dle->device); #ifdef USE_RUNDUMP - amode = F_OK; + amode = F_OK; #else - amode = R_OK; + amode = R_OK; #endif + } } } - else { /* program_is_wrapper==1 */ - int pid_wrapper; - fflush(stdout);fflush(stdin); - switch (pid_wrapper = fork()) { - case -1: error("fork: %s", strerror(errno)); + if (dle->program_is_application_api) { + pid_t application_api_pid; + backup_support_option_t *bsu; + int app_err[2]; + GPtrArray *errarray; + + bsu = backup_support_option(dle->program, g_options, dle->disk, + dle->device, &errarray); + + if (!bsu) { + char *line; + guint i; + for (i=0; i < errarray->len; i++) { + line = g_ptr_array_index(errarray, i); + fprintf(stdout, _("ERROR Application '%s': %s\n"), + dle->program, line); + amfree(line); + } + err = vstrallocf(_("Application '%s': can't run support command"), + dle->program); + goto common_exit; + } + + if (dle->data_path == DATA_PATH_AMANDA && + (bsu->data_path_set & DATA_PATH_AMANDA)==0) { + g_printf("ERROR application %s doesn't support amanda data-path\n", + dle->program); + } + if (dle->data_path == DATA_PATH_DIRECTTCP && + (bsu->data_path_set & DATA_PATH_DIRECTTCP)==0) { + g_printf("ERROR application %s doesn't support directtcp data-path\n", + dle->program); + } + if (GPOINTER_TO_INT(dle->estimatelist->data) == ES_CALCSIZE && + !bsu->calcsize) { + g_printf("ERROR application %s doesn't support calcsize estimate\n", + dle->program); + } + if (dle->include_file && dle->include_file->nb_element > 0 && + !bsu->include_file) { + g_printf("ERROR application %s doesn't support include-file\n", + dle->program); + } + if (dle->include_list && dle->include_list->nb_element > 0 && + !bsu->include_list) { + g_printf("ERROR application %s doesn't support include-list\n", + dle->program); + } + if (dle->include_optional && !bsu->include_optional) { + g_printf("ERROR application %s doesn't support optional include\n", + dle->program); + } + if (dle->exclude_file && dle->exclude_file->nb_element > 0 && + !bsu->exclude_file) { + g_printf("ERROR application %s doesn't support exclude-file\n", + dle->program); + } + if (dle->exclude_list && dle->exclude_list->nb_element > 0 && + !bsu->exclude_list) { + g_printf("ERROR application %s doesn't support exclude-list\n", + dle->program); + } + if (dle->exclude_optional && !bsu->exclude_optional) { + g_printf("ERROR application %s doesn't support optional exclude\n", + dle->program); + } + fflush(stdout);fflush(stderr); + + if (pipe(app_err) < 0) { + err = vstrallocf(_("Application '%s': can't create pipe"), + dle->program); + goto common_exit; + } + + switch (application_api_pid = fork()) { + case -1: + err = vstrallocf(_("fork failed: %s"), strerror(errno)); + goto common_exit; + case 0: /* child */ { - char *argvchild[6]; - char *cmd = vstralloc(DUMPER_DIR, "/", program, NULL); - argvchild[0] = program; - argvchild[1] = "selfcheck"; - argvchild[2] = disk; - argvchild[3] = amdevice; - argvchild[4] = optstr; - argvchild[5] = NULL; - execve(cmd,argvchild,safe_env()); + GPtrArray *argv_ptr = g_ptr_array_new(); + guint i; + char *cmd = vstralloc(APPLICATION_DIR, "/", dle->program, NULL); + GSList *scriptlist; + script_t *script; + estimatelist_t el; + char *cmdline; + + aclose(app_err[0]); + dup2(app_err[1], 2); + + g_ptr_array_add(argv_ptr, stralloc(dle->program)); + g_ptr_array_add(argv_ptr, stralloc("selfcheck")); + if (bsu->message_line == 1) { + g_ptr_array_add(argv_ptr, stralloc("--message")); + g_ptr_array_add(argv_ptr, stralloc("line")); + } + if (g_options->config != NULL && bsu->config == 1) { + g_ptr_array_add(argv_ptr, stralloc("--config")); + g_ptr_array_add(argv_ptr, stralloc(g_options->config)); + } + if (g_options->hostname != NULL && bsu->host == 1) { + g_ptr_array_add(argv_ptr, stralloc("--host")); + g_ptr_array_add(argv_ptr, stralloc(g_options->hostname)); + } + if (dle->disk != NULL && bsu->disk == 1) { + g_ptr_array_add(argv_ptr, stralloc("--disk")); + g_ptr_array_add(argv_ptr, stralloc(dle->disk)); + } + if (dle->device) { + g_ptr_array_add(argv_ptr, stralloc("--device")); + g_ptr_array_add(argv_ptr, stralloc(dle->device)); + } + if (dle->create_index && bsu->index_line == 1) { + g_ptr_array_add(argv_ptr, stralloc("--index")); + g_ptr_array_add(argv_ptr, stralloc("line")); + } + if (dle->record && bsu->record == 1) { + g_ptr_array_add(argv_ptr, stralloc("--record")); + } + + for (el = dle->estimatelist; el != NULL; el=el->next) { + estimate_t estimate = (estimate_t)GPOINTER_TO_INT(el->data); + if (estimate == ES_CALCSIZE && bsu->calcsize == 1) { + g_ptr_array_add(argv_ptr, stralloc("--calcsize")); + } + } + application_property_add_to_argv(argv_ptr, dle, bsu, + g_options->features); + + for (scriptlist = dle->scriptlist; scriptlist != NULL; + scriptlist = scriptlist->next) { + script = (script_t *)scriptlist->data; + if (script->result && script->result->proplist) { + property_add_to_argv(argv_ptr, + script->result->proplist); + } + } + + g_ptr_array_add(argv_ptr, NULL); + + cmdline = stralloc(cmd); + for (i = 0; i < argv_ptr->len-1; i++) { + char *quoted = quote_string( + (char *)g_ptr_array_index(argv_ptr,i)); + cmdline = vstrextend(&cmdline, " ", quoted, NULL); + amfree(quoted); + } + dbprintf(_("Spawning \"%s\" in pipeline\n"), cmdline); + amfree(cmdline); + + safe_fd(-1, 0); + execve(cmd, (char **)argv_ptr->pdata, safe_env()); + g_printf(_("ERROR [Can't execute %s: %s]\n"), cmd, strerror(errno)); exit(127); } default: /* parent */ { - int status; - waitpid(pid_wrapper, &status, 0); + int status; + FILE *app_stderr; + char *line; + + aclose(app_err[1]); + app_stderr = fdopen(app_err[0], "r"); + while((line = agets(app_stderr)) != NULL) { + if (strlen(line) > 0) { + fprintf(stdout, "ERROR Application '%s': %s\n", + dle->program, line); + dbprintf("ERROR %s\n", line); + } + amfree(line); + } + fclose(app_stderr); + if (waitpid(application_api_pid, &status, 0) < 0) { + err = vstrallocf(_("waitpid failed: %s"), + strerror(errno)); + goto common_exit; + } else if (!WIFEXITED(status)) { + err = vstrallocf(_("Application '%s': exited with signal %d"), + dle->program, WTERMSIG(status)); + goto common_exit; + } else if (WEXITSTATUS(status) != 0) { + err = vstrallocf(_("Application '%s': exited with status %d"), + dle->program, WEXITSTATUS(status)); + goto common_exit; + } } } - fflush(stdout);fflush(stdin); + amfree(bsu); + fflush(stdout);fflush(stderr); + amfree(device); + amfree(qamdevice); + amfree(qdisk); return; } - dbprintf(("%s: device %s\n", debug_prefix_time(NULL), device)); + if (device) { + qdevice = quote_string(device); + dbprintf(_("device %s\n"), qdevice); - /* skip accessability test if this is an AFS entry */ - if(strncmp(device, "afs:", 4) != 0) { + /* skip accessability test if this is an AFS entry */ + if(strncmp_const(device, "afs:") != 0) { #ifdef CHECK_FOR_ACCESS_WITH_OPEN - access_result = open(device, O_RDONLY); - access_type = "open"; + access_result = open(device, O_RDONLY); + access_type = "open"; #else - access_result = access(device, amode); - access_type = "access"; + access_result = access(device, amode); + access_type = "access"; #endif - if(access_result == -1) { - err = vstralloc("could not ", access_type, " ", device, - " (", disk, "): ", strerror(errno), NULL); - } + if(access_result == -1) { + err = vstrallocf(_("Could not %s %s (%s): %s"), + access_type, qdevice, qdisk, strerror(errno)); + } #ifdef CHECK_FOR_ACCESS_WITH_OPEN - aclose(access_result); + aclose(access_result); #endif + } } common_exit: + if (!qdevice) + qdevice = quote_string(device); + amfree(share); amfree(subdir); if(user_and_password) { - memset(user_and_password, '\0', lpass); + memset(user_and_password, '\0', (size_t)lpass); amfree(user_and_password); } - if(domain) { - memset(domain, '\0', strlen(domain)); - amfree(domain); - } + amfree(domain); if(err) { - printf("ERROR [%s]\n", err); - dbprintf(("%s: %s\n", debug_prefix_time(NULL), err)); + g_printf(_("ERROR %s\n"), err); + dbprintf(_("%s\n"), err); amfree(err); } else { - printf("OK %s\n", disk); - dbprintf(("%s: disk \"%s\" OK\n", debug_prefix_time(NULL), disk)); - printf("OK %s\n", amdevice); - dbprintf(("%s: amdevice \"%s\" OK\n", - debug_prefix_time(NULL), amdevice)); - printf("OK %s\n", device); - dbprintf(("%s: device \"%s\" OK\n", debug_prefix_time(NULL), device)); + if (dle->disk) { + g_printf("OK %s\n", qdisk); + dbprintf(_("disk %s OK\n"), qdisk); + } + if (dle->device) { + g_printf("OK %s\n", qamdevice); + dbprintf(_("amdevice %s OK\n"), qamdevice); + } + if (device) { + g_printf("OK %s\n", qdevice); + dbprintf(_("device %s OK\n"), qdevice); + } } if(extra_info) { - dbprintf(("%s: extra info: %s\n", debug_prefix_time(NULL), extra_info)); + dbprintf(_("extra info: %s\n"), extra_info); amfree(extra_info); } + amfree(qdisk); + amfree(qdevice); + amfree(qamdevice); amfree(device); /* XXX perhaps do something with level: read dumpdates and sanity check */ } -static void check_overall() +static void +check_overall(void) { char *cmd; struct stat buf; int testfd; + char *gnutar_list_dir; + int need_amandates = 0; if( need_runtar ) { - cmd = vstralloc(libexecdir, "/", "runtar", versionsuffix(), NULL); + cmd = vstralloc(amlibexecdir, "/", "runtar", NULL); check_file(cmd,X_OK); check_suid(cmd); amfree(cmd); @@ -727,7 +1001,7 @@ static void check_overall() if( need_rundump ) { - cmd = vstralloc(libexecdir, "/", "rundump", versionsuffix(), NULL); + cmd = vstralloc(amlibexecdir, "/", "rundump", NULL); check_file(cmd,X_OK); check_suid(cmd); amfree(cmd); @@ -737,7 +1011,7 @@ static void check_overall() #ifdef DUMP check_file(DUMP, X_OK); #else - printf("ERROR [DUMP program not available]\n"); + g_printf(_("ERROR [DUMP program not available]\n")); #endif } @@ -745,7 +1019,7 @@ static void check_overall() #ifdef RESTORE check_file(RESTORE, X_OK); #else - printf("ERROR [RESTORE program not available]\n"); + g_printf(_("ERROR [RESTORE program not available]\n")); #endif } @@ -753,7 +1027,7 @@ static void check_overall() #ifdef VDUMP check_file(VDUMP, X_OK); #else - printf("ERROR [VDUMP program not available]\n"); + g_printf(_("ERROR [VDUMP program not available]\n")); #endif } @@ -761,7 +1035,7 @@ static void check_overall() #ifdef VRESTORE check_file(VRESTORE, X_OK); #else - printf("ERROR [VRESTORE program not available]\n"); + g_printf(_("ERROR [VRESTORE program not available]\n")); #endif } @@ -769,7 +1043,7 @@ static void check_overall() #ifdef XFSDUMP check_file(XFSDUMP, F_OK); #else - printf("ERROR [XFSDUMP program not available]\n"); + g_printf(_("ERROR [XFSDUMP program not available]\n")); #endif } @@ -777,7 +1051,7 @@ static void check_overall() #ifdef XFSRESTORE check_file(XFSRESTORE, X_OK); #else - printf("ERROR [XFSRESTORE program not available]\n"); + g_printf(_("ERROR [XFSRESTORE program not available]\n")); #endif } @@ -785,7 +1059,7 @@ static void check_overall() #ifdef VXDUMP check_file(VXDUMP, X_OK); #else - printf("ERROR [VXDUMP program not available]\n"); + g_printf(_("ERROR [VXDUMP program not available]\n")); #endif } @@ -793,7 +1067,7 @@ static void check_overall() #ifdef VXRESTORE check_file(VXRESTORE, X_OK); #else - printf("ERROR [VXRESTORE program not available]\n"); + g_printf(_("ERROR [VXRESTORE program not available]\n")); #endif } @@ -801,158 +1075,228 @@ static void check_overall() #ifdef GNUTAR check_file(GNUTAR, X_OK); #else - printf("ERROR [GNUTAR program not available]\n"); -#endif -#ifdef AMANDATES_FILE - check_file(AMANDATES_FILE, R_OK|W_OK); -#endif -#ifdef GNUTAR_LISTED_INCREMENTAL_DIR - check_dir(GNUTAR_LISTED_INCREMENTAL_DIR,R_OK|W_OK); + g_printf(_("ERROR [GNUTAR program not available]\n")); #endif + gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR); + if (strlen(gnutar_list_dir) == 0) + gnutar_list_dir = NULL; + if (gnutar_list_dir) { + /* make sure our listed-incremental dir is ready */ + check_dir(gnutar_list_dir, R_OK|W_OK); + } else { + /* no listed-incremental dir, so check that amandates is ready */ + need_amandates = 1; + } } if( need_calcsize ) { char *cmd; - cmd = vstralloc(libexecdir, "/", "calcsize", versionsuffix(), NULL); + cmd = vstralloc(amlibexecdir, "/", "calcsize", NULL); check_file(cmd, X_OK); amfree(cmd); + + /* calcsize uses amandates */ + need_amandates = 1; + } + + if (need_amandates) { + char *amandates_file; + amandates_file = getconf_str(CNF_AMANDATES); + check_file(amandates_file, R_OK|W_OK); } if( need_samba ) { #ifdef SAMBA_CLIENT check_file(SAMBA_CLIENT, X_OK); #else - printf("ERROR [SMBCLIENT program not available]\n"); + g_printf(_("ERROR [SMBCLIENT program not available]\n")); #endif testfd = open("/etc/amandapass", R_OK); if (testfd >= 0) { if(fstat(testfd, &buf) == 0) { if ((buf.st_mode & 0x7) != 0) { - printf("ERROR [/etc/amandapass is world readable!]\n"); + g_printf(_("ERROR [/etc/amandapass is world readable!]\n")); } else { - printf("OK [/etc/amandapass is readable, but not by all]\n"); + g_printf(_("OK [/etc/amandapass is readable, but not by all]\n")); } } else { - printf("OK [unable to stat /etc/amandapass: %s]\n", + g_printf(_("OK [unable to stat /etc/amandapass: %s]\n"), strerror(errno)); } aclose(testfd); } else { - printf("ERROR [unable to open /etc/amandapass: %s]\n", + g_printf(_("ERROR [unable to open /etc/amandapass: %s]\n"), strerror(errno)); } } - if( need_compress_path ) + if (need_compress_path ) check_file(COMPRESS_PATH, X_OK); - if( need_dump || need_xfsdump ) - check_file("/etc/dumpdates", + if (need_dump || need_xfsdump ) { + if (check_file_exist("/etc/dumpdates")) { + check_file("/etc/dumpdates", #ifdef USE_RUNDUMP - F_OK + F_OK #else - R_OK|W_OK + R_OK|W_OK +#endif + ); + } else { +#ifndef USE_RUNDUMP + if (access("/etc", R_OK|W_OK) == -1) { + g_printf(_("ERROR [dump will not be able to create the /etc/dumpdates file: %s]\n"), strerror(errno)); + } #endif - ); + } + } - if (need_vdump) - check_file("/etc/vdumpdates", F_OK); + if (need_vdump) { + if (check_file_exist("/etc/vdumpdates")) { + check_file("/etc/vdumpdates", F_OK); + } + } + if (need_global_check) { check_access("/dev/null", R_OK|W_OK); - check_space(AMANDA_TMPDIR, 64); /* for amandad i/o */ + check_space(AMANDA_TMPDIR, (off_t)64); /* for amandad i/o */ #ifdef AMANDA_DBGDIR - check_space(AMANDA_DBGDIR, 64); /* for amandad i/o */ + check_space(AMANDA_DBGDIR, (off_t)64); /* for amandad i/o */ #endif - check_space("/etc", 64); /* for /etc/dumpdates writing */ + check_space("/etc", (off_t)64); /* for /etc/dumpdates writing */ + } } -static void check_space(dir, kbytes) -char *dir; -long kbytes; +static void +check_space( + char * dir, + off_t kbytes) { - generic_fs_stats_t statp; - - if(get_fs_stats(dir, &statp) == -1) - printf("ERROR [cannot statfs %s: %s]\n", dir, strerror(errno)); - else if(statp.avail < kbytes) - printf("ERROR [dir %s needs %ldKB, only has %ldKB available.]\n", - dir, kbytes, statp.avail); - else - printf("OK %s has more than %ld KB available.\n", dir, kbytes); -} + struct fs_usage fsusage; + char *quoted = quote_string(dir); + intmax_t kb_avail; -static void check_access(filename, mode) -char *filename; -int mode; -{ - char *noun, *adjective; - - if(mode == F_OK) - noun = "find", adjective = "exists"; - else if((mode & X_OK) == X_OK) - noun = "execute", adjective = "executable"; - else if((mode & (W_OK|R_OK)) == (W_OK|R_OK)) - noun = "read/write", adjective = "read/writable"; - else - noun = "access", adjective = "accessible"; - - if(access(filename, mode) == -1) - printf("ERROR [can not %s %s: %s]\n", noun, filename, strerror(errno)); - else - printf("OK %s %s\n", filename, adjective); -} + if(get_fs_usage(dir, NULL, &fsusage) == -1) { + g_printf(_("ERROR [cannot get filesystem usage for %s: %s]\n"), quoted, strerror(errno)); + amfree(quoted); + return; + } -static void check_file(filename, mode) -char *filename; -int mode; -{ - struct stat stat_buf; - if(!stat(filename, &stat_buf)) { - if(!S_ISREG(stat_buf.st_mode)) { - printf("ERROR [%s is not a file]\n", filename); - } + /* do the division first to avoid potential integer overflow */ + kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize; + + if (fsusage.fsu_bavail_top_bit_set || fsusage.fsu_bavail == 0) { + g_printf(_("ERROR [dir %s needs %lldKB, has nothing available.]\n"), quoted, + (long long)kbytes); + } else if (kb_avail < kbytes) { + g_printf(_("ERROR [dir %s needs %lldKB, only has %lldKB available.]\n"), quoted, + (long long)kbytes, + (long long)kb_avail); + } else { + g_printf(_("OK %s has more than %lldKB available.\n"), + quoted, (long long)kbytes); } - check_access(filename, mode); + amfree(quoted); } -static void check_dir(dirname, mode) -char *dirname; -int mode; +static int +check_file_exist( + char *filename) { struct stat stat_buf; - char *dir; - if(!stat(dirname, &stat_buf)) { - if(!S_ISDIR(stat_buf.st_mode)) { - printf("ERROR [%s is not a directory]\n", dirname); + if (stat(filename, &stat_buf) != 0) { + if(errno == ENOENT) { + return 0; } } - dir = stralloc2(dirname, "/."); - check_access(dir, mode); - amfree(dir); + return 1; } -static void check_suid(filename) -char *filename; +static void +print_platform(void) { -/* The following is only valid for real Unixs */ -#ifndef IGNORE_UID_CHECK struct stat stat_buf; - if(!stat(filename, &stat_buf)) { - if(stat_buf.st_uid != 0 ) { - printf("ERROR [%s is not owned by root]\n",filename); + char *uname; + char *distro = NULL; + char *platform = NULL; + char line[1025]; + GPtrArray *argv_ptr; + + if (stat("/etc/lsb-release", &stat_buf) == 0) { + FILE *release = fopen("/etc/lsb-release", "r"); + distro = "Ubuntu"; + if (release) { + char *result; + while ((result = fgets(line, 1024, release))) { + if (strstr(line, "DESCRIPTION")) { + platform = strchr(line, '='); + if (platform) platform++; + } + } + fclose(release); } - if((stat_buf.st_mode & S_ISUID) != S_ISUID) { - printf("ERROR [%s is not SUID root]\n",filename); + } else if (stat("/etc/redhat-release", &stat_buf) == 0) { + FILE *release = fopen("/etc/redhat-release", "r"); + distro = "RPM"; + if (release) { + char *result; + result = fgets(line, 1024, release); + if (result) { + platform = line; + } + fclose(release); + } + } else if (stat("/etc/debian_version", &stat_buf) == 0) { + FILE *release = fopen("/etc/debian_version", "r"); + distro = "Debian"; + if (release) { + char *result; + result = fgets(line, 1024, release); + if (result) { + platform = line; + } + fclose(release); + } + } else { + argv_ptr = g_ptr_array_new(); + + g_ptr_array_add(argv_ptr, UNAME_PATH); + g_ptr_array_add(argv_ptr, "-s"); + g_ptr_array_add(argv_ptr, NULL); + uname = get_first_line(argv_ptr); + if (uname) { + if (strncmp(uname, "SunOS", 5) == 0) { + FILE *release = fopen("/etc/release", "r"); + distro = "Solaris"; + if (release) { + char *result; + result = fgets(line, 1024, release); + if (result) { + platform = line; + } + } + fclose(release); + } + amfree(uname); } + g_ptr_array_free(argv_ptr, TRUE); + } + + if (!distro) { + distro = "Unknown"; } - else { - printf("ERROR [can not stat %s]\n",filename); + if (!platform) { + platform = "Unknown"; } -#endif + if (platform[strlen(platform) -1] == '\n') { + platform[strlen(platform) -1] = '\0'; + } + g_fprintf(stdout, "OK distro %s\n", distro); + g_fprintf(stdout, "OK platform %s\n", platform); }