From 4dd14dac422e0ef93af49a3bca3727310cdd3b92 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 11 Jun 2023 13:19:05 +0200 Subject: [PATCH] New helper functions to read/write /proc and /sys style files From the Infix project. Signed-off-by: Joachim Wiberg --- src/Makefile.am | 2 +- src/lite.h | 10 +++ src/procval.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 src/procval.c diff --git a/src/Makefile.am b/src/Makefile.am index c9b8eac..b2180d2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ libite_la_SOURCES = chomp.c copyfile.c \ fexist.c fisdir.c \ fparseln.c fsendfile.c \ ifconfig.c lfile.c \ - makepath.c progress.c \ + makepath.c procval.c progress.c \ pidfile.c pidfilefn.c popenf.c \ reallocarray.c rsync.c strtrim.c \ strlcpy.c strlcat.c strtonum.c \ diff --git a/src/lite.h b/src/lite.h index bf50204..8420b75 100644 --- a/src/lite.h +++ b/src/lite.h @@ -90,6 +90,16 @@ int fcopyfile (FILE *src, FILE *dst); ssize_t fsendfile (FILE *src, FILE *dst, size_t len); int truncatef (off_t length, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +char *vreadsnf (char *line, size_t len, const char *fmt, va_list ap); +char *readsnf (char *line, size_t len, const char *fmt, ...); +int writesf (const char *str, const char *mode, const char *fmt, ...); + +int vreadllf (long long *value, const char *fmt, va_list ap); +int readllf (long long *value, const char *fmt, ...); +int readdf (int *value, const char *fmt, ...); +int writellf (long long value, const char *mode, const char *fmt, ...); +int writedf (int value, const char *mode, const char *fmt, ...); + int ifconfig (const char *ifname, const char *addr, const char *mask, int up); lfile_t*lfopen (const char *file, const char *sep); diff --git a/src/procval.c b/src/procval.c new file mode 100644 index 0000000..700ff88 --- /dev/null +++ b/src/procval.c @@ -0,0 +1,229 @@ +/* Reading and writing values/strings to/from /proc and /sys style files + * + * Copyright (c) 2023 Tobias Waldekranz + * Copyright (c) 2023 Joachim Wiberg + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * @file procval.c + * @author Joachim Wiberg + * @date 2023 + * @copyright ISC License + */ + +#include +#include +#include +#include + +#include "lite.h" + +/** + * Similar to readsnf() except it takes a @a va_list argument + * @param line Pointer to line buffer. + * @param len Size of line buffer. + * @param fmt Formatted string to be composed into a pathname. + * @param ap List of variable arguemnts from va_start(). + * + * For details, see readsnf(). + * + * @returns same as readsnf(). + */ +char *vreadsnf(char *line, size_t len, const char *fmt, va_list ap) +{ + va_list apc; + FILE *fp; + + va_copy(apc, ap); + fp = vfopenf("r", fmt, ap); + va_end(ap); + if (!fp) + return NULL; + + if (!fgets(line, len, fp)) { + fclose(fp); + return NULL; + } + + fclose(fp); + return chomp(line); +} + + +/** + * Read first line from a file composed from fmt and optional args. + * @param line Pointer to line buffer. + * @param len Size of line buffer. + * @param fmt Formatted string to be composed into a pathname. + * + * @returns On success, this function returns the @p line read from the + * file, with any trailing '\n' chomp()ed out. On error, @c NULL. + */ +char *readsnf(char *line, size_t len, const char *fmt, ...) +{ + va_list ap; + char *ln; + + va_start(ap, fmt); + ln = vreadsnf(line, len, fmt, ap); + va_end(ap); + + return ln; +} + +/** + * Write a string buffer to a file composed from fmt and optional args. + * @param str Pointer to string buffer, may be multiple lines. + * @param mode An fopen() mode string, e.g. "w+". + * @param fmt Formatted string to be composed into a pathname. + * + * @returns result of operation, with @a errno set on error. + */ +int writesf(const char *str, const char *mode, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + va_start(ap, fmt); + fp = vfopenf(mode, fmt, ap); + va_end(ap); + if (!fp) + return -1; + + fprintf(fp, "%s\n", str); + return fclose(fp); +} + +/** + * Same as readllf() exectp it takes a @a va_list argument. + */ +int vreadllf(long long *value, const char *fmt, va_list ap) +{ + char line[0x100]; + + if (!vreadsnf(line, sizeof(line), fmt, ap)) + return -1; + + errno = 0; + *value = strtoll(line, NULL, 0); + + return errno ? -1 : 0; +} + +/** + * Read 64-bit integer value from a file composed from fmt and optional args. + * @param value Pointer to where to store read 64-bit integer value. + * @param mode An fopen() mode string, e.g. "w+". + * @param fmt Formatted string to be composed into a pathname. + * + * @returns result of operation, with @a errno set on error. + */ +int readllf(long long *value, const char *fmt, ...) +{ + va_list ap; + int rc; + + va_start(ap, fmt); + rc = vreadllf(value, fmt, ap); + va_end(ap); + + return rc; +} + + +/** + * Read integer value from a file composed from fmt and optional args. + * @param value Pointer to where to store read integer value. + * @param mode An fopen() mode string, e.g. "w+". + * @param fmt Formatted string to be composed into a pathname. + * + * @returns result of operation, with @a errno set on error. + */ +int readdf(int *value, const char *fmt, ...) +{ + long long tmp; + va_list ap; + int rc; + + va_start(ap, fmt); + rc = vreadllf(&tmp, fmt, ap); + va_end(ap); + + if (rc) + return rc; + + if (tmp < INT_MIN || tmp > INT_MAX) { + errno = ERANGE; + return -1; + } + + *value = tmp; + return 0; +} + +/** + * Write 64-bit integer value to a file composed from fmt and optional args. + * @param value 64-bit integer value to write. + * @param mode An fopen() mode string, e.g. "w+". + * @param fmt Formatted string to be composed into a pathname. + * + * @returns result of operation, with @a errno set on error. + */ +int writellf(long long value, const char *mode, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + va_start(ap, fmt); + fp = vfopenf(mode, fmt, ap); + va_end(ap); + if (!fp) + return -1; + + fprintf(fp, "%lld\n", value); + return fclose(fp); +} + + +/** + * Write integer value to a file composed from fmt and optional args. + * @param value Integer value to write. + * @param mode An fopen() mode string, e.g. "w+". + * @param fmt Formatted string to be composed into a pathname. + * + * @returns result of operation, with @a errno set on error. + */ +int writedf(int value, const char *mode, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + va_start(ap, fmt); + fp = vfopenf(mode, fmt, ap); + va_end(ap); + if (!fp) + return -1; + + fprintf(fp, "%d\n", value); + return fclose(fp); +} + + +/** + * Local Variables: + * indent-tabs-mode: t + * c-file-style: "linux" + * End: + */