linux/tools/perf/util/target.c
<<
>>
Prefs
   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
  12#include <pwd.h>
  13#include <string.h>
  14
  15
  16enum perf_target_errno perf_target__validate(struct perf_target *target)
  17{
  18        enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS;
  19
  20        if (target->pid)
  21                target->tid = target->pid;
  22
  23        /* CPU and PID are mutually exclusive */
  24        if (target->tid && target->cpu_list) {
  25                target->cpu_list = NULL;
  26                if (ret == PERF_ERRNO_TARGET__SUCCESS)
  27                        ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU;
  28        }
  29
  30        /* UID and PID are mutually exclusive */
  31        if (target->tid && target->uid_str) {
  32                target->uid_str = NULL;
  33                if (ret == PERF_ERRNO_TARGET__SUCCESS)
  34                        ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID;
  35        }
  36
  37        /* UID and CPU are mutually exclusive */
  38        if (target->uid_str && target->cpu_list) {
  39                target->cpu_list = NULL;
  40                if (ret == PERF_ERRNO_TARGET__SUCCESS)
  41                        ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU;
  42        }
  43
  44        /* PID and SYSTEM are mutually exclusive */
  45        if (target->tid && target->system_wide) {
  46                target->system_wide = false;
  47                if (ret == PERF_ERRNO_TARGET__SUCCESS)
  48                        ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM;
  49        }
  50
  51        /* UID and SYSTEM are mutually exclusive */
  52        if (target->uid_str && target->system_wide) {
  53                target->system_wide = false;
  54                if (ret == PERF_ERRNO_TARGET__SUCCESS)
  55                        ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM;
  56        }
  57
  58        return ret;
  59}
  60
  61enum perf_target_errno perf_target__parse_uid(struct perf_target *target)
  62{
  63        struct passwd pwd, *result;
  64        char buf[1024];
  65        const char *str = target->uid_str;
  66
  67        target->uid = UINT_MAX;
  68        if (str == NULL)
  69                return PERF_ERRNO_TARGET__SUCCESS;
  70
  71        /* Try user name first */
  72        getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
  73
  74        if (result == NULL) {
  75                /*
  76                 * The user name not found. Maybe it's a UID number.
  77                 */
  78                char *endptr;
  79                int uid = strtol(str, &endptr, 10);
  80
  81                if (*endptr != '\0')
  82                        return PERF_ERRNO_TARGET__INVALID_UID;
  83
  84                getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
  85
  86                if (result == NULL)
  87                        return PERF_ERRNO_TARGET__USER_NOT_FOUND;
  88        }
  89
  90        target->uid = result->pw_uid;
  91        return PERF_ERRNO_TARGET__SUCCESS;
  92}
  93
  94/*
  95 * This must have a same ordering as the enum perf_target_errno.
  96 */
  97static const char *perf_target__error_str[] = {
  98        "PID/TID switch overriding CPU",
  99        "PID/TID switch overriding UID",
 100        "UID switch overriding CPU",
 101        "PID/TID switch overriding SYSTEM",
 102        "UID switch overriding SYSTEM",
 103        "Invalid User: %s",
 104        "Problems obtaining information for user %s",
 105};
 106
 107int perf_target__strerror(struct perf_target *target, int errnum,
 108                          char *buf, size_t buflen)
 109{
 110        int idx;
 111        const char *msg;
 112
 113        BUG_ON(buflen == 0);
 114
 115        if (errnum >= 0) {
 116                const char *err = strerror_r(errnum, buf, buflen);
 117
 118                if (err != buf) {
 119                        size_t len = strlen(err);
 120                        memcpy(buf, err, min(buflen - 1, len));
 121                        *(buf + min(buflen - 1, len)) = '\0';
 122                }
 123
 124                return 0;
 125        }
 126
 127        if (errnum <  __PERF_ERRNO_TARGET__START ||
 128            errnum >= __PERF_ERRNO_TARGET__END)
 129                return -1;
 130
 131        idx = errnum - __PERF_ERRNO_TARGET__START;
 132        msg = perf_target__error_str[idx];
 133
 134        switch (errnum) {
 135        case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU
 136         ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM:
 137                snprintf(buf, buflen, "%s", msg);
 138                break;
 139
 140        case PERF_ERRNO_TARGET__INVALID_UID:
 141        case PERF_ERRNO_TARGET__USER_NOT_FOUND:
 142                snprintf(buf, buflen, msg, target->uid_str);
 143                break;
 144
 145        default:
 146                /* cannot reach here */
 147                break;
 148        }
 149
 150        return 0;
 151}
 152