diff options
Diffstat (limited to 'tools/perf/util/target.c')
-rw-r--r-- | tools/perf/util/target.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c new file mode 100644 index 000000000000..1064d5b148ad --- /dev/null +++ b/tools/perf/util/target.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Helper functions for handling target threads/cpus | ||
3 | * | ||
4 | * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com> | ||
5 | * | ||
6 | * Released under the GPL v2. | ||
7 | */ | ||
8 | |||
9 | #include "target.h" | ||
10 | #include "debug.h" | ||
11 | |||
12 | #include <pwd.h> | ||
13 | #include <string.h> | ||
14 | |||
15 | |||
16 | enum perf_target_errno perf_target__validate(struct perf_target *target) | ||
17 | { | ||
18 | enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS; | ||
19 | |||
20 | if (target->pid) | ||
21 | target->tid = target->pid; | ||
22 | |||
23 | /* CPU and PID are mutually exclusive */ | ||
24 | if (target->tid && target->cpu_list) { | ||
25 | target->cpu_list = NULL; | ||
26 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
27 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU; | ||
28 | } | ||
29 | |||
30 | /* UID and PID are mutually exclusive */ | ||
31 | if (target->tid && target->uid_str) { | ||
32 | target->uid_str = NULL; | ||
33 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
34 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID; | ||
35 | } | ||
36 | |||
37 | /* UID and CPU are mutually exclusive */ | ||
38 | if (target->uid_str && target->cpu_list) { | ||
39 | target->cpu_list = NULL; | ||
40 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
41 | ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU; | ||
42 | } | ||
43 | |||
44 | /* PID and SYSTEM are mutually exclusive */ | ||
45 | if (target->tid && target->system_wide) { | ||
46 | target->system_wide = false; | ||
47 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
48 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM; | ||
49 | } | ||
50 | |||
51 | /* UID and SYSTEM are mutually exclusive */ | ||
52 | if (target->uid_str && target->system_wide) { | ||
53 | target->system_wide = false; | ||
54 | if (ret == PERF_ERRNO_TARGET__SUCCESS) | ||
55 | ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM; | ||
56 | } | ||
57 | |||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | enum perf_target_errno perf_target__parse_uid(struct perf_target *target) | ||
62 | { | ||
63 | struct passwd pwd, *result; | ||
64 | char buf[1024]; | ||
65 | const char *str = target->uid_str; | ||
66 | |||
67 | target->uid = UINT_MAX; | ||
68 | if (str == NULL) | ||
69 | return PERF_ERRNO_TARGET__SUCCESS; | ||
70 | |||
71 | /* Try user name first */ | ||
72 | getpwnam_r(str, &pwd, buf, sizeof(buf), &result); | ||
73 | |||
74 | if (result == NULL) { | ||
75 | /* | ||
76 | * The user name not found. Maybe it's a UID number. | ||
77 | */ | ||
78 | char *endptr; | ||
79 | int uid = strtol(str, &endptr, 10); | ||
80 | |||
81 | if (*endptr != '\0') | ||
82 | return PERF_ERRNO_TARGET__INVALID_UID; | ||
83 | |||
84 | getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); | ||
85 | |||
86 | if (result == NULL) | ||
87 | return PERF_ERRNO_TARGET__USER_NOT_FOUND; | ||
88 | } | ||
89 | |||
90 | target->uid = result->pw_uid; | ||
91 | return PERF_ERRNO_TARGET__SUCCESS; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * This must have a same ordering as the enum perf_target_errno. | ||
96 | */ | ||
97 | static const char *perf_target__error_str[] = { | ||
98 | "PID/TID switch overriding CPU", | ||
99 | "PID/TID switch overriding UID", | ||
100 | "UID switch overriding CPU", | ||
101 | "PID/TID switch overriding SYSTEM", | ||
102 | "UID switch overriding SYSTEM", | ||
103 | "Invalid User: %s", | ||
104 | "Problems obtaining information for user %s", | ||
105 | }; | ||
106 | |||
107 | int perf_target__strerror(struct perf_target *target, int errnum, | ||
108 | char *buf, size_t buflen) | ||
109 | { | ||
110 | int idx; | ||
111 | const char *msg; | ||
112 | |||
113 | if (errnum >= 0) { | ||
114 | strerror_r(errnum, buf, buflen); | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | if (errnum < __PERF_ERRNO_TARGET__START || | ||
119 | errnum >= __PERF_ERRNO_TARGET__END) | ||
120 | return -1; | ||
121 | |||
122 | idx = errnum - __PERF_ERRNO_TARGET__START; | ||
123 | msg = perf_target__error_str[idx]; | ||
124 | |||
125 | switch (errnum) { | ||
126 | case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU | ||
127 | ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM: | ||
128 | snprintf(buf, buflen, "%s", msg); | ||
129 | break; | ||
130 | |||
131 | case PERF_ERRNO_TARGET__INVALID_UID: | ||
132 | case PERF_ERRNO_TARGET__USER_NOT_FOUND: | ||
133 | snprintf(buf, buflen, msg, target->uid_str); | ||
134 | break; | ||
135 | |||
136 | default: | ||
137 | /* cannot reach here */ | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | return 0; | ||
142 | } | ||