~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to tools/perf/util/path.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * I'm tired of doing "vsnprintf()" etc just to open a
 
3
 * file, so here's a "return static buffer with printf"
 
4
 * interface for paths.
 
5
 *
 
6
 * It's obviously not thread-safe. Sue me. But it's quite
 
7
 * useful for doing things like
 
8
 *
 
9
 *   f = open(mkpath("%s/%s.perf", base, name), O_RDONLY);
 
10
 *
 
11
 * which is what it's designed for.
 
12
 */
 
13
#include "cache.h"
 
14
 
 
15
static char bad_path[] = "/bad-path/";
 
16
/*
 
17
 * Two hacks:
 
18
 */
 
19
 
 
20
static const char *get_perf_dir(void)
 
21
{
 
22
        return ".";
 
23
}
 
24
 
 
25
#ifdef NO_STRLCPY
 
26
size_t strlcpy(char *dest, const char *src, size_t size)
 
27
{
 
28
        size_t ret = strlen(src);
 
29
 
 
30
        if (size) {
 
31
                size_t len = (ret >= size) ? size - 1 : ret;
 
32
                memcpy(dest, src, len);
 
33
                dest[len] = '\0';
 
34
        }
 
35
        return ret;
 
36
}
 
37
#endif
 
38
 
 
39
static char *get_pathname(void)
 
40
{
 
41
        static char pathname_array[4][PATH_MAX];
 
42
        static int idx;
 
43
 
 
44
        return pathname_array[3 & ++idx];
 
45
}
 
46
 
 
47
static char *cleanup_path(char *path)
 
48
{
 
49
        /* Clean it up */
 
50
        if (!memcmp(path, "./", 2)) {
 
51
                path += 2;
 
52
                while (*path == '/')
 
53
                        path++;
 
54
        }
 
55
        return path;
 
56
}
 
57
 
 
58
static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
 
59
{
 
60
        const char *perf_dir = get_perf_dir();
 
61
        size_t len;
 
62
 
 
63
        len = strlen(perf_dir);
 
64
        if (n < len + 1)
 
65
                goto bad;
 
66
        memcpy(buf, perf_dir, len);
 
67
        if (len && !is_dir_sep(perf_dir[len-1]))
 
68
                buf[len++] = '/';
 
69
        len += vsnprintf(buf + len, n - len, fmt, args);
 
70
        if (len >= n)
 
71
                goto bad;
 
72
        return cleanup_path(buf);
 
73
bad:
 
74
        strlcpy(buf, bad_path, n);
 
75
        return buf;
 
76
}
 
77
 
 
78
char *perf_pathdup(const char *fmt, ...)
 
79
{
 
80
        char path[PATH_MAX];
 
81
        va_list args;
 
82
        va_start(args, fmt);
 
83
        (void)perf_vsnpath(path, sizeof(path), fmt, args);
 
84
        va_end(args);
 
85
        return xstrdup(path);
 
86
}
 
87
 
 
88
char *mkpath(const char *fmt, ...)
 
89
{
 
90
        va_list args;
 
91
        unsigned len;
 
92
        char *pathname = get_pathname();
 
93
 
 
94
        va_start(args, fmt);
 
95
        len = vsnprintf(pathname, PATH_MAX, fmt, args);
 
96
        va_end(args);
 
97
        if (len >= PATH_MAX)
 
98
                return bad_path;
 
99
        return cleanup_path(pathname);
 
100
}
 
101
 
 
102
char *perf_path(const char *fmt, ...)
 
103
{
 
104
        const char *perf_dir = get_perf_dir();
 
105
        char *pathname = get_pathname();
 
106
        va_list args;
 
107
        unsigned len;
 
108
 
 
109
        len = strlen(perf_dir);
 
110
        if (len > PATH_MAX-100)
 
111
                return bad_path;
 
112
        memcpy(pathname, perf_dir, len);
 
113
        if (len && perf_dir[len-1] != '/')
 
114
                pathname[len++] = '/';
 
115
        va_start(args, fmt);
 
116
        len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
 
117
        va_end(args);
 
118
        if (len >= PATH_MAX)
 
119
                return bad_path;
 
120
        return cleanup_path(pathname);
 
121
}
 
122
 
 
123
/* strip arbitrary amount of directory separators at end of path */
 
124
static inline int chomp_trailing_dir_sep(const char *path, int len)
 
125
{
 
126
        while (len && is_dir_sep(path[len - 1]))
 
127
                len--;
 
128
        return len;
 
129
}
 
130
 
 
131
/*
 
132
 * If path ends with suffix (complete path components), returns the
 
133
 * part before suffix (sans trailing directory separators).
 
134
 * Otherwise returns NULL.
 
135
 */
 
136
char *strip_path_suffix(const char *path, const char *suffix)
 
137
{
 
138
        int path_len = strlen(path), suffix_len = strlen(suffix);
 
139
 
 
140
        while (suffix_len) {
 
141
                if (!path_len)
 
142
                        return NULL;
 
143
 
 
144
                if (is_dir_sep(path[path_len - 1])) {
 
145
                        if (!is_dir_sep(suffix[suffix_len - 1]))
 
146
                                return NULL;
 
147
                        path_len = chomp_trailing_dir_sep(path, path_len);
 
148
                        suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
 
149
                }
 
150
                else if (path[--path_len] != suffix[--suffix_len])
 
151
                        return NULL;
 
152
        }
 
153
 
 
154
        if (path_len && !is_dir_sep(path[path_len - 1]))
 
155
                return NULL;
 
156
        return strndup(path, chomp_trailing_dir_sep(path, path_len));
 
157
}