/* return zero on success */ int path_join(const char *base, int base_len, const char *extend, int extend_len, char *output, int size) { int i; if(extend_len < 0) extend_len = strlen(extend); if(path_isabs(extend)) { /* just copy the extend path */ if(extend_len+1 > size) { fprintf(stderr, "'%s' + '%s' results in a too long path\n", base, extend); return __LINE__; } memcpy(output, extend, extend_len+1); path_normalize(output); return 0; } if(base_len < 0) base_len = strlen(base); /* +2 for separator and null terminator */ if(base_len+extend_len+2 > size) { fprintf(stderr, "'%s' + '%s' results in a too long path\n", base, extend); return __LINE__; } /* no base path, just use extend path then */ if(base_len == 0) { memcpy(output, extend, extend_len+1); path_normalize(output); return 0; } /* copy base path */ memcpy(output, base, base_len); /* append path separator if needed */ if(!path_is_separator(base[base_len-1])) { output[base_len] = PATH_SEPARATOR; base_len++; } /* append the extra path, and null-terminator*/ for(i = 0; i < extend_len+1; i++) output[base_len+i] = extend[i]; /* normalize path and return success */ path_normalize(output); return 0; }
/* * Convert a system path into a VFS path. */ const char *fs_resolve(const char *system) { static char path[MAXSTR]; const char *p; /* * PhysicsFS will claim a file doesn't exist if its path uses a * directory separator other than a forward slash, even if that * separator is valid for the system. We'll oblige. */ SAFECPY(path, system); path_normalize(path); if (fs_exists(path)) return path; /* Chop off directories until we have a match. */ p = path; while ((p = path_next_sep(p))) { /* Skip separator. */ p += 1; if (fs_exists(p)) return p; } return NULL; }
fscrawl_t fsc_open(const char *path) { struct __fscrawl *f; char *npath; f = malloc(sizeof(struct __fscrawl)); if (!f) return NULL; npath = path_normalize(path, NULL, 1); if (!npath) goto free; f->fts = _fts_open(npath, FTS_LOGICAL); free(npath); if (!f->fts) { logerrno(LOG_WARN, "ftc_open", errno); goto free; } f->ent.base = NULL; f->ent.name = NULL; f->ent.dir = 0; return f; free: if (f) free(f); return NULL; }
int lf_path_dir(lua_State *L) { char buffer[1024]; int n = lua_gettop(L); const char *path = 0; if(n < 1) luaL_error(L, "path_dir: incorrect number of arguments"); path = lua_tostring(L, 1); if(!path) luaL_error(L, "path_dir: argument is not a string"); /* check if we can take the easy way out */ if(path_isnice(path)) { lua_pushlstring(L, path, path_dir_length(path)); return 1; } /* we must normalize the path as well */ strncpy(buffer, path, sizeof(buffer)); path_normalize(buffer); lua_pushlstring(L, buffer, path_dir_length(buffer)); return 1; }
depsRef depsScanForHeaders(const char *path) { PATHSPLIT f; char buf[MAXJPATH]; time_t time; HEADER *h; if (!inState(DEPS_STATE_INIT | DEPS_STATE_SEARCH)) { if (!inState(DEPS_STATE_SEARCH)) setErr(DEPS_ERROR_NOT_SEARCH); if (!inState(DEPS_STATE_INIT)) setErr(DEPS_ERROR_NOT_INIT); return NULL; } setErr(0); path_split(path, &f); path_normalize(&f, NULL); path_tostring(&f, buf); timestamp(buf, &time); if (!time) return NULL; h = headers(buf, time); return (depsRef) h; }
int lf_path_normalize(lua_State *L) { int n = lua_gettop(L); const char *path = 0; if(n != 1) luaL_error(L, "path_normalize: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); path = lua_tostring(L, 1); if(path_isnice(path)) { /* path is ok */ lua_pushstring(L, path); } else { /* normalize and return */ char buffer[2*1024]; strcpy(buffer, path); path_normalize(buffer); lua_pushstring(L, buffer); } return 1; }
char * path_reltoabs( char *dir, char *basedir ) { char *absdir; /* check if the path starts with a / or * is a remote path (i.e. contains machine:/path/name ). */ if ( ( *dir != '/' ) && ( strchr(dir, ':') == 0 ) ) { char *absdir; absdir = ( char * )malloc( strlen( basedir ) + 1 + strlen( dir ) + 1 ); ASSERT( absdir ); ( void )sprintf( absdir, "%s/%s", basedir, dir ); dir = absdir; } if ( strchr(dir, ':') == 0 ) { absdir = path_normalize( dir ); } else { absdir = ( char * )malloc( strlen( dir ) + 1); ( void )sprintf( absdir, "%s", dir); } return absdir; }
static int addwatch(const char *path, const char *name) { fscrawl_t f; char *npath = path_normalize(path, name, 1); if (!npath) return -1; if (inotify_watch(npath) < 0) goto clean; f = fsc_open(npath); if (!f) goto clean; for(;;) { notify_event *ev; fs_entry *ent = fsc_read(f); if (!ent) break; ev = notify_event_new(); notify_event_set_type(ev, NOTIFY_CREATE); notify_event_set_path(ev, ent->base); notify_event_set_filename(ev, ent->name); notify_event_set_dir(ev, ent->dir); if (ev->dir) { char *fullpath = path_normalize(ev->path, ent->name, 1); if (fullpath && inotify_watch(fullpath) < 0) xfree(fullpath); } queue_enqueue(init_ev_q, ev); } fsc_close(f); return 1; clean: xfree(npath); return -1; }
static void windows_tz_to_tzid(char *buf, int max, Str name) { Tok tk; char *path = path_normalize(NULL, fs->fox_home, "data" SEP_S "windows-tz.txt", -1, NULL); char *ini_buf = read_from_file(NULL, path, NULL); free(path); if (buf == NULL) { goto ERROR_END; } Tok_simple_init(&tk, ini_buf); Tok_simple_next(&tk); for (;;) { switch (tk.v.type) { case TL_STR: if (str_eq(tk.str_val.p, tk.str_val.size, name.p, name.size)) { Tok_simple_next(&tk); if (tk.v.type != T_LET) { goto ERROR_END; } Tok_simple_next(&tk); if (tk.v.type != TL_STR) { goto ERROR_END; } memcpy(buf, tk.str_val.p, tk.str_val.size); buf[tk.str_val.size] = '\0'; free(ini_buf); return; } else { // 行末まで飛ばす while (tk.v.type == T_LET || tk.v.type == TL_STR) { Tok_simple_next(&tk); } } break; case T_NL: case T_SEMICL: Tok_simple_next(&tk); break; case T_EOF: goto ERROR_END; default: fatal_errorf("Parse error at line %d (windows-tz.txt)", tk.v.line); break; } } ERROR_END: strcpy(buf, "Etc/UTC"); free(ini_buf); }
void test(const char *path) { PATHSPLIT f; char buf[1024]; printf("> %s\n", path); path_split(path, &f); path_print(&f); path_normalize(&f, NULL); path_tostring(&f, buf); printf("< %s\n", buf); }
static int rmwatch(const char *path, const char *name) { char *fpath; int ret; fpath = path_normalize(path, name, 1); if (!fpath) return -1; ret = inotify_ignore(fpath); free(fpath); return ret; }
void search_adddir(const char *path) { PATHSPLIT f; char buf[MAXJPATH]; path_split(path, &f); path_normalize(&f, NULL); /* path_setcwd() should have been called */ path_tostring(&f, buf); searchdirs = list_new(searchdirs, buf, 0); #ifdef SEARCH_OPTIM /* searchhash is only valid for a fixed set of search directories */ hashdone(searchhash); searchhash = 0; #endif }
static int pkcs8_dir_open(void *_handle, const char *config) { if (!_handle || !config) { return DNSSEC_EINVAL; } pkcs8_dir_handle_t *handle = _handle; char *path = path_normalize(config); if (!path) { return DNSSEC_NOT_FOUND; } handle->dir_name = path; return DNSSEC_EOK; }
void depsTimeStamp(const char *path, time_t *time) { PATHSPLIT f; char buf[MAXJPATH]; if (!inState(DEPS_STATE_INIT)) { setErr(DEPS_ERROR_NOT_INIT); return; } setErr(0); path_split(path, &f); path_normalize(&f, NULL); path_tostring(&f, buf); timestamp(buf, time); }
t_httpreq * parse(char *input) { char *inputdup, *token, *subtoken; char vbuf[MAX_VERSION_LENGTH]; int n; /* For storing temporary value, i.e return codes */ t_httpreq *req; inputdup = strdup(input); req = (t_httpreq*)malloc(sizeof(t_httpreq)); if (req == NULL) fprintf(stderr,"malloc cannot allocate memory for new request"); req->version = strdup(DEFAULT_VERSION); req->versionlen = 3; req->valid = 1; req->ifmodifiedsince = -1; /* Parse the HTTP method */ if ((token = strtok(inputdup, " ")) == NULL) { req->valid = 0; } else { /* Note: method may be null if strdup fails * Below I tried to make sure that the method could not * be overflowed. The method should only be written to * the object if it is a valid method otherwise it should * be NULL */ if (strlen(token) > MAX_METHOD_LENGTH) { req->method = NULL; } else { req->method = strdup(token); } if (req->method != NULL) { req->methodlen = strlen(token); } else { req->valid=0; } req->method_ident = ident_method(token); if (req->method_ident == HTTP_OTHER) { req->valid=0; } } /* Parse the request URL */ if ((token = strtok(NULL, " ")) == NULL) { req->valid = 0; } else { if (strlen(token) > MAX_URI_LENGTH) { req->url = NULL; } else { req->url = strdup(path_normalize(token)); } if (req->url != NULL) { req->urllen = strlen(token); } else { req->valid=0; req->urllen = -1; } } /* Parse the HTTP version */ if ((token = strtok(NULL, " ")) == NULL) { req->valid = 0; } else { if (strncmp(token, "HTTP/", 5) != 0 || /* must start with HTTP/ */ strlen(token) < 8 || /* must have a length of 8 */ strchr(token+6, '.') == NULL) { /* version must have a '.' */ req->valid = 0; } else { token += 5; /* Parse major version */ subtoken = strtok(token, "."); req->majorversion = atoi(subtoken); /* Parse minor version */ if ((subtoken = strtok(NULL, ".")) == NULL) { req->valid = 0; } else { req->minorversion = atoi(subtoken); if ((n = sprintf(vbuf, "%d.%d", req->majorversion, req->minorversion)) > 0) { /* Free default version that was allocated */ free(req->version); /* Note: Version may be null if strdup fails */ req->version = strdup(vbuf); if (req->version != NULL) { req->versionlen = strlen(vbuf); } else { req->versionlen = -1; } } } } } /* For no we need this to */ req->content = 1; free(inputdup); return req; }
const char *search(const char *source, const char *_header, time_t *time) { PATHNAME f[1]; char buf[MAXJPATH]; char buf2[MAXSYM], *header = buf2; char buf3[MAXJPATH]; int system = (_header[0] == '<'); LIST *list = searchdirs->next; /* D support */ int dMode=0; int fnlen=strlen(source); if(source[fnlen-2]=='.' && source[fnlen-1]=='d') dMode=1; /* <foo.h> --> foo.h */ strcpy(header, _header + 1); header[strlen(header) - 1] = '\0'; /* src/foo.c --> src */ path_parse(source, f); path_parent(f); path_build(f, buf3, 1); /* C::B patch: Fix bug with usage of root folder */ # if PATH_DELIM == '\\' /* Special case for D:/ - dirname is D:/, not "D:" */ if ((strlen(buf3)==3) && (buf3[1]==':') && ((buf3[2]=='\\') || (buf3[2]=='/'))) buf3[2] = 0; # endif if (DEBUG_SEARCH) printf( "search %s\n included by %s\n", _header, source); #ifdef SEARCH_OPTIM { char key[MAXJPATH] = ""; SEARCH search, *s = &search; if (!system) { strcpy(key, buf3); strcat(key, ","); } strcat(key, _header); s->key = key; if (!searchhash) searchhash = hashinit(sizeof(SEARCH), "search"); if (hashcheck(searchhash, (HASHDATA **)&s)) { if (DEBUG_SEARCH) printf(" %s: %s [CACHED]\n", _header, s->time ? s->path : "*missing*" ); *time = s->time; return s->path; } } #endif /* If this is "foo.h" not <foo.h> then set the first search directory * to the including file's directory */ if (!system) { searchdirs->string = buf3; list = searchdirs; } path_parse(header, f); f->f_grist.ptr = 0; f->f_grist.len = 0; for (; list; list = list->next) { f->f_root.ptr = list->string; f->f_root.len = strlen(list->string); path_build(f, buf, 1); { PATHSPLIT f; char buf2[MAXJPATH]; path_split(buf, &f); path_normalize(&f, NULL); path_tostring(&f, buf2); strcpy(buf, buf2); } if (DEBUG_SEARCH) printf(" %s: %s [TRY]\n", _header, buf); timestamp(buf, time); #ifdef SEARCH_OPTIM if (*time) { char key[MAXJPATH] = ""; SEARCH search, *s = &search; if (!system) { strcpy(key, buf3); strcat(key, ","); } strcat(key, _header); s->key = newstr(key); s->time = *time; s->path = newstr(buf); (void) hashenter(searchhash, (HASHDATA **)&s); } #endif if (*time) return newstr(buf); } if(!dMode) { #ifdef SEARCH_OPTIM /* remember that this file could not be found */ { char key[MAXJPATH] = ""; SEARCH search, *s = &search; if (!system) { strcpy(key, buf3); strcat(key, ","); } strcat(key, _header); s->key = newstr(key); s->time = 0; s->path = NULL; (void) hashenter(searchhash, (HASHDATA **)&s); } #endif /* C compilers do *not* look in the current directory for #include files */ *time = 0; return NULL; } /* D support (look in current directory) */ else { f->f_root.ptr = 0; f->f_root.len = 0; path_build( f, buf, 1 ); { PATHSPLIT f; char buf2[MAXJPATH]; path_split(buf, &f); path_normalize(&f, NULL); path_tostring(&f, buf2); strcpy(buf, buf2); } if( DEBUG_SEARCH ) printf( "search %s: %s\n", _header, buf ); timestamp( buf, time ); #ifdef SEARCH_OPTIM if (*time) { char key[MAXJPATH] = ""; SEARCH search, *s = &search; if (!system) { strcpy(key, buf3); strcat(key, ","); } strcat(key, _header); s->key = newstr(key); s->time = *time; s->path = newstr(buf); (void) hashenter(searchhash, (HASHDATA **)&s); } #endif if (*time) return newstr(buf); #ifdef SEARCH_OPTIM /* remember that this file could not be found */ { char key[MAXJPATH] = ""; SEARCH search, *s = &search; if (!system) { strcpy(key, buf3); strcat(key, ","); } strcat(key, _header); s->key = newstr(key); s->time = 0; s->path = NULL; (void) hashenter(searchhash, (HASHDATA **)&s); } #endif *time = 0; return NULL; } }
static int dependency_cpp_callback(struct NODE *node, void *user, const char *filename, int sys) { struct CPPDEPINFO *depinfo = (struct CPPDEPINFO *)user; struct CPPDEPINFO recurseinfo; char buf[MAX_PATH_LENGTH]; int check_system = sys; int found = 0; struct NODE *depnode = NULL; time_t timestamp = 0; if(!sys) { /* "normal.header" */ int flen = strlen(node->filename)-1; while(flen) { if(node->filename[flen] == '/') break; flen--; } path_join(node->filename, flen, filename, -1, buf, sizeof(buf)); if(node_findfile(node->graph, buf, &depnode, ×tamp)) found = 1; else { /* file does not exist */ check_system = 1; } } if(check_system) { /* <system.header> */ if(path_isabs(filename)) { if(node_findfile(node->graph, filename, &depnode, ×tamp)) { strcpy(buf, filename); found = 1; } } else { struct STRINGLIST *cur; int flen = strlen(filename); for(cur = depinfo->paths; cur; cur = cur->next) { path_join(cur->str, cur->len, filename, flen, buf, sizeof(buf)); if(node_findfile(node->graph, buf, &depnode, ×tamp)) { found = 1; break; } } } } /* */ if(found) { path_normalize(buf); if(!depnode) node_create(&depnode, node->graph, buf, NULL, timestamp); if(node_add_dependency (node, depnode) == NULL) return 2; if(!depnode) return 3; /* do the dependency walk */ if(!depnode->depchecked) { recurseinfo.paths = depinfo->paths; recurseinfo.context = depinfo->context; if(dependency_cpp_run(depinfo->context, depnode, dependency_cpp_callback, &recurseinfo) != 0) return 4; } } return 0; }
int super_html_read_serve( FILE *flog, const unsigned char *path, const struct ejudge_cfg *config, const struct contest_desc *cnts, struct sid_state *sstate) { struct stat sb; int cond_count = 0, total, i, cur_id, j, arch, k; struct generic_section_config *pg; struct section_global_data *global; struct section_problem_data *prob, *aprob; struct section_tester_data *tst, *atst; struct section_language_data *lang; size_t vm_size, st_size; size_t *mem_lims, *st_lims; int *mem_cnt, *st_cnt; //int mem_u, st_u, max_i; path_t check_cmd = { 0 }; FILE *fuh; char *fuh_text = 0; size_t fuh_size = 0; path_t cs_spool_dir; path_t conf_dir; path_t tmppath; unsigned char *prob_no_any = 0; size_t cs_spool_dir_len = 0; unsigned char cs_conf_file[PATH_MAX]; if (!cnts) { fprintf(flog, "No contest XML description\n"); return -1; } if (!cnts->conf_dir || !*cnts->conf_dir) { snprintf(conf_dir, sizeof(conf_dir), "%s/%s", cnts->root_dir, "conf"); } else if (!os_IsAbsolutePath(cnts->conf_dir)) { snprintf(conf_dir, sizeof(conf_dir), "%s/%s", cnts->root_dir, cnts->conf_dir); } else { snprintf(conf_dir, sizeof(conf_dir), "%s", cnts->conf_dir); } if (stat(path, &sb) < 0) { // file do not exist return 0; } if (!S_ISREG(sb.st_mode)) { fprintf(flog, "File `%s' not a regular file\n", path); return -1; } if (access(path, R_OK) < 0) { fprintf(flog, "File `%s' is not readable\n", path); return -1; } // FIXME: redirect output? if (!(sstate->cfg = prepare_parse_config_file(path, &cond_count))) { fprintf(flog, "Parsing of `%s' failed\n", path); return -1; } if (cond_count > 0) { fprintf(flog, "The configuration file uses conditional compilation directives\n"); return -1; } // find global section for (pg = sstate->cfg; pg; pg = pg->next) if (!pg->name[0] || !strcmp(pg->name, "global")) break; if (!pg) { fprintf(flog, "The global section is not defined\n"); return -1; } global = sstate->global = (struct section_global_data *) pg; // set up the default value of the root_dir if (!global->root_dir[0]) { snprintf(global->root_dir, sizeof(global->root_dir), "%06d", global->contest_id); } if (!os_IsAbsolutePath(global->root_dir) && config && config->contests_home_dir && os_IsAbsolutePath(config->contests_home_dir)) { snprintf(tmppath, sizeof(tmppath), "%s/%s", config->contests_home_dir, global->root_dir); snprintf(global->root_dir, sizeof(global->root_dir), "%s", tmppath); } #if defined EJUDGE_CONTESTS_HOME_DIR if (!os_IsAbsolutePath(global->root_dir)) { snprintf(tmppath, sizeof(tmppath), "%s/%s", EJUDGE_CONTESTS_HOME_DIR, global->root_dir); snprintf(global->root_dir, sizeof(global->root_dir), "%s", tmppath); } #endif if (!os_IsAbsolutePath(global->root_dir)) { err("global.root_dir must be absolute directory!"); return -1; } // check variables that we don't want to be ever set if (prepare_check_forbidden_global(flog, global) < 0) return -1; // contest_id, conf_dir, root_dir must match if (global->contest_id != cnts->id) { fprintf(flog, "contest_id does not match\n"); return -1; } if (strcmp(global->root_dir, cnts->root_dir)) { fprintf(flog, "root_dir does not match\n"); return -1; } /* if ((!cnts->conf_dir && global->conf_dir) || (cnts->conf_dir && strcmp(cnts->conf_dir, global->conf_dir))) { fprintf(flog, "conf_dir does not match\n"); return -1; } */ // compile server must be used if (!global->compile_dir[0]) { fprintf(flog, "compilation server is not used\n"); return -1; } if (!os_IsAbsolutePath(global->compile_dir)) { snprintf(tmppath, sizeof(tmppath), "%s/var/%s", global->root_dir, global->compile_dir); path_normalize(tmppath, sizeof(tmppath)); snprintf(global->compile_dir, sizeof(global->compile_dir), "%s", tmppath); } if (!config->compile_home_dir) { fprintf(flog, "compile server home dir is not set\n"); return -1; } // cut off "/var/compile" suffix from the compile dir snprintf(cs_spool_dir, sizeof(cs_spool_dir), "%s", global->compile_dir); cs_spool_dir_len = strlen(cs_spool_dir); if (cs_spool_dir_len < sizeof(compile_dir_suffix) || strcmp(cs_spool_dir+cs_spool_dir_len-sizeof(compile_dir_suffix)+1, compile_dir_suffix) != 0) { fprintf(flog, "invalid `compile_dir' %s\n", cs_spool_dir); return -1; } cs_spool_dir[cs_spool_dir_len-sizeof(compile_dir_suffix)+1] = 0; sstate->compile_home_dir = xstrdup(cs_spool_dir); //fprintf(stderr, "compile_home_dir>>%s<<\n", sstate->compile_home_dir); /* snprintf(cs_spool_dir, sizeof(cs_spool_dir), "%s/var/compile", config->compile_home_dir); if (strcmp(cs_spool_dir, global->compile_dir)) { fprintf(flog, "non-default compilation server is used\n"); return -1; } */ prepare_set_global_defaults(global); if (global->stand2_file_name[0]) sstate->enable_stand2 = 1; if (global->plog_file_name[0]) sstate->enable_plog = 1; if (global->stand_extra_format[0]) sstate->enable_extra_col = 1; fuh = open_memstream(&fuh_text, &fuh_size); prepare_unparse_unhandled_global(fuh, global); close_memstream(fuh); fuh = 0; if (fuh_text && *fuh_text) { global->unhandled_vars = fuh_text; } else { xfree(fuh_text); } fuh_text = 0; fuh_size = 0; // collect languages total = 0; cur_id = 0; for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "language") != 0) continue; lang = (struct section_language_data*) pg; if (!lang->id) lang->id = cur_id + 1; cur_id = lang->id; if (lang->id <= 0 || lang->id > EJ_MAX_LANG_ID) { fprintf(flog, "Invalid language ID\n"); return -1; } if (lang->id >= total) total = lang->id + 1; } sstate->lang_a = 0; sstate->langs = 0; sstate->loc_cs_map = 0; sstate->lang_opts = 0; sstate->lang_flags = 0; if (total > 0) { sstate->lang_a = 4; while (total > sstate->lang_a) sstate->lang_a *= 2; XCALLOC(sstate->langs, sstate->lang_a); XCALLOC(sstate->loc_cs_map, sstate->lang_a); XCALLOC(sstate->lang_opts, sstate->lang_a); XCALLOC(sstate->lang_flags, sstate->lang_a); for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "language") != 0) continue; lang = (struct section_language_data*) pg; if (sstate->langs[lang->id]) { fprintf(flog, "Duplicated language ID %d\n", lang->id); return -1; } sstate->langs[lang->id] = lang; } } // load the compilation server state and establish correspondence if (super_load_cs_languages(config, sstate, global->extra_compile_dirs, 0, cs_conf_file, sizeof(cs_conf_file)) < 0) { fprintf(flog, "Failed to load compilation server configuration\n"); return -1; } for (i = 1; i < sstate->lang_a; i++) { if (!(lang = sstate->langs[i])) continue; if (!lang->compile_id) lang->compile_id = lang->id; if (prepare_check_forbidden_lang(flog, lang) < 0) return -1; /* if (lang->compile_id <= 0 || lang->compile_id >= sstate->cs_lang_total || !sstate->cs_langs[lang->compile_id]) { } */ // improve error messaging if (lang->compile_id > 0 && lang->compile_id < sstate->cs_lang_total && sstate->cs_langs[lang->compile_id] && strcmp(lang->short_name, sstate->cs_langs[lang->compile_id]->short_name) != 0) { fprintf(flog, "contest configuration file '%s' specifies language short name '%s' for language %d\n" "and it is different from language short name '%s' in compilation configuration file '%s'\n", path, lang->short_name, lang->compile_id, sstate->cs_langs[lang->compile_id]->short_name, cs_conf_file); return -1; } if (lang->compile_id <= 0 || lang->compile_id >= sstate->cs_lang_total || !sstate->cs_langs[lang->compile_id] || strcmp(lang->short_name, sstate->cs_langs[lang->compile_id]->short_name) != 0) { lang->compile_id = 0; } for (int j = 1; j < sstate->cs_lang_total; ++j) { if (sstate->cs_langs[j] && !strcmp(lang->short_name, sstate->cs_langs[j]->short_name)) { lang->compile_id = j; break; } } if (lang->compile_id <= 0) { fprintf(flog, "Invalid compile_id\n"); return -1; } sstate->loc_cs_map[lang->id] = lang->compile_id; sstate->cs_loc_map[lang->compile_id] = lang->id; fuh = open_memstream(&fuh_text, &fuh_size); prepare_unparse_unhandled_lang(fuh, lang); close_memstream(fuh); fuh = 0; if (fuh_text && *fuh_text) { lang->unhandled_vars = fuh_text; } else { xfree(fuh_text); } fuh_text = 0; fuh_size = 0; if (lang->compiler_env) { for (j = 0; lang->compiler_env[j]; j++) { if (!strncmp(lang->compiler_env[j], "EJUDGE_FLAGS=", 13)) { sstate->lang_opts[lang->id] = xstrmerge1(sstate->lang_opts[lang->id], lang->compiler_env[j] + 13); } } for (--j; j >= 0; --j) { if (!strncmp(lang->compiler_env[j], "EJUDGE_FLAGS=", 13)) { xfree(lang->compiler_env[j]); lang->compiler_env[j] = 0; for (k = j + 1; lang->compiler_env[k]; k++) { lang->compiler_env[k - 1] = lang->compiler_env[k]; } lang->compiler_env[k - 1] = lang->compiler_env[k]; } } } } // collect abstract problems for (pg = sstate->cfg, total = 0; pg; pg = pg->next) { if (!strcmp(pg->name, "problem") && (prob = (struct section_problem_data*) pg)->abstract) total++; } sstate->aprob_a = 0; sstate->aprob_u = 0; sstate->aprobs = 0; sstate->aprob_flags = 0; if (total) { sstate->aprob_a = 4; while (total > sstate->aprob_a) sstate->aprob_a *= 2; XCALLOC(sstate->aprobs, sstate->aprob_a); XCALLOC(sstate->aprob_flags, sstate->aprob_a); for (pg = sstate->cfg, i = 0; pg; pg = pg->next) { if (strcmp(pg->name, "problem") != 0) continue; prob = (struct section_problem_data*) pg; if (!prob->abstract) continue; sstate->aprobs[i++] = prob; if (!prob->short_name[0]) { fprintf(flog, "Abstract problem must have `short_name' field set\n"); return -1; } if (prob->super[0]) { fprintf(flog, "Abstract problem must not have a superproblem\n"); return -1; } if (prepare_check_forbidden_prob(flog, prob) < 0) return -1; prepare_set_abstr_problem_defaults(prob, global); fuh = open_memstream(&fuh_text, &fuh_size); prepare_unparse_unhandled_prob(fuh, prob, global); close_memstream(fuh); fuh = 0; if (fuh_text && *fuh_text) { prob->unhandled_vars = fuh_text; } else { xfree(fuh_text); } fuh_text = 0; fuh_size = 0; } ASSERT(i == total); sstate->aprob_u = total; } // collect concrete problems total = 0; cur_id = 0; for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "problem") != 0) continue; prob = (struct section_problem_data*) pg; if (prob->abstract) continue; if (!prob->id) prob->id = cur_id + 1; cur_id = prob->id; if (prob->id <= 0 || prob->id > EJ_MAX_PROB_ID) { fprintf(flog, "Invalid problem ID\n"); return -1; } if (prob->id >= total) total = prob->id + 1; } sstate->probs = 0; sstate->prob_a = 0; sstate->prob_flags = 0; if (total > 0) { sstate->prob_a = 4; while (total > sstate->prob_a) sstate->prob_a *= 2; XCALLOC(sstate->probs, sstate->prob_a); XCALLOC(sstate->prob_flags, sstate->prob_a); XALLOCAZ(prob_no_any, sstate->prob_a); for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "problem") != 0) continue; prob = (struct section_problem_data*) pg; if (prob->abstract) continue; if (sstate->probs[prob->id]) { fprintf(flog, "Duplicated problem id %d\n", prob->id); return -1; } sstate->probs[prob->id] = prob; if (prob->super[0]) { for (i = 0; i < sstate->aprob_u; i++) if (!strcmp(prob->super, sstate->aprobs[i]->short_name)) break; if (i == sstate->aprob_u) { fprintf(flog, "Abstract problem `%s' not found\n", prob->super); return -1; } } if (prepare_check_forbidden_prob(flog, prob) < 0) return -1; prepare_set_concr_problem_defaults(prob, global); fuh = open_memstream(&fuh_text, &fuh_size); prepare_unparse_unhandled_prob(fuh, prob, global); close_memstream(fuh); fuh = 0; if (fuh_text && *fuh_text) { prob->unhandled_vars = fuh_text; } else { xfree(fuh_text); } fuh_text = 0; fuh_size = 0; } } // collect abstract testers total = 0; for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "tester")) continue; tst = (struct section_tester_data*) pg; if (!tst->abstract) continue; // check, that we know such abstract tester if ((arch = prepare_unparse_is_supported_tester(tst->name)) < 0) { fprintf(flog, "Unsupported abstract tester `%s'\n", tst->name); return -1; } if ((i = prepare_unparse_is_supported_arch(tst->arch)) < 0) { fprintf(flog, "Unsupported tester architecture `%s'\n", tst->arch); return -1; } if (i != arch) { fprintf(flog, "Abstract tester name does not match tester arch\n"); return -1; } if (tst->id) { fprintf(flog, "Abstract tester must not define tester ID\n"); return -1; } if (tst->problem_name[0]) { fprintf(flog, "Abstract tester must not define problem name\n"); return -1; } if (tst->problem) { fprintf(flog, "Abstract tester must not define problem ID\n"); return -1; } total++; } /* Relax, try to work without testers... */ /* if (!total) { fprintf(flog, "No abstract testers defined\n"); return -1; } */ sstate->atester_total = total; if (total > 0) { XCALLOC(sstate->atesters, sstate->atester_total); for (pg = sstate->cfg, i = 0; pg; pg = pg->next) { if (strcmp(pg->name, "tester")) continue; tst = (struct section_tester_data*) pg; if (!tst->abstract) continue; sstate->atesters[i++] = tst; // FIXME: check for unhandled fields } } // collect concrete testers, attempting to recover vm limit, stack limit // and checker name total = 0; cur_id = 0; for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "tester") != 0) continue; tst = (struct section_tester_data*) pg; if (tst->abstract) continue; if (!tst->id) tst->id = cur_id + 1; cur_id = tst->id; if (tst->id <= 0 || tst->id > EJ_MAX_TESTER) { fprintf(flog, "Invalid tester ID\n"); return -1; } if (tst->id >= total) total = tst->id + 1; } sstate->tester_total = total; if (total > 0) { XCALLOC(sstate->testers, sstate->tester_total); } for (pg = sstate->cfg; pg; pg = pg->next) { if (strcmp(pg->name, "tester") != 0) continue; tst = (struct section_tester_data*) pg; if (tst->abstract) continue; if (sstate->testers[tst->id]) { fprintf(flog, "Duplicated tester ID %d\n", tst->id); return -1; } sstate->testers[tst->id] = tst; if (tst->super && tst->super[0] && tst->super[1]) { fprintf(flog, "Tester %d has several supertesters\n", tst->id); return -1; } atst = 0; if (tst->super) { for (i = 0; i < sstate->atester_total; i++) if (!strcmp(sstate->atesters[i]->name, tst->super[0])) break; if (i == sstate->atester_total) { fprintf(flog, "Abstract tester `%s' not found\n", tst->super[0]); return -1; } atst = sstate->atesters[i]; } if (tst->any) { continue; } prob = 0; if (tst->problem && tst->problem_name[0]) { fprintf(flog, "Both problem and problem_name fields cannot be set\n"); return -1; } else if (tst->problem) { if (tst->problem <= 0 || tst->problem >= sstate->prob_a || !sstate->probs[tst->problem]) { fprintf(flog, "problem %d is invalid\n", tst->problem); return -1; } prob = sstate->probs[tst->problem]; } else if (tst->problem_name[0]) { for (i = 1; i < sstate->prob_a; i++) if (sstate->probs[i] && !strcmp(sstate->probs[i]->short_name, tst->problem_name)) break; if (i == sstate->prob_a) { fprintf(flog, "Problem `%s' does not exist\n", tst->problem_name); return -1; } prob = sstate->probs[i]; } else { fprintf(flog, "Neither problem not problem_name are set\n"); return -1; } prob_no_any[prob->id] = 1; vm_size = tst->max_vm_size; if (vm_size == -1L && atst) vm_size = atst->max_vm_size; st_size = tst->max_stack_size; if (st_size == -1L && atst) st_size = atst->max_stack_size; if (vm_size != -1L) { if (prob->max_vm_size == -1L) prob->max_vm_size = vm_size; if (prob->max_vm_size != vm_size) { fprintf(flog, "Conflicting max_vm_size specifications for problem `%s'\n", prob->short_name); return -1; } } if (st_size != -1L) { if (prob->max_stack_size == -1L) prob->max_stack_size = st_size; if (prob->max_stack_size != st_size) { fprintf(flog, "Conflicting max_stack_size specifications for problem `%s'\n", prob->short_name); return -1; } } } for (i = 0; i < sstate->tester_total; i++) { if (!(tst = sstate->testers[i])) continue; atst = 0; if (tst->super) { for (j = 0; j < sstate->atester_total; j++) if (!strcmp(sstate->atesters[j]->name, tst->super[0])) break; if (j == sstate->atester_total) { fprintf(flog, "Abstract tester `%s' not found\n", tst->super[0]); return -1; } atst = sstate->atesters[j]; } if (!tst->any) continue; for (j = 0; j < sstate->prob_a; j++) { if (!(prob = sstate->probs[j])) continue; if (prob_no_any[j]) continue; vm_size = tst->max_vm_size; if (vm_size == -1L && atst) vm_size = atst->max_vm_size; st_size = tst->max_stack_size; if (st_size == -1L && atst) st_size = atst->max_stack_size; if (vm_size != -1L) { if (prob->max_vm_size == -1L) prob->max_vm_size = vm_size; if (prob->max_vm_size != vm_size) { fprintf(flog, "Conflicting max_vm_size specifications for problem `%s'\n", prob->short_name); return -1; } } if (st_size != -1L) { if (prob->max_stack_size == -1L) prob->max_stack_size = st_size; if (prob->max_stack_size != st_size) { fprintf(flog, "Conflicting max_stack_size specifications for problem `%s'\n", prob->short_name); return -1; } } } } XALLOCA(mem_lims, sstate->prob_a); XALLOCA(st_lims, sstate->prob_a); XALLOCA(mem_cnt, sstate->prob_a); XALLOCA(st_cnt, sstate->prob_a); // propagate most used memory limit to superproblem /* for (i = 0; i < sstate->aprob_u; i++) { aprob = sstate->aprobs[i]; mem_u = 0; st_u = 0; XMEMZERO(mem_cnt, sstate->prob_a); XMEMZERO(st_cnt, sstate->prob_a); for (j = 1; j < sstate->prob_a; j++) { if (!(prob = sstate->probs[j]) || !prob->super[0] || strcmp(prob->super, aprob->short_name)) continue; if (prob->max_vm_size != -1L) { for (k = 0; k < mem_u; k++) if (mem_lims[k] == prob->max_vm_size) break; if (k == mem_u) mem_u++; mem_lims[k] = prob->max_vm_size; mem_cnt[k]++; } if (prob->max_stack_size != -1L) { for (k = 0; k < st_u; k++) if (st_lims[k] == prob->max_stack_size) break; if (k == st_u) st_u++; st_lims[k] = prob->max_stack_size; st_cnt[k]++; } } if (mem_u > 0) { max_i = 0; for (i = 1; i < mem_u; i++) if (mem_cnt[i] > mem_cnt[max_i]) max_i = i; aprob->max_vm_size = mem_lims[max_i]; for (j = 1; j < sstate->prob_a; j++) { if (!(prob = sstate->probs[j]) || !prob->super[0] || strcmp(prob->super, aprob->short_name)) continue; if (prob->max_vm_size == -1L) { prob->max_vm_size = 0; } else if (prob->max_vm_size == aprob->max_vm_size) { prob->max_vm_size = -1L; } } } if (st_u > 0) { max_i = 0; for (i = 1; i < st_u; i++) if (st_cnt[i] > st_cnt[max_i]) max_i = i; aprob->max_stack_size = st_lims[max_i]; for (j = 1; j < sstate->prob_a; j++) { if (!(prob = sstate->probs[j]) || !prob->super[0] || strcmp(prob->super, aprob->short_name)) continue; if (prob->max_stack_size == -1L) { prob->max_stack_size = 0; } else if (prob->max_stack_size == aprob->max_stack_size) { prob->max_stack_size = -1L; } } } } */ // assign this check_cmd to all abstract problems without check_cmd for (i = 0; i < sstate->aprob_u; i++) if (!(aprob = sstate->aprobs[i])->check_cmd[0]) snprintf(aprob->check_cmd, sizeof(aprob->check_cmd), "%s", check_cmd); sstate->contest_start_cmd_text = do_load_file(conf_dir, global->contest_start_cmd); sstate->contest_stop_cmd_text = do_load_file(conf_dir, global->contest_stop_cmd); sstate->stand_header_text = do_load_file(conf_dir, global->stand_header_file); sstate->stand_footer_text = do_load_file(conf_dir, global->stand_footer_file); sstate->stand2_header_text = do_load_file(conf_dir, global->stand2_header_file); sstate->stand2_footer_text = do_load_file(conf_dir, global->stand2_footer_file); sstate->plog_header_text = do_load_file(conf_dir, global->plog_header_file); sstate->plog_footer_text = do_load_file(conf_dir, global->plog_footer_file); return 0; }