/* Helper for disk_state_load_from_disk(). */ STATIC int disk_state_load_from_disk_impl(const char *fname) { int ret; char *content = NULL; sr_state_t *parsed_state = NULL; sr_disk_state_t *disk_state = NULL; /* Read content of file so we can parse it. */ if ((content = read_file_to_str(fname, 0, NULL)) == NULL) { log_warn(LD_FS, "SR: Unable to read SR state file %s", escaped(fname)); ret = -errno; goto error; } { config_line_t *lines = NULL; char *errmsg = NULL; /* Every error in this code path will return EINVAL. */ ret = -EINVAL; if (config_get_lines(content, &lines, 0) < 0) { config_free_lines(lines); goto error; } disk_state = disk_state_new(time(NULL)); config_assign(&state_format, disk_state, lines, 0, &errmsg); config_free_lines(lines); if (errmsg) { log_warn(LD_DIR, "SR: Reading state error: %s", errmsg); tor_free(errmsg); goto error; } } /* So far so good, we've loaded our state file into our disk state. Let's * validate it and then parse it. */ if (disk_state_validate(disk_state) < 0) { ret = -EINVAL; goto error; } parsed_state = disk_state_parse(disk_state); if (parsed_state == NULL) { ret = -EINVAL; goto error; } state_set(parsed_state); disk_state_set(disk_state); tor_free(content); log_info(LD_DIR, "SR: State loaded successfully from file %s", fname); return 0; error: disk_state_free(disk_state); tor_free(content); return ret; }
/** Reload the persistent state from disk, generating a new state as needed. * Return 0 on success, less than 0 on failure. */ int or_state_load(void) { or_state_t *new_state = NULL; char *contents = NULL, *fname; char *errmsg = NULL; int r = -1, badstate = 0; fname = get_datadir_fname("state"); switch (file_status(fname)) { case FN_FILE: if (!(contents = read_file_to_str(fname, 0, NULL))) { log_warn(LD_FS, "Unable to read state file \"%s\"", fname); goto done; } break; case FN_NOENT: break; case FN_ERROR: case FN_DIR: default: log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname); goto done; } new_state = tor_malloc_zero(sizeof(or_state_t)); new_state->_magic = OR_STATE_MAGIC; config_init(&state_format, new_state); if (contents) { config_line_t *lines=NULL; int assign_retval; if (config_get_lines(contents, &lines, 0)<0) goto done; assign_retval = config_assign(&state_format, new_state, lines, 0, 0, &errmsg); config_free_lines(lines); if (assign_retval<0) badstate = 1; if (errmsg) { log_warn(LD_GENERAL, "%s", errmsg); tor_free(errmsg); } } if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0) badstate = 1; if (errmsg) { log_warn(LD_GENERAL, "%s", errmsg); tor_free(errmsg); } if (badstate && !contents) { log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state." " This is a bug in Tor."); goto done; } else if (badstate && contents) { or_state_save_broken(fname); tor_free(contents); config_free(&state_format, new_state); new_state = tor_malloc_zero(sizeof(or_state_t)); new_state->_magic = OR_STATE_MAGIC; config_init(&state_format, new_state); } else if (contents) { log_info(LD_GENERAL, "Loaded state from \"%s\"", fname); } else { log_info(LD_GENERAL, "Initialized state"); } if (or_state_set(new_state) == -1) { or_state_save_broken(fname); } new_state = NULL; if (!contents) { global_state->next_write = 0; or_state_save(time(NULL)); } r = 0; done: tor_free(fname); tor_free(contents); if (new_state) config_free(&state_format, new_state); return r; }