]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - tools/perf/util/util.c
perf tools: Add perf_exe() helper to find perf binary
[linux.git] / tools / perf / util / util.c
index 093352e93d50674e17ddfe7146658d3bfe86dbac..d388f80d8703e914b2ce9040c340135286b7d921 100644 (file)
@@ -2,6 +2,7 @@
 #include "../perf.h"
 #include "util.h"
 #include "debug.h"
+#include "namespaces.h"
 #include <api/fs/fs.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -20,6 +21,7 @@
 #include <linux/time64.h>
 #include <unistd.h>
 #include "strlist.h"
+#include "string2.h"
 
 /*
  * XXX We need to find a better place for these things...
@@ -116,23 +118,67 @@ int mkdir_p(char *path, mode_t mode)
        return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
 }
 
-int rm_rf(const char *path)
+static bool match_pat(char *file, const char **pat)
+{
+       int i = 0;
+
+       if (!pat)
+               return true;
+
+       while (pat[i]) {
+               if (strglobmatch(file, pat[i]))
+                       return true;
+
+               i++;
+       }
+
+       return false;
+}
+
+/*
+ * The depth specify how deep the removal will go.
+ * 0       - will remove only files under the 'path' directory
+ * 1 .. x  - will dive in x-level deep under the 'path' directory
+ *
+ * If specified the pat is array of string patterns ended with NULL,
+ * which are checked upon every file/directory found. Only matching
+ * ones are removed.
+ *
+ * The function returns:
+ *    0 on success
+ *   -1 on removal failure with errno set
+ *   -2 on pattern failure
+ */
+static int rm_rf_depth_pat(const char *path, int depth, const char **pat)
 {
        DIR *dir;
-       int ret = 0;
+       int ret;
        struct dirent *d;
        char namebuf[PATH_MAX];
+       struct stat statbuf;
 
+       /* Do not fail if there's no file. */
+       ret = lstat(path, &statbuf);
+       if (ret)
+               return 0;
+
+       /* Try to remove any file we get. */
+       if (!(statbuf.st_mode & S_IFDIR))
+               return unlink(path);
+
+       /* We have directory in path. */
        dir = opendir(path);
        if (dir == NULL)
-               return 0;
+               return -1;
 
        while ((d = readdir(dir)) != NULL && !ret) {
-               struct stat statbuf;
 
                if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
                        continue;
 
+               if (!match_pat(d->d_name, pat))
+                       return -2;
+
                scnprintf(namebuf, sizeof(namebuf), "%s/%s",
                          path, d->d_name);
 
@@ -144,7 +190,7 @@ int rm_rf(const char *path)
                }
 
                if (S_ISDIR(statbuf.st_mode))
-                       ret = rm_rf(namebuf);
+                       ret = depth ? rm_rf_depth_pat(namebuf, depth - 1, pat) : 0;
                else
                        ret = unlink(namebuf);
        }
@@ -156,6 +202,22 @@ int rm_rf(const char *path)
        return rmdir(path);
 }
 
+int rm_rf_perf_data(const char *path)
+{
+       const char *pat[] = {
+               "header",
+               "data.*",
+               NULL,
+       };
+
+       return rm_rf_depth_pat(path, 0, pat);
+}
+
+int rm_rf(const char *path)
+{
+       return rm_rf_depth_pat(path, INT_MAX, NULL);
+}
+
 /* A filter which removes dot files */
 bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
 {
@@ -506,3 +568,13 @@ const char *perf_tip(const char *dirpath)
 
        return tip;
 }
+
+char *perf_exe(char *buf, int len)
+{
+       int n = readlink("/proc/self/exe", buf, len);
+       if (n > 0) {
+               buf[n] = 0;
+               return buf;
+       }
+       return strcpy(buf, "perf");
+}