From b25850f25b4d1a0bb4a1a8709dc019e5fab21b96 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 6 Jan 2025 19:34:41 +0100 Subject: [PATCH] MINOR: tools: add a few functions to simply check for a file's existence At many places we'd like to be able to simply construct a path from a format string and check if that path corresponds to an existing file, directory etc. Here we add 3 functions, a generic one to test that a path corresponds to a given file mode (e.g. S_IFDIR, S_IFREG etc), and two other ones specifically checking for a file or a dir for easier use. --- include/haproxy/tools.h | 3 ++ src/tools.c | 64 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index ef2f5c4ec..b96436115 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -1020,6 +1020,9 @@ int my_unsetenv(const char *name); * some expansion is made. */ char *env_expand(char *in); +int is_path_mode(mode_t mode, const char *path_fmt, ...); +int is_file_present(const char *path_fmt, ...); +int is_dir_present(const char *path_fmt, ...); uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbargs, uint32_t opts, const char **errptr); ssize_t read_line_to_trash(const char *path_fmt, ...); size_t sanitize_for_printing(char *line, size_t pos, size_t width); diff --git a/src/tools.c b/src/tools.c index 472baf919..5524ae7e0 100644 --- a/src/tools.c +++ b/src/tools.c @@ -5975,6 +5975,70 @@ void ha_generate_uuid_v7(struct buffer *output) } +/* See is_path_mode(). This version is for internal use and uses a va_list. */ +static int _is_path_mode(mode_t mode, const char *path_fmt, va_list args) +{ + struct stat file_stat; + ssize_t ret; + + chunk_reset(&trash); + + ret = vsnprintf(trash.area, trash.size, path_fmt, args); + if (ret >= trash.size) + return 0; + + if (stat(trash.area, &file_stat) != 0) + return 0; + + return (file_stat.st_mode & S_IFMT) == mode; +} + +/* Use and following arguments as a printf format to build up the + * name of a file, which will be checked for existence and for mode matching + * among S_IF*. On success, non-zero is returned. On failure, zero is + * returned. The trash is destroyed. + */ +int is_path_mode(mode_t mode, const char *path_fmt, ...) +{ + va_list args; + int ret; + + va_start(args, path_fmt); + ret = _is_path_mode(mode, path_fmt, args); + va_end(args); + return ret; +} + +/* Use and following arguments as a printf format to build up the + * name of a file, which will be checked for existence. On success, non-zero + * is returned. On failure, zero is returned. The trash is destroyed. + */ +int is_file_present(const char *path_fmt, ...) +{ + va_list args; + int ret; + + va_start(args, path_fmt); + ret = _is_path_mode(S_IFREG, path_fmt, args); + va_end(args); + return ret; +} + +/* Use and following arguments as a printf format to build up the + * name of a directory, which will be checked for existence. On success, non-zero + * is returned. On failure, zero is returned. The trash is destroyed. + */ +int is_dir_present(const char *path_fmt, ...) +{ + va_list args; + int ret; + + va_start(args, path_fmt); + ret = _is_path_mode(S_IFDIR, path_fmt, args); + va_end(args); + return ret; +} + /* only used by parse_line() below. It supports writing in place provided that * is updated to the next location before calling it. In that case, the * char at may be overwritten.