static int check_config(void) { int i; int total = 0; if (check_writable_spool(serve_state.global->compile_queue_dir, SPOOL_OUT) < 0) return -1; for (i = 1; i <= serve_state.max_lang; i++) { if (!serve_state.langs[i]) continue; /* script must exist and be executable */ total++; if (check_executable(serve_state.langs[i]->cmd) < 0) return -1; } if (!total) { err("no languages"); return -1; } return 0; }
static int check_config(void) { int i, n1 = 0, n2, j, k; int total = 0; struct section_problem_data *prb = 0; struct section_tester_data *tst = 0; unsigned char *var_test_dir; unsigned char *var_corr_dir; unsigned char *var_info_dir; unsigned char *var_tgz_dir; problem_xml_t px; const struct section_global_data *global = serve_state.global; if (skip_arch_count > 0) { for (i = 0; i < serve_state.max_abstr_tester; ++i) { tst = serve_state.abstr_testers[i]; if (!tst) continue; tst->skip_testing = -1; for (j = 0; j < skip_arch_count; ++j) { if (!strcmp(skip_archs[j], tst->arch)) { break; } } if (j < skip_arch_count) { tst->skip_testing = 1; } } } /* check spooler dirs */ if (check_writable_spool(global->run_queue_dir, SPOOL_OUT) < 0) return -1; if (check_writable_dir(global->run_exe_dir) < 0) return -1; /* check working dirs */ if (make_writable(global->run_work_dir) < 0) return -1; if (check_writable_dir(global->run_work_dir) < 0) return -1; for (i = 1; i <= serve_state.max_prob; i++) { prb = serve_state.probs[i]; if (!prb) continue; if (prb->disable_testing) continue; if (prb->manual_checking) continue; /* ignore output-only problems with XML and answer variants */ px = 0; if (prb->variant_num > 0 && prb->xml.a) { px = prb->xml.a[0]; } else { px = prb->xml.p; } if (px && px->answers) { prb->disable_testing = 1; continue; } // check if there exists a tester for this problem for (j = 1; j <= serve_state.max_tester; j++) { if (!serve_state.testers[j]) continue; if (serve_state.testers[j]->any) break; if (serve_state.testers[j]->problem == i) break; } if (j > serve_state.max_tester) { // no checker for the problem :-( info("no checker found for problem %d", i); continue; } if (prb->type > 0 && prb->type != PROB_TYPE_TESTS) { // output-only problems have no input file if (prb->variant_num <= 0) { if (prb->use_corr) { if (!prb->corr_dir[0]) { err("directory with answers is not defined"); return -1; } if (global->advanced_layout > 0) { var_corr_dir = (unsigned char*) alloca(sizeof(path_t)); get_advanced_layout_path(var_corr_dir, sizeof(path_t), global, prb, DFLT_P_CORR_DIR, -1); } else { var_corr_dir = prb->corr_dir; } if (check_readable_dir(var_corr_dir) < 0) return -1; if ((n2 = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0) return -1; n1 = n2; info("found %d answers for problem %s", n2, prb->short_name); if (n2 != 1) { err("output-only problem must define only one answer file"); return -1; } } if (prb->use_info) { if (!prb->info_dir[0]) { err("directory with test information is not defined"); return -1; } if (global->advanced_layout > 0) { var_info_dir = (unsigned char*) alloca(sizeof(path_t)); get_advanced_layout_path(var_info_dir, sizeof(path_t), global, prb, DFLT_P_INFO_DIR, -1); } else { var_info_dir = prb->info_dir; } if (check_readable_dir(var_info_dir) < 0) return -1; if ((n2 = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0) return -1; info("found %d info files for problem %s", n2, prb->short_name); if (n2 != 1) { err("output-only problem must define only one info file"); return -1; } } if (prb->use_tgz) { if (!prb->tgz_dir[0]) { err("directory with tgz information is not defined"); return -1; } if (global->advanced_layout > 0) { var_tgz_dir = (unsigned char*) alloca(sizeof(path_t)); get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global, prb, DFLT_P_TGZ_DIR, -1); } else { var_tgz_dir = prb->tgz_dir; } if (check_readable_dir(var_tgz_dir) < 0) return -1; if ((n2 = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1; info("found %d tgz files for problem %s", n2, prb->short_name); if (n2 != 1) { err("output-only problem must define only one tgz file"); return -1; } } } else { var_test_dir = (unsigned char *) alloca(sizeof(path_t)); var_corr_dir = (unsigned char *) alloca(sizeof(path_t)); var_info_dir = (unsigned char *) alloca(sizeof(path_t)); var_tgz_dir = (unsigned char *) alloca(sizeof(path_t)); for (k = 1; k <= prb->variant_num; k++) { if (global->advanced_layout > 0) { get_advanced_layout_path(var_test_dir, sizeof(path_t), global, prb, DFLT_P_TEST_DIR, k); get_advanced_layout_path(var_corr_dir, sizeof(path_t), global, prb, DFLT_P_CORR_DIR, k); get_advanced_layout_path(var_info_dir, sizeof(path_t), global, prb, DFLT_P_INFO_DIR, k); get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global, prb, DFLT_P_TGZ_DIR, k); } else { snprintf(var_test_dir, sizeof(path_t), "%s-%d", prb->test_dir, k); snprintf(var_corr_dir, sizeof(path_t), "%s-%d", prb->corr_dir, k); snprintf(var_info_dir, sizeof(path_t), "%s-%d", prb->info_dir, k); snprintf(var_tgz_dir, sizeof(path_t), "%s-%d", prb->tgz_dir, k); } if (prb->use_corr) { if (!prb->corr_dir[0]) { err("directory with answers is not defined"); return -1; } if (check_readable_dir(var_corr_dir) < 0) return -1; if ((j = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0) return -1; if (j != 1) { err("output-only problem must define only one answer file"); return -1; } } if (prb->use_info) { if (!prb->info_dir[0]) { err("directory with test infos is not defined"); return -1; } if (check_readable_dir(var_info_dir) < 0) return -1; if ((j = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0) return -1; if (j != 1) { err("output-only problem must define only one info file"); return -1; } } if (prb->use_tgz) { if (!prb->tgz_dir[0]) { err("directory with tgz is not defined"); return -1; } if (check_readable_dir(var_tgz_dir) < 0) return -1; if ((j = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1; if (j != 1) { err("output-only problem must define only one info file"); return -1; } } } n1 = n2 = 1; } } else if (!prb->type) { /* check existence of tests */ if (prb->variant_num <= 0) { if (global->advanced_layout > 0) { var_test_dir = (unsigned char *) alloca(sizeof(path_t)); get_advanced_layout_path(var_test_dir, sizeof(path_t), global, prb, DFLT_P_TEST_DIR, -1); } else { var_test_dir = prb->test_dir; } if (check_readable_dir(var_test_dir) < 0) return -1; if ((n1 = count_files(var_test_dir, prb->test_sfx, prb->test_pat)) < 0) return -1; if (!n1) { err("'%s' does not contain any tests", var_test_dir); return -1; } /* if (prb->type_val > 0 && n1 != 1) { err("`%s' must have only one test (as output-only problem)", prb->short_name); return -1; } */ info("found %d tests for problem %s", n1, prb->short_name); if (n1 < prb->tests_to_accept) { err("%d tests required for problem acceptance!",prb->tests_to_accept); return -1; } if (prb->use_corr) { if (!prb->corr_dir[0]) { err("directory with answers is not defined"); return -1; } if (global->advanced_layout > 0) { var_corr_dir = (unsigned char *) alloca(sizeof(path_t)); get_advanced_layout_path(var_corr_dir, sizeof(path_t), global, prb, DFLT_P_CORR_DIR, -1); } else { var_corr_dir = prb->corr_dir; } if (check_readable_dir(var_corr_dir) < 0) return -1; if ((n2 = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0) return -1; info("found %d answers for problem %s", n2, prb->short_name); if (n1 != n2) { err("number of test does not match number of answers"); return -1; } } if (prb->use_info) { if (!prb->info_dir[0]) { err("directory with test information is not defined"); return -1; } if (global->advanced_layout > 0) { var_info_dir = (unsigned char *) alloca(sizeof(path_t)); get_advanced_layout_path(var_info_dir, sizeof(path_t), global, prb, DFLT_P_INFO_DIR, -1); } else { var_info_dir = prb->info_dir; } if (check_readable_dir(var_info_dir) < 0) return -1; if ((n2 = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0) return -1; info("found %d info files for problem %s", n2, prb->short_name); if (n1 != n2) { err("number of test does not match number of info files"); return -1; } } if (prb->use_tgz) { if (!prb->tgz_dir[0]) { err("directory with tgz information is not defined"); return -1; } if (global->advanced_layout > 0) { var_tgz_dir = (unsigned char *) alloca(sizeof(path_t)); get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global, prb, DFLT_P_TGZ_DIR, -1); } else { var_tgz_dir = prb->tgz_dir; } if (check_readable_dir(var_tgz_dir) < 0) return -1; if ((n2 = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1; info("found %d tgz files for problem %s", n2, prb->short_name); if (n1 != n2) { err("number of test does not match number of tgz files"); return -1; } } } else { n1 = n2 = -1; var_test_dir = (unsigned char *) alloca(sizeof(path_t)); var_corr_dir = (unsigned char *) alloca(sizeof(path_t)); var_info_dir = (unsigned char *) alloca(sizeof(path_t)); var_tgz_dir = (unsigned char *) alloca(sizeof(path_t)); for (k = 1; k <= prb->variant_num; k++) { if (global->advanced_layout > 0) { get_advanced_layout_path(var_test_dir, sizeof(path_t), global, prb, DFLT_P_TEST_DIR, k); get_advanced_layout_path(var_corr_dir, sizeof(path_t), global, prb, DFLT_P_CORR_DIR, k); get_advanced_layout_path(var_info_dir, sizeof(path_t), global, prb, DFLT_P_INFO_DIR, k); get_advanced_layout_path(var_tgz_dir, sizeof(path_t), global, prb, DFLT_P_TGZ_DIR, k); } else { snprintf(var_test_dir, sizeof(path_t), "%s-%d", prb->test_dir, k); snprintf(var_corr_dir, sizeof(path_t), "%s-%d", prb->corr_dir, k); snprintf(var_info_dir, sizeof(path_t), "%s-%d", prb->info_dir, k); snprintf(var_tgz_dir, sizeof(path_t), "%s-%d", prb->tgz_dir, k); } if (check_readable_dir(var_test_dir) < 0) return -1; if ((j = count_files(var_test_dir, prb->test_sfx, prb->test_pat)) < 0) return -1; if (!j) { err("'%s' does not contain any tests", var_test_dir); return -1; } /* if (prb->type_val > 0 && n1 != 1) { err("`%s', variant %d must have only one test (as output-only problem)", prb->short_name, j); return -1; } */ if (n1 < 0) n1 = j; if (n1 != j) { err("number of tests %d for variant %d does not equal %d", j, k, n1); return -1; } info("found %d tests for problem %s, variant %d", n1, prb->short_name, k); if (n1 < prb->tests_to_accept) { err("%d tests required for problem acceptance!", prb->tests_to_accept); return -1; } if (prb->use_corr) { if (!prb->corr_dir[0]) { err("directory with answers is not defined"); return -1; } if (check_readable_dir(var_corr_dir) < 0) return -1; if ((j = count_files(var_corr_dir,prb->corr_sfx,prb->corr_pat)) < 0) return -1; info("found %d answers for problem %s, variant %d", j, prb->short_name, k); if (n1 != j) { err("number of tests %d does not match number of answers %d", n1, j); return -1; } } if (prb->use_info) { if (!prb->info_dir[0]) { err("directory with test infos is not defined"); return -1; } if (check_readable_dir(var_info_dir) < 0) return -1; if ((j = count_files(var_info_dir,prb->info_sfx,prb->info_pat)) < 0) return -1; info("found %d test infos for problem %s, variant %d", j, prb->short_name, k); if (n1 != j) { err("number of tests %d does not match number of test infos %d", n1, j); return -1; } } if (prb->use_tgz) { if (!prb->tgz_dir[0]) { err("directory with tgz is not defined"); return -1; } if (check_readable_dir(var_tgz_dir) < 0) return -1; if ((j = count_files(var_tgz_dir, prb->tgz_sfx, 0)) < 0) return -1; info("found %d tgzs for problem %s, variant %d", j, prb->short_name, k); if (n1 != j) { err("number of tests %d does not match number of tgz %d", n1, j); return -1; } } n2 = n1; } } } if (n1 >= tests_a - 1) { if (!tests_a) tests_a = 128; while (n1 >= tests_a - 1) tests_a *= 2; xfree(tests); XCALLOC(tests, tests_a); } ASSERT(prb->test_score >= 0); if (global->score_system == SCORE_MOSCOW) { if (prb->full_score <= 0) { err("problem %s: problem full_score is not set", prb->short_name); return -1; } prb->ntests = n1; if (!prb->scoring_checker) { if (!(prb->x_score_tests = prepare_parse_score_tests(prb->score_tests, prb->full_score))){ err("problem %s: parsing of score_tests failed", prb->short_name); return -1; } prb->x_score_tests[prb->full_score - 1] = n1 + 1; if (prb->full_score > 1 && prb->x_score_tests[prb->full_score - 2] > n1 + 1) { err("problem %s: score_tests[%d] > score_tests[%d]", prb->short_name, prb->full_score - 2, prb->full_score - 1); return -1; } } } else if (prb->test_score >= 0 && global->score_system != SCORE_ACM) { int score_summ = 0; prb->ntests = n1; XCALLOC(prb->tscores, prb->ntests + 1); for (j = 1; j <= prb->ntests; j++) prb->tscores[j] = prb->test_score; // test_score_list overrides test_score if (prb->test_score_list && prb->test_score_list[0]) { char const *s = prb->test_score_list; int tn = 1; int was_indices = 0; int n; int index, score; while (1) { while (*s > 0 && *s <= ' ') s++; if (!*s) break; if (*s == '[') { if (sscanf(s, "[ %d ] %d%n", &index, &score, &n) != 2) { err("cannot parse test_score_list for problem %s", prb->short_name); return -1; } if (index < 1 || index > prb->ntests) { err("problem %s: test_score_list: index out of range", prb->short_name); return -1; } if (score < 0) { err("problem %s: test_score_list: invalid score", prb->short_name); return -1; } tn = index; was_indices = 1; prb->tscores[tn++] = score; s += n; } else { if (sscanf(s, "%d%n", &score, &n) != 1) { err("cannot parse test_score_list for problem %s", prb->short_name); return -1; } if (score < 0) { err("problem %s: test_score_list: invalid score", prb->short_name); return -1; } if (tn > prb->ntests) { err("problem %s: too many scores specified", prb->short_name); return -1; } prb->tscores[tn++] = score; s += n; } } if (!was_indices && tn <= prb->ntests) { info("test_score_list for problem %s defines only %d tests", prb->short_name, tn - 1); } } for (j = 1; j <= prb->ntests; j++) score_summ += prb->tscores[j]; if (score_summ > prb->full_score && !prb->valuer_cmd[0]) { err("total score (%d) > full score (%d) for problem %s", score_summ, prb->full_score, prb->short_name); return -1; } } } for (i = 1; i <= serve_state.max_tester; i++) { if (!serve_state.testers[i]) continue; if (serve_state.testers[i]->any) continue; prb = serve_state.probs[serve_state.testers[i]->problem]; total++; /* check working dirs */ if (make_writable(serve_state.testers[i]->check_dir) < 0) return -1; if (check_writable_dir(serve_state.testers[i]->check_dir) < 0) return -1; if (serve_state.testers[i]->prepare_cmd[0] && check_executable(serve_state.testers[i]->prepare_cmd) < 0) return -1; if (serve_state.testers[i]->start_cmd[0] && check_executable(serve_state.testers[i]->start_cmd) < 0) return -1; } info("checking default testers..."); if ((i = process_default_testers()) < 0) return -1; info("checking default testers done"); total += i; if (!total) info("no testers"); #if CONF_HAS_LIBINTL - 0 == 1 // bind message catalogs, if specified if (global->enable_l10n && global->l10n_dir[0]) { bindtextdomain("ejudge", global->l10n_dir); textdomain("ejudge"); } #endif return 0; }