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 | |
602ad878 | 16 | enum target_errno target__validate(struct target *target) |
12864b31 | 17 | { |
602ad878 | 18 | enum target_errno ret = TARGET_ERRNO__SUCCESS; |
60bbddaa | 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; |
602ad878 ACM |
26 | if (ret == TARGET_ERRNO__SUCCESS) |
27 | ret = TARGET_ERRNO__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; |
602ad878 ACM |
33 | if (ret == TARGET_ERRNO__SUCCESS) |
34 | ret = TARGET_ERRNO__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; |
602ad878 ACM |
40 | if (ret == TARGET_ERRNO__SUCCESS) |
41 | ret = TARGET_ERRNO__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; |
602ad878 ACM |
47 | if (ret == TARGET_ERRNO__SUCCESS) |
48 | ret = TARGET_ERRNO__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; | |
602ad878 ACM |
54 | if (ret == TARGET_ERRNO__SUCCESS) |
55 | ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM; | |
60bbddaa NK |
56 | } |
57 | ||
3aa5939d AH |
58 | /* THREAD and SYSTEM/CPU are mutually exclusive */ |
59 | if (target->per_thread && (target->system_wide || target->cpu_list)) { | |
60 | target->per_thread = false; | |
61 | if (ret == TARGET_ERRNO__SUCCESS) | |
62 | ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD; | |
63 | } | |
64 | ||
60bbddaa | 65 | return ret; |
12864b31 | 66 | } |
dfe78ada | 67 | |
602ad878 | 68 | enum target_errno target__parse_uid(struct target *target) |
dfe78ada NK |
69 | { |
70 | struct passwd pwd, *result; | |
71 | char buf[1024]; | |
72 | const char *str = target->uid_str; | |
73 | ||
74 | target->uid = UINT_MAX; | |
75 | if (str == NULL) | |
602ad878 | 76 | return TARGET_ERRNO__SUCCESS; |
dfe78ada NK |
77 | |
78 | /* Try user name first */ | |
79 | getpwnam_r(str, &pwd, buf, sizeof(buf), &result); | |
80 | ||
81 | if (result == NULL) { | |
82 | /* | |
83 | * The user name not found. Maybe it's a UID number. | |
84 | */ | |
85 | char *endptr; | |
86 | int uid = strtol(str, &endptr, 10); | |
87 | ||
88 | if (*endptr != '\0') | |
602ad878 | 89 | return TARGET_ERRNO__INVALID_UID; |
dfe78ada NK |
90 | |
91 | getpwuid_r(uid, &pwd, buf, sizeof(buf), &result); | |
92 | ||
93 | if (result == NULL) | |
602ad878 | 94 | return TARGET_ERRNO__USER_NOT_FOUND; |
dfe78ada NK |
95 | } |
96 | ||
97 | target->uid = result->pw_uid; | |
602ad878 | 98 | return TARGET_ERRNO__SUCCESS; |
dfe78ada | 99 | } |
16ad2ffb NK |
100 | |
101 | /* | |
602ad878 | 102 | * This must have a same ordering as the enum target_errno. |
16ad2ffb | 103 | */ |
602ad878 | 104 | static const char *target__error_str[] = { |
16ad2ffb NK |
105 | "PID/TID switch overriding CPU", |
106 | "PID/TID switch overriding UID", | |
107 | "UID switch overriding CPU", | |
108 | "PID/TID switch overriding SYSTEM", | |
109 | "UID switch overriding SYSTEM", | |
3aa5939d | 110 | "SYSTEM/CPU switch overriding PER-THREAD", |
16ad2ffb NK |
111 | "Invalid User: %s", |
112 | "Problems obtaining information for user %s", | |
113 | }; | |
114 | ||
602ad878 | 115 | int target__strerror(struct target *target, int errnum, |
16ad2ffb NK |
116 | char *buf, size_t buflen) |
117 | { | |
118 | int idx; | |
119 | const char *msg; | |
120 | ||
0ecf4f0c | 121 | BUG_ON(buflen == 0); |
4cc49d4d | 122 | |
16ad2ffb | 123 | if (errnum >= 0) { |
4cc49d4d KS |
124 | const char *err = strerror_r(errnum, buf, buflen); |
125 | ||
17e44dc4 ACM |
126 | if (err != buf) |
127 | scnprintf(buf, buflen, "%s", err); | |
4cc49d4d | 128 | |
16ad2ffb NK |
129 | return 0; |
130 | } | |
131 | ||
602ad878 | 132 | if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END) |
16ad2ffb NK |
133 | return -1; |
134 | ||
602ad878 ACM |
135 | idx = errnum - __TARGET_ERRNO__START; |
136 | msg = target__error_str[idx]; | |
16ad2ffb NK |
137 | |
138 | switch (errnum) { | |
3aa5939d AH |
139 | case TARGET_ERRNO__PID_OVERRIDE_CPU ... |
140 | TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD: | |
16ad2ffb NK |
141 | snprintf(buf, buflen, "%s", msg); |
142 | break; | |
143 | ||
602ad878 ACM |
144 | case TARGET_ERRNO__INVALID_UID: |
145 | case TARGET_ERRNO__USER_NOT_FOUND: | |
16ad2ffb NK |
146 | snprintf(buf, buflen, msg, target->uid_str); |
147 | break; | |
148 | ||
149 | default: | |
150 | /* cannot reach here */ | |
151 | break; | |
152 | } | |
153 | ||
154 | return 0; | |
155 | } |