target.c 3.4 KB

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