int file_size(char *file) { struct stat st; file = check_valid_path(file, current_object, "file_size", 0); if (!file) return -1; if (file[0] == '/') file++; if (!legal_path(file)) return -1; #ifdef PURIFY (void)memset(&st, '\0', sizeof(st)); #endif if (stat(file, &st) == -1) return -1; if (S_IFDIR & st.st_mode) return -2; return (int)st.st_size; }
/* * Check that a path to a file is valid for read or write. * This is done by functions in the master object. * The path is always treated as an absolute path, and is returned without * a leading '/'. * If the path was '/', then '.' is returned. * Otherwise, the returned path is temporarily allocated by apply(), which * means it will be deallocated at next apply(). */ const char *check_valid_path (const char * path, object_t * call_object, const char * const call_fun, int writeflg) { svalue_t *v; if(!master_ob && !call_object){ //early startup, ignore security extern svalue_t apply_ret_value; free_svalue(&apply_ret_value, "check_valid_path"); apply_ret_value.type = T_STRING; apply_ret_value.subtype = STRING_MALLOC; path = apply_ret_value.u.string = string_copy(path, "check_valid_path"); return path; } if (call_object == 0 || call_object->flags & O_DESTRUCTED) return 0; #ifdef WIN32 { char *p; for(p=path; *p; p++) if (*p == '\\') *p='/'; } #endif copy_and_push_string(path); push_object(call_object); push_constant_string(call_fun); if (writeflg) v = apply_master_ob(APPLY_VALID_WRITE, 3); else v = apply_master_ob(APPLY_VALID_READ, 3); if (v == (svalue_t *)-1) v = 0; if (v && v->type == T_NUMBER && v->u.number == 0) return 0; if (v && v->type == T_STRING) { path = v->u.string; } else { extern svalue_t apply_ret_value; free_svalue(&apply_ret_value, "check_valid_path"); apply_ret_value.type = T_STRING; apply_ret_value.subtype = STRING_MALLOC; path = apply_ret_value.u.string = string_copy(path, "check_valid_path"); } if (path[0] == '/') path++; if (path[0] == '\0') path = "."; if (legal_path(path)) return path; return 0; }
/* Set the global list of include directories. Affects globals inc_list and inc_list_size */ void set_inc_list(struct svalue *sv) { int i; struct vector *v; char *p, *end; char **tmp_inc_list; free_inc_list(); if (sv == 0) { inc_list_size = 0; inc_list = NULL; return; } if (sv->type != T_POINTER) { (void)fprintf(stderr, "'define_include_dirs' in master.c did not return an array.\n"); exit(1); inc_list_size = 0; inc_list = NULL; return; } v = sv->u.vec; if (v->size == 0) { (void)fprintf(stderr, "'define_include_dirs' returned an empty array\n"); inc_list_size = 0; inc_list = NULL; return; } tmp_inc_list = (char **) xalloc(v->size * sizeof (char *)); inc_list_size = 0; for (i = 0; i < v->size; i++) { if (v->item[i].type != T_STRING) { (void)fprintf(stderr, "Illegal value returned from 'define_include_dirs' in master.c\n"); continue; } p = v->item[i].u.string; if (*p == '/') p++; /* * Even make sure that the game administrator has not made an error. */ if (!legal_path(p)) { (void)fprintf(stderr, "'define_include_dirs' must give paths without any '..'\n"); continue; } if ((end = strstr(p, "%s"))) { if (end != p + strlen(p) - 2) { (void)fprintf(stderr, "'define_include_dirs' may only contain %%s last."); continue; } } else end = p + strlen(p); if (end != p && end[-1] != '/') { tmp_inc_list[inc_list_size] = xalloc(end - p + 2); strncpy(tmp_inc_list[inc_list_size], p, end - p); tmp_inc_list[inc_list_size][end - p] = '/'; tmp_inc_list[inc_list_size][end - p + 1] = '\0'; } else { tmp_inc_list[inc_list_size] = xalloc(end - p + 1); strncpy(tmp_inc_list[inc_list_size], p, end - p); tmp_inc_list[inc_list_size][end - p] = '\0'; } inc_list_size++; } if (inc_list_size == 0) { inc_list = NULL; free(tmp_inc_list); } else if (inc_list_size != v->size) { inc_list = (char **) xalloc(inc_list_size * sizeof (char *)); for (i = 0; i < inc_list_size; i++) inc_list[i] = tmp_inc_list[i]; free(tmp_inc_list); } else inc_list = tmp_inc_list; }