/* remove VLAN header from packet and update csum accordingly. */ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) { struct vlan_hdr *vhdr; int err; err = make_writable(skb, VLAN_ETH_HLEN); if (unlikely(err)) return err; if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) skb->csum = csum_sub(skb->csum, csum_partial(skb->data + ETH_HLEN, VLAN_HLEN, 0)); vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); *current_tci = vhdr->h_vlan_TCI; memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN); __skb_pull(skb, VLAN_HLEN); vlan_set_encap_proto(skb, vhdr); skb->mac_header += VLAN_HLEN; skb_reset_mac_len(skb); return 0; }
void set_drmarker_hotp_policy_status_table(void *new_table) { dr_marker_t *dr_marker = get_drmarker(); ASSERT_OWN_WRITE_LOCK(true, hotp_get_lock()); /* We don't want to write to the dr_marker_t before it is initialized; we * could get an exception. */ if (dr_marker == NULL) /* Part of fix for case 5367. */ return; /* Ok, dr_marker_t has been initialized. */ /* It is ok to do this memory protection change here even though this can * be any arbitrary time due to the nature of nudge. This is because * once initialized, the dr_marker_t isn't touched by any one except the hot * patch nudge. * * TODO: In future other parts of the core may need to change the dr_marker_t. * It might be a good idea to introduce a lock for the dr_marker_t and * generic accessor functions. */ make_writable((byte*)dr_marker, INTERCEPTION_CODE_SIZE); dr_marker->dr_hotp_policy_status_table = new_table; make_unwritable((byte*)dr_marker, INTERCEPTION_CODE_SIZE); }
static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *ipv4_key) { struct iphdr *nh; int err; err = make_writable(skb, skb_network_offset(skb) + sizeof(struct iphdr)); if (unlikely(err)) return err; nh = ip_hdr(skb); if (ipv4_key->ipv4_src != nh->saddr) set_ip_addr(skb, nh, &nh->saddr, ipv4_key->ipv4_src); if (ipv4_key->ipv4_dst != nh->daddr) set_ip_addr(skb, nh, &nh->daddr, ipv4_key->ipv4_dst); if (ipv4_key->ipv4_tos != nh->tos) ipv4_change_dsfield(nh, 0, ipv4_key->ipv4_tos); if (ipv4_key->ipv4_ttl != nh->ttl) set_ip_ttl(skb, nh, ipv4_key->ipv4_ttl); return 0; }
/* remove VLAN header from packet and update csum accordingly. */ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) { struct vlan_hdr *vhdr; int err; err = make_writable(skb, VLAN_ETH_HLEN); if (unlikely(err)) return err; if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_sub(skb->csum, csum_partial(skb->data + (2 * ETH_ALEN), VLAN_HLEN, 0)); vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN); *current_tci = vhdr->h_vlan_TCI; memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN); __skb_pull(skb, VLAN_HLEN); vlan_set_encap_proto(skb, vhdr); skb->mac_header += VLAN_HLEN; /* Update mac_len for subsequent MPLS actions */ skb->mac_len -= VLAN_HLEN; return 0; }
static int pop_mpls(struct sk_buff *skb, const __be16 ethertype) { struct ethhdr *hdr; int err; err = make_writable(skb, skb->mac_len + MPLS_HLEN); if (unlikely(err)) return err; if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_sub(skb->csum, csum_partial(mac_header_end(skb), MPLS_HLEN, 0)); memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb), skb->mac_len); __skb_pull(skb, MPLS_HLEN); skb_reset_mac_header(skb); /* mac_header_end() is used to locate the ethertype * field correctly in the presence of VLAN tags. */ hdr = (struct ethhdr *)(mac_header_end(skb) - ETH_HLEN); hdr->h_proto = ethertype; if (eth_p_mpls(skb->protocol)) skb->protocol = ethertype; return 0; }
void addr_cache_init(os_exception_frame_t *frame) { (void) frame; // Only run this if not already initialized if(addr_cache) return; addr_cache = mmap((void*)0, AC_NUM_ENTRIES * sizeof(ac_entry), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); if(addr_cache == MAP_FAILED) { addr_cache = NULL; fprintf(stderr, "Failed to mmap addr_cache.\n"); exit(1); } setbuf(stdout, NULL); unsigned int i; for(i = 0; i < AC_NUM_ENTRIES; ++i) { AC_SET_ENTRY_INVALID(addr_cache[i], (i >> 1) << 10) } #if defined(__i386__) && !defined(NO_TRANSLATION) // Relocate the assembly code that wants addr_cache at a fixed address extern uint32_t *ac_reloc_start[] __asm__("ac_reloc_start"), *ac_reloc_end[] __asm__("ac_reloc_end"); uint32_t **reloc; for(reloc = ac_reloc_start; reloc != ac_reloc_end; reloc++) { make_writable(*reloc); **reloc += (uintptr_t)addr_cache; } #endif }
static int set_eth_addr(struct sk_buff *skb, const struct ovs_key_ethernet *eth_key) { int err; err = make_writable(skb, ETH_HLEN); if (unlikely(err)) return err; memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN); memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN); return 0; }
static int set_eth_addr(struct sk_buff *skb, const struct ovs_key_ethernet *eth_key) { int err; err = make_writable(skb, ETH_HLEN); if (unlikely(err)) return err; skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2); ether_addr_copy(eth_hdr(skb)->h_source, eth_key->eth_src); ether_addr_copy(eth_hdr(skb)->h_dest, eth_key->eth_dst); ovs_skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2); return 0; }
static int set_tcp(struct sk_buff *skb, const struct ovs_key_tcp *tcp_port_key) { struct tcphdr *th; int err; err = make_writable(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)); if (unlikely(err)) return err; th = tcp_hdr(skb); if (tcp_port_key->tcp_src != th->source) set_tp_port(skb, &th->source, tcp_port_key->tcp_src, &th->check); if (tcp_port_key->tcp_dst != th->dest) set_tp_port(skb, &th->dest, tcp_port_key->tcp_dst, &th->check); return 0; }
static int set_udp(struct sk_buff *skb, const struct ovs_key_udp *udp_port_key) { struct udphdr *uh; int err; err = make_writable(skb, skb_transport_offset(skb) + sizeof(struct udphdr)); if (unlikely(err)) return err; uh = udp_hdr(skb); if (udp_port_key->udp_src != uh->source) set_udp_port(skb, &uh->source, udp_port_key->udp_src); if (udp_port_key->udp_dst != uh->dest) set_udp_port(skb, &uh->dest, udp_port_key->udp_dst); return 0; }
static int set_mpls(struct sk_buff *skb, const __be32 *mpls_lse) { __be32 *stack = (__be32 *)mac_header_end(skb); int err; err = make_writable(skb, skb->mac_len + MPLS_HLEN); if (unlikely(err)) return err; if (skb->ip_summed == CHECKSUM_COMPLETE) { __be32 diff[] = { ~(*stack), *mpls_lse }; skb->csum = ~csum_partial((char *)diff, sizeof(diff), ~skb->csum); } *stack = *mpls_lse; return 0; }
static int set_eth_addr(struct sk_buff *skb, const struct ovs_key_ethernet *eth_key) { int err; err = make_writable(skb, ETH_HLEN); if (unlikely(err)) return err; if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) skb->csum = csum_sub(skb->csum, csum_partial(eth_hdr(skb), ETH_ALEN * 2, 0)); memcpy(eth_hdr(skb)->h_source, eth_key->eth_src, ETH_ALEN); memcpy(eth_hdr(skb)->h_dest, eth_key->eth_dst, ETH_ALEN); if (get_ip_summed(skb) == OVS_CSUM_COMPLETE) skb->csum = csum_add(skb->csum, csum_partial(eth_hdr(skb), ETH_ALEN * 2, 0)); 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; }
static int process_default_testers(void) { int total = 0; int i, j, k; unsigned char *prob_flags = 0; struct section_tester_data *tp, *tq; struct section_problem_data *ts; struct section_tester_data tn; //temporary entry prob_flags = (unsigned char *) alloca(serve_state.max_prob + 1); /* scan all the 'any' testers */ for (i = 1; i <= serve_state.max_tester; i++) { tp = serve_state.testers[i]; if (!tp || !tp->any) continue; // check architecture uniqueness for (j = 1; j <= serve_state.max_tester; j++) { tq = serve_state.testers[j]; if (i == j || !tq || !tq->any) continue; if (strcmp(serve_state.testers[j]->arch, tp->arch) != 0) continue; err("default testers %d and %d has the same architecture '%s'", i, j, tp->arch); return -1; } // mark the problems with explicit testers for this architecture memset(prob_flags, 0, serve_state.max_prob + 1); for (j = 1; j <= serve_state.max_tester; j++) { tq = serve_state.testers[j]; if (!tq || tq->any) continue; if (strcmp(tp->arch, tq->arch) != 0) continue; // tq is specific tester with the same architecture ASSERT(tq->problem > 0 && tq->problem <= serve_state.max_prob); ASSERT(serve_state.probs[tq->problem]); prob_flags[tq->problem] = 1; } // scan all problems, which have no default tester for (k = 1; k <= serve_state.max_prob; k++) { ts = serve_state.probs[k]; if (!ts || prob_flags[k]) continue; if (ts->disable_testing) continue; if (ts->manual_checking) continue; // so at this point: tp - pointer to the default tester, // k is the problem number // ts - pointer to the problem which should be handled by the // default tester if (prepare_tester_refinement(&serve_state, &tn, i, k) < 0) return -1; if (create_tester_dirs(&tn) < 0) return -1; /* check working dirs */ if (make_writable(tn.check_dir) < 0) return -1; if (check_writable_dir(tn.check_dir) < 0) return -1; if (tn.prepare_cmd[0] && check_executable(tn.prepare_cmd) < 0) return -1; if (tn.start_cmd[0] && check_executable(tn.start_cmd) < 0) return -1; total++; sarray_free(tn.start_env); sarray_free(tn.super); } } return total; }