static config_file_t *config_file_new_internal( const char *path, unsigned depth, config_file_cb_t *cb) { RFILE *file = NULL; struct config_file *conf = (struct config_file*)malloc(sizeof(*conf)); if (!conf) return NULL; conf->path = NULL; conf->entries = NULL; conf->tail = NULL; conf->last = NULL; conf->includes = NULL; conf->include_depth = 0; conf->guaranteed_no_duplicates = false ; if (!path || !*path) return conf; if (path_is_directory(path)) goto error; conf->path = strdup(path); if (!conf->path) goto error; conf->include_depth = depth; file = filestream_open(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) { free(conf->path); goto error; } while (!filestream_eof(file)) { char *line = NULL; struct config_entry_list *list = (struct config_entry_list*)malloc(sizeof(*list)); if (!list) { config_file_free(conf); filestream_close(file); return NULL; } list->readonly = false; list->key = NULL; list->value = NULL; list->next = NULL; line = filestream_getline(file); if (!line) { free(list); continue; } if (*line && parse_line(conf, list, line, cb)) { if (conf->entries) conf->tail->next = list; else conf->entries = list; conf->tail = list; if (cb != NULL && list->key != NULL && list->value != NULL) cb->config_file_new_entry_cb(list->key, list->value) ; } free(line); if (list != conf->tail) free(list); } filestream_close(file); return conf; error: free(conf); return NULL; }
int rfeof(RFILE* stream) { return filestream_eof(stream); }
/* Parses log file referenced by runtime_log->path. * Does nothing if log file does not exist. */ static void runtime_log_read_file(runtime_log_t *runtime_log) { unsigned runtime_hours = 0; unsigned runtime_minutes = 0; unsigned runtime_seconds = 0; unsigned last_played_year = 0; unsigned last_played_month = 0; unsigned last_played_day = 0; unsigned last_played_hour = 0; unsigned last_played_minute = 0; unsigned last_played_second = 0; RtlJSONContext context = {0}; RFILE *file = NULL; int ret = 0; /* Check if log file exists */ if (!filestream_exists(runtime_log->path)) return; /* Attempt to open log file */ file = filestream_open(runtime_log->path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) { RARCH_ERR("Failed to open runtime log file: %s\n", runtime_log->path); return; } /* Initialise JSON parser */ context.runtime_string = NULL; context.last_played_string = NULL; context.parser = JSON_Parser_Create(NULL); context.file = file; if (!context.parser) { RARCH_ERR("Failed to create JSON parser.\n"); goto end; } /* Configure parser */ JSON_Parser_SetAllowBOM(context.parser, JSON_True); JSON_Parser_SetStringHandler(context.parser, &RtlJSONStringHandler); JSON_Parser_SetObjectMemberHandler(context.parser, &RtlJSONObjectMemberHandler); JSON_Parser_SetUserData(context.parser, &context); /* Read file */ while (!filestream_eof(file)) { /* Runtime log files are tiny - use small chunk size */ char chunk[128] = {0}; int64_t length = filestream_read(file, chunk, sizeof(chunk)); /* Error checking... */ if (!length && !filestream_eof(file)) { RARCH_ERR("Failed to read runtime log file: %s\n", runtime_log->path); JSON_Parser_Free(context.parser); goto end; } /* Parse chunk */ if (!JSON_Parser_Parse(context.parser, chunk, length, JSON_False)) { RARCH_ERR("Error parsing chunk of runtime log file: %s\n---snip---\n%s\n---snip---\n", runtime_log->path, chunk); RtlJSONLogError(&context); JSON_Parser_Free(context.parser); goto end; } } /* Finalise parsing */ if (!JSON_Parser_Parse(context.parser, NULL, 0, JSON_True)) { RARCH_WARN("Error parsing runtime log file: %s\n", runtime_log->path); RtlJSONLogError(&context); JSON_Parser_Free(context.parser); goto end; } /* Free parser */ JSON_Parser_Free(context.parser); /* Process string values read from JSON file */ /* Runtime */ ret = 0; if (!string_is_empty(context.runtime_string)) ret = sscanf(context.runtime_string, LOG_FILE_RUNTIME_FORMAT_STR, &runtime_hours, &runtime_minutes, &runtime_seconds); if (ret != 3) { RARCH_ERR("Runtime log file - invalid 'runtime' entry detected: %s\n", runtime_log->path); goto end; } /* Last played */ ret = 0; if (!string_is_empty(context.last_played_string)) ret = sscanf(context.last_played_string, LOG_FILE_LAST_PLAYED_FORMAT_STR, &last_played_year, &last_played_month, &last_played_day, &last_played_hour, &last_played_minute, &last_played_second); if (ret != 6) { RARCH_ERR("Runtime log file - invalid 'last played' entry detected: %s\n", runtime_log->path); goto end; } /* If we reach this point then all is well * > Assign values to runtime_log object */ runtime_log->runtime.hours = runtime_hours; runtime_log->runtime.minutes = runtime_minutes; runtime_log->runtime.seconds = runtime_seconds; runtime_log->last_played.year = last_played_year; runtime_log->last_played.month = last_played_month; runtime_log->last_played.day = last_played_day; runtime_log->last_played.hour = last_played_hour; runtime_log->last_played.minute = last_played_minute; runtime_log->last_played.second = last_played_second; end: /* Clean up leftover strings */ if (context.runtime_string) free(context.runtime_string); if (context.last_played_string) free(context.last_played_string); /* Close log file */ filestream_close(file); }