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 target_errno target__validate(struct target *target)
  17{
  18        enum target_errno ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  27                        ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  34                        ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  41                        ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  48                        ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  55                        ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
  56        }
  57
  58        /* THREAD and SYSTEM/CPU are mutually exclusive */
  59        if (target->per_thread && (target->system_wide || target->cpu_list)) {
  60                target->per_thread = false;
  61                if (ret == TARGET_ERRNO__SUCCESS)
  62                        ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
  63        }
  64
  65        return ret;
  66}
  67
  68enum target_errno target__parse_uid(struct target *target)
  69{
  70        struct passwd pwd, *result;
  71        char buf[1024];
  72        const char *str = target->uid_str;
  73
  74        target->uid = UINT_MAX;
  75        if (str == NULL)
  76                return TARGET_ERRNO__SUCCESS;
  77
  78        /* Try user name first */
  79        getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
  80
  81        if (result == NULL) {
  82                /*
  83                 * The user name not found. Maybe it's a UID number.
  84                 */
  85                char *endptr;
  86                int uid = strtol(str, &endptr, 10);
  87
  88                if (*endptr != '\0')
  89                        return TARGET_ERRNO__INVALID_UID;
  90
  91                getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
  92
  93                if (result == NULL)
  94                        return TARGET_ERRNO__USER_NOT_FOUND;
  95        }
  96
  97        target->uid = result->pw_uid;
  98        return TARGET_ERRNO__SUCCESS;
  99}
 100
 101/*
 102 * This must have a same ordering as the enum target_errno.
 103 */
 104static const char *target__error_str[] = {
 105        "PID/TID switch overriding CPU",
 106        "PID/TID switch overriding UID",
 107        "UID switch overriding CPU",
 108        "PID/TID switch overriding SYSTEM",
 109        "UID switch overriding SYSTEM",
 110        "SYSTEM/CPU switch overriding PER-THREAD",
 111        "Invalid User: %s",
 112        "Problems obtaining information for user %s",
 113};
 114
 115int target__strerror(struct target *target, int errnum,
 116                          char *buf, size_t buflen)
 117{
 118        int idx;
 119        const char *msg;
 120
 121        BUG_ON(buflen == 0);
 122
 123        if (errnum >= 0) {
 124                const char *err = strerror_r(errnum, buf, buflen);
 125
 126                if (err != buf)
 127                        scnprintf(buf, buflen, "%s", err);
 128
 129                return 0;
 130        }
 131
 132        if (errnum <  __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
 133                return -1;
 134
 135        idx = errnum - __TARGET_ERRNO__START;
 136        msg = target__error_str[idx];
 137
 138        switch (errnum) {
 139        case TARGET_ERRNO__PID_OVERRIDE_CPU ...
 140             TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
 141                snprintf(buf, buflen, "%s", msg);
 142                break;
 143
 144        case TARGET_ERRNO__INVALID_UID:
 145        case TARGET_ERRNO__USER_NOT_FOUND:
 146                snprintf(buf, buflen, msg, target->uid_str);
 147                break;
 148
 149        default:
 150                /* cannot reach here */
 151                break;
 152        }
 153
 154        return 0;
 155}
 156