Commit | Line | Data |
---|---|---|
12864b31 NK |
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 | ||
dfe78ada | 12 | #include <pwd.h> |
16ad2ffb | 13 | #include <string.h> |
dfe78ada | 14 | |
12864b31 | 15 | |
60bbddaa | 16 | enum perf_target_errno perf_target__validate(struct perf_target *target) |
12864b31 | 17 | { |
60bbddaa NK |
18 | enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS; |
19 | ||
12864b31 NK |
20 | if (target->pid) |
21 | target->tid = target->pid; | |
22 | ||
23 | /* CPU and PID are mutually exclusive */ | |
24 | if (target->tid && target->cpu_list) { | |
12864b31 | 25 | target->cpu_list = NULL; |
60bbddaa NK |
26 | if (ret == PERF_ERRNO_TARGET__SUCCESS) |
27 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU; | |
12864b31 NK |
28 | } |
29 | ||
30 | /* UID and PID are mutually exclusive */ | |
31 | if (target->tid && target->uid_str) { | |
12864b31 | 32 | target->uid_str = NULL; |
60bbddaa NK |
33 | if (ret == PERF_ERRNO_TARGET__SUCCESS) |
34 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID; | |
12864b31 NK |
35 | } |
36 | ||
37 | /* UID and CPU are mutually exclusive */ | |
38 | if (target->uid_str && target->cpu_list) { | |
12864b31 | 39 | target->cpu_list = NULL; |
60bbddaa NK |
40 | if (ret == PERF_ERRNO_TARGET__SUCCESS) |
41 | ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU; | |
12864b31 NK |
42 | } |
43 | ||
60bbddaa NK |
44 | /* PID and SYSTEM are mutually exclusive */ |
45 | if (target->tid && target->system_wide) { | |
12864b31 | 46 | target->system_wide = false; |
60bbddaa NK |
47 | if (ret == PERF_ERRNO_TARGET__SUCCESS) |
48 | ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM; | |
12864b31 | 49 | } |
60bbddaa NK |
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; | |
12864b31 | 59 | } |
dfe78ada NK |
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 | } | |
16ad2ffb NK |
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 | ||
0ecf4f0c | 113 | BUG_ON(buflen == 0); |
4cc49d4d | 114 | |
16ad2ffb | 115 | if (errnum >= 0) { |
4cc49d4d KS |
116 | const char *err = strerror_r(errnum, buf, buflen); |
117 | ||
118 | if (err != buf) { | |
119 | size_t len = strlen(err); | |
120 | char *c = mempcpy(buf, err, min(buflen - 1, len)); | |
121 | *c = '\0'; | |
122 | } | |
123 | ||
16ad2ffb NK |
124 | return 0; |
125 | } | |
126 | ||
127 | if (errnum < __PERF_ERRNO_TARGET__START || | |
128 | errnum >= __PERF_ERRNO_TARGET__END) | |
129 | return -1; | |
130 | ||
131 | idx = errnum - __PERF_ERRNO_TARGET__START; | |
132 | msg = perf_target__error_str[idx]; | |
133 | ||
134 | switch (errnum) { | |
135 | case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU | |
136 | ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM: | |
137 | snprintf(buf, buflen, "%s", msg); | |
138 | break; | |
139 | ||
140 | case PERF_ERRNO_TARGET__INVALID_UID: | |
141 | case PERF_ERRNO_TARGET__USER_NOT_FOUND: | |
142 | snprintf(buf, buflen, msg, target->uid_str); | |
143 | break; | |
144 | ||
145 | default: | |
146 | /* cannot reach here */ | |
147 | break; | |
148 | } | |
149 | ||
150 | return 0; | |
151 | } |