// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2018 Jan Stancek */ #include #include #include #include #define TST_NO_DEFAULT_MAIN #include "tst_test.h" #include "tst_sys_conf.h" struct tst_sys_conf { char path[PATH_MAX]; char value[PATH_MAX]; struct tst_sys_conf *next; }; static struct tst_sys_conf *save_restore_data; static void print_error(const int lineno, int info_only, const char *err, const char *path) { if (info_only) tst_res_(__FILE__, lineno, TINFO | TERRNO, err, path); else tst_brk_(__FILE__, lineno, TBROK | TERRNO, err, path); } void tst_sys_conf_dump(void) { struct tst_sys_conf *i; for (i = save_restore_data; i; i = i->next) tst_res(TINFO, "%s = %s", i->path, i->value); } void tst_sys_conf_save_str(const char *path, const char *value) { struct tst_sys_conf *n = SAFE_MALLOC(sizeof(*n)); strncpy(n->path, path, sizeof(n->path)-1); strncpy(n->value, value, sizeof(n->value)-1); n->path[sizeof(n->path) - 1] = 0; n->value[sizeof(n->value) - 1] = 0; n->next = save_restore_data; save_restore_data = n; } int tst_sys_conf_save(const struct tst_path_val *conf) { char line[PATH_MAX]; int ttype, iret; FILE *fp; void *ret; if (!conf || !conf->path) tst_brk(TBROK, "path is empty"); if (access(conf->path, F_OK) != 0) { if (conf->flags & TST_SR_SKIP_MISSING) { tst_res(TINFO | TERRNO, "Path not found: %s", conf->path); return 1; } ttype = (conf->flags & TST_SR_TBROK_MISSING) ? TBROK : TCONF; tst_brk(ttype | TERRNO, "Path not found: %s", conf->path); } if (access(conf->path, W_OK) != 0) { if (conf->flags & TST_SR_SKIP_RO) { tst_res(TINFO | TERRNO, "Path is not writable: %s", conf->path); return 1; } ttype = (conf->flags & TST_SR_TBROK_RO) ? TBROK : TCONF; tst_brk(ttype | TERRNO, "Path is not writable: %s", conf->path); } fp = fopen(conf->path, "r"); if (fp == NULL) { print_error(__LINE__, conf->flags & TST_SR_IGNORE_ERR, "Failed to open '%s' for reading", conf->path); return 1; } ret = fgets(line, sizeof(line), fp); fclose(fp); if (ret == NULL) { if (conf->flags & TST_SR_IGNORE_ERR) return 1; tst_brk(TBROK | TERRNO, "Failed to read anything from '%s'", conf->path); } tst_sys_conf_save_str(conf->path, line); if (!conf->val) return 0; fp = fopen(conf->path, "w"); if (fp == NULL) { print_error(__LINE__, conf->flags & TST_SR_IGNORE_ERR, "Failed to open '%s' for writing", conf->path); return 0; } iret = fputs(conf->val, fp); if (iret < 0) { print_error(__LINE__, conf->flags & TST_SR_IGNORE_ERR, "Failed to write into '%s'", conf->path); } iret = fclose(fp); if (iret < 0) { print_error(__LINE__, conf->flags & TST_SR_IGNORE_ERR, "Failed to close '%s'", conf->path); } return 0; } void tst_sys_conf_restore(int verbose) { struct tst_sys_conf *i; for (i = save_restore_data; i; i = i->next) { if (verbose) { tst_res(TINFO, "Restoring conf.: %s -> %s\n", i->path, i->value); } FILE_PRINTF(i->path, "%s", i->value); } }