summaryrefslogtreecommitdiff
path: root/tools/perf/util/path.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/path.c')
-rw-r--r--tools/perf/util/path.c168
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);
}