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