diff options
Diffstat (limited to 'tools/perf/util/path.c')
| -rw-r--r-- | tools/perf/util/path.c | 168 |
1 files changed, 45 insertions, 123 deletions
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c index a8c49548ca48..2e62f272fda8 100644 --- a/tools/perf/util/path.c +++ b/tools/perf/util/path.c @@ -1,48 +1,14 @@ -/* - * I'm tired of doing "vsnprintf()" etc just to open a - * file, so here's a "return static buffer with printf" - * interface for paths. - * - * It's obviously not thread-safe. Sue me. But it's quite - * useful for doing things like - * - * f = open(mkpath("%s/%s.perf", base, name), O_RDONLY); - * - * which is what it's designed for. - */ +// SPDX-License-Identifier: GPL-2.0 +#include "path.h" #include "cache.h" - -static char bad_path[] = "/bad-path/"; -/* - * Two hacks: - */ - -static const char *get_perf_dir(void) -{ - return "."; -} - -#ifndef HAVE_STRLCPY -size_t strlcpy(char *dest, const char *src, size_t size) -{ - size_t ret = strlen(src); - - if (size) { - size_t len = (ret >= size) ? size - 1 : ret; - memcpy(dest, src, len); - dest[len] = '\0'; - } - return ret; -} -#endif - -static char *get_pathname(void) -{ - static char pathname_array[4][PATH_MAX]; - static int idx; - - return pathname_array[3 & ++idx]; -} +#include <linux/kernel.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> static char *cleanup_path(char *path) { @@ -55,103 +21,59 @@ static char *cleanup_path(char *path) return path; } -static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args) +char *mkpath(char *path_buf, size_t sz, const char *fmt, ...) { - const char *perf_dir = get_perf_dir(); - size_t len; - - len = strlen(perf_dir); - if (n < len + 1) - goto bad; - memcpy(buf, perf_dir, len); - if (len && !is_dir_sep(perf_dir[len-1])) - buf[len++] = '/'; - len += vsnprintf(buf + len, n - len, fmt, args); - if (len >= n) - goto bad; - return cleanup_path(buf); -bad: - strlcpy(buf, bad_path, n); - return buf; -} - -char *perf_pathdup(const char *fmt, ...) -{ - char path[PATH_MAX]; va_list args; + unsigned len; + va_start(args, fmt); - (void)perf_vsnpath(path, sizeof(path), fmt, args); + len = vsnprintf(path_buf, sz, fmt, args); va_end(args); - return xstrdup(path); + if (len >= sz) + strncpy(path_buf, "/bad-path/", sz); + return cleanup_path(path_buf); } -char *mkpath(const char *fmt, ...) +int path__join(char *bf, size_t size, const char *path1, const char *path2) { - va_list args; - unsigned len; - char *pathname = get_pathname(); + return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2); +} - va_start(args, fmt); - len = vsnprintf(pathname, PATH_MAX, fmt, args); - va_end(args); - if (len >= PATH_MAX) - return bad_path; - return cleanup_path(pathname); +int path__join3(char *bf, size_t size, const char *path1, const char *path2, const char *path3) +{ + return scnprintf(bf, size, "%s%s%s%s%s", path1, path1[0] ? "/" : "", + path2, path2[0] ? "/" : "", path3); } -char *perf_path(const char *fmt, ...) +bool is_regular_file(const char *file) { - const char *perf_dir = get_perf_dir(); - char *pathname = get_pathname(); - va_list args; - unsigned len; + struct stat st; - len = strlen(perf_dir); - if (len > PATH_MAX-100) - return bad_path; - memcpy(pathname, perf_dir, len); - if (len && perf_dir[len-1] != '/') - pathname[len++] = '/'; - va_start(args, fmt); - len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args); - va_end(args); - if (len >= PATH_MAX) - return bad_path; - return cleanup_path(pathname); + if (stat(file, &st)) + return false; + + return S_ISREG(st.st_mode); } -/* strip arbitrary amount of directory separators at end of path */ -static inline int chomp_trailing_dir_sep(const char *path, int len) +/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */ +bool is_directory(const char *base_path, const struct dirent *dent) { - while (len && is_dir_sep(path[len - 1])) - len--; - return len; + char path[PATH_MAX]; + struct stat st; + + snprintf(path, sizeof(path), "%s/%s", base_path, dent->d_name); + if (stat(path, &st)) + return false; + + return S_ISDIR(st.st_mode); } -/* - * If path ends with suffix (complete path components), returns the - * part before suffix (sans trailing directory separators). - * Otherwise returns NULL. - */ -char *strip_path_suffix(const char *path, const char *suffix) +bool is_directory_at(int dir_fd, const char *path) { - int path_len = strlen(path), suffix_len = strlen(suffix); + struct stat st; - while (suffix_len) { - if (!path_len) - return NULL; - - if (is_dir_sep(path[path_len - 1])) { - if (!is_dir_sep(suffix[suffix_len - 1])) - return NULL; - path_len = chomp_trailing_dir_sep(path, path_len); - suffix_len = chomp_trailing_dir_sep(suffix, suffix_len); - } - else if (path[--path_len] != suffix[--suffix_len]) - return NULL; - } + if (fstatat(dir_fd, path, &st, /*flags=*/0)) + return false; - if (path_len && !is_dir_sep(path[path_len - 1])) - return NULL; - return strndup(path, chomp_trailing_dir_sep(path, path_len)); + return S_ISDIR(st.st_mode); } |
