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