| 1 | |
| 2 | |
| 3 | * Helper functions for handling target threads/cpus
|
| 4 | *
|
| 5 | * Copyright (C) 2012, LG Electronics, Namhyung Kim <[email protected]>
|
| 6 |
|
| 7 |
|
| 8 | #include "target.h"
|
| 9 |
|
| 10 | #include <pwd.h>
|
| 11 | #include <stdio.h>
|
| 12 | #include <stdlib.h>
|
| 13 | #include <string.h>
|
| 14 | #include <linux/kernel.h>
|
| 15 | #include <linux/string.h>
|
| 16 |
|
| 17 | enum target_errno target__validate(struct target *target)
|
| 18 | {
|
| 19 | enum target_errno ret = TARGET_ERRNO__SUCCESS;
|
| 20 |
|
| 21 | if (target->pid)
|
| 22 | target->tid = target->pid;
|
| 23 |
|
| 24 |
|
| 25 | if (target->tid && target->cpu_list) {
|
| 26 | target->cpu_list = NULL;
|
| 27 | if (ret == TARGET_ERRNO__SUCCESS)
|
| 28 | ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
|
| 29 | }
|
| 30 |
|
| 31 |
|
| 32 | if (target->tid && target->system_wide) {
|
| 33 | target->system_wide = false;
|
| 34 | if (ret == TARGET_ERRNO__SUCCESS)
|
| 35 | ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
|
| 36 | }
|
| 37 |
|
| 38 |
|
| 39 | if (target->bpf_str && target->cpu_list) {
|
| 40 | target->cpu_list = NULL;
|
| 41 | if (ret == TARGET_ERRNO__SUCCESS)
|
| 42 | ret = TARGET_ERRNO__BPF_OVERRIDE_CPU;
|
| 43 | }
|
| 44 |
|
| 45 |
|
| 46 | if (target->bpf_str && target->tid) {
|
| 47 | target->tid = NULL;
|
| 48 | if (ret == TARGET_ERRNO__SUCCESS)
|
| 49 | ret = TARGET_ERRNO__BPF_OVERRIDE_PID;
|
| 50 | }
|
| 51 |
|
| 52 |
|
| 53 | if (target->bpf_str && target->per_thread) {
|
| 54 | target->per_thread = false;
|
| 55 | if (ret == TARGET_ERRNO__SUCCESS)
|
| 56 | ret = TARGET_ERRNO__BPF_OVERRIDE_THREAD;
|
| 57 | }
|
| 58 |
|
| 59 |
|
| 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 |
|
| 66 | return ret;
|
| 67 | }
|
| 68 |
|
| 69 | uid_t parse_uid(const char *str)
|
| 70 | {
|
| 71 | struct passwd pwd, *result;
|
| 72 | char buf[1024];
|
| 73 |
|
| 74 | if (str == NULL)
|
| 75 | return UINT_MAX;
|
| 76 |
|
| 77 |
|
| 78 | getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
|
| 79 |
|
| 80 | if (result == NULL) {
|
| 81 | |
| 82 | * The user name not found. Maybe it's a UID number.
|
| 83 |
|
| 84 | char *endptr;
|
| 85 | int uid = strtol(str, &endptr, 10);
|
| 86 |
|
| 87 | if (*endptr != '\0')
|
| 88 | return UINT_MAX;
|
| 89 |
|
| 90 | getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
|
| 91 |
|
| 92 | if (result == NULL)
|
| 93 | return UINT_MAX;
|
| 94 | }
|
| 95 |
|
| 96 | return result->pw_uid;
|
| 97 | }
|
| 98 |
|
| 99 | |
| 100 | * This must have a same ordering as the enum target_errno.
|
| 101 |
|
| 102 | static const char *target__error_str[] = {
|
| 103 | "PID/TID switch overriding CPU",
|
| 104 | "PID/TID switch overriding SYSTEM",
|
| 105 | "SYSTEM/CPU switch overriding PER-THREAD",
|
| 106 | "BPF switch overriding CPU",
|
| 107 | "BPF switch overriding PID/TID",
|
| 108 | "BPF switch overriding THREAD",
|
| 109 | };
|
| 110 |
|
| 111 | int target__strerror(struct target *target __maybe_unused, int errnum,
|
| 112 | char *buf, size_t buflen)
|
| 113 | {
|
| 114 | int idx;
|
| 115 | const char *msg;
|
| 116 |
|
| 117 | BUG_ON(buflen == 0);
|
| 118 |
|
| 119 | if (errnum >= 0) {
|
| 120 | str_error_r(errnum, buf, buflen);
|
| 121 | return 0;
|
| 122 | }
|
| 123 |
|
| 124 | if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
|
| 125 | return -1;
|
| 126 |
|
| 127 | idx = errnum - __TARGET_ERRNO__START;
|
| 128 | msg = target__error_str[idx];
|
| 129 |
|
| 130 | switch (errnum) {
|
| 131 | case TARGET_ERRNO__PID_OVERRIDE_CPU ...
|
| 132 | TARGET_ERRNO__BPF_OVERRIDE_THREAD:
|
| 133 | snprintf(buf, buflen, "%s", msg);
|
| 134 | break;
|
| 135 |
|
| 136 | default:
|
| 137 |
|
| 138 | break;
|
| 139 | }
|
| 140 |
|
| 141 | return 0;
|
| 142 | }
|