1 // SPDX-License-Identifier: GPL-2.0-only
3 * Helper functions for handling target threads/cpus
5 * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
16 #include <linux/kernel.h>
17 #include <linux/string.h>
19 enum target_errno target__validate(struct target *target)
21 enum target_errno ret = TARGET_ERRNO__SUCCESS;
24 target->tid = target->pid;
26 /* CPU and PID are mutually exclusive */
27 if (target->tid && target->cpu_list) {
28 target->cpu_list = NULL;
29 if (ret == TARGET_ERRNO__SUCCESS)
30 ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
33 /* UID and PID are mutually exclusive */
34 if (target->tid && target->uid_str) {
35 target->uid_str = NULL;
36 if (ret == TARGET_ERRNO__SUCCESS)
37 ret = TARGET_ERRNO__PID_OVERRIDE_UID;
40 /* UID and CPU are mutually exclusive */
41 if (target->uid_str && target->cpu_list) {
42 target->cpu_list = NULL;
43 if (ret == TARGET_ERRNO__SUCCESS)
44 ret = TARGET_ERRNO__UID_OVERRIDE_CPU;
47 /* PID and SYSTEM are mutually exclusive */
48 if (target->tid && target->system_wide) {
49 target->system_wide = false;
50 if (ret == TARGET_ERRNO__SUCCESS)
51 ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
54 /* UID and SYSTEM are mutually exclusive */
55 if (target->uid_str && target->system_wide) {
56 target->system_wide = false;
57 if (ret == TARGET_ERRNO__SUCCESS)
58 ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
61 /* THREAD and SYSTEM/CPU are mutually exclusive */
62 if (target->per_thread && (target->system_wide || target->cpu_list)) {
63 target->per_thread = false;
64 if (ret == TARGET_ERRNO__SUCCESS)
65 ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
71 enum target_errno target__parse_uid(struct target *target)
73 struct passwd pwd, *result;
75 const char *str = target->uid_str;
77 target->uid = UINT_MAX;
79 return TARGET_ERRNO__SUCCESS;
81 /* Try user name first */
82 getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
86 * The user name not found. Maybe it's a UID number.
89 int uid = strtol(str, &endptr, 10);
92 return TARGET_ERRNO__INVALID_UID;
94 getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
97 return TARGET_ERRNO__USER_NOT_FOUND;
100 target->uid = result->pw_uid;
101 return TARGET_ERRNO__SUCCESS;
105 * This must have a same ordering as the enum target_errno.
107 static const char *target__error_str[] = {
108 "PID/TID switch overriding CPU",
109 "PID/TID switch overriding UID",
110 "UID switch overriding CPU",
111 "PID/TID switch overriding SYSTEM",
112 "UID switch overriding SYSTEM",
113 "SYSTEM/CPU switch overriding PER-THREAD",
115 "Problems obtaining information for user %s",
118 int target__strerror(struct target *target, int errnum,
119 char *buf, size_t buflen)
127 str_error_r(errnum, buf, buflen);
131 if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
134 idx = errnum - __TARGET_ERRNO__START;
135 msg = target__error_str[idx];
138 case TARGET_ERRNO__PID_OVERRIDE_CPU ...
139 TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
140 snprintf(buf, buflen, "%s", msg);
143 case TARGET_ERRNO__INVALID_UID:
144 case TARGET_ERRNO__USER_NOT_FOUND:
145 snprintf(buf, buflen, msg, target->uid_str);
149 /* cannot reach here */