target.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Helper functions for handling target threads/cpus
  4. *
  5. * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
  6. */
  7. #include "target.h"
  8. #include <pwd.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <linux/kernel.h>
  13. #include <linux/string.h>
  14. enum target_errno target__validate(struct target *target)
  15. {
  16. enum target_errno ret = TARGET_ERRNO__SUCCESS;
  17. if (target->pid)
  18. target->tid = target->pid;
  19. /* CPU and PID are mutually exclusive */
  20. if (target->tid && target->cpu_list) {
  21. target->cpu_list = NULL;
  22. if (ret == TARGET_ERRNO__SUCCESS)
  23. ret = TARGET_ERRNO__PID_OVERRIDE_CPU;
  24. }
  25. /* PID and SYSTEM are mutually exclusive */
  26. if (target->tid && target->system_wide) {
  27. target->system_wide = false;
  28. if (ret == TARGET_ERRNO__SUCCESS)
  29. ret = TARGET_ERRNO__PID_OVERRIDE_SYSTEM;
  30. }
  31. /* BPF and CPU are mutually exclusive */
  32. if (target->bpf_str && target->cpu_list) {
  33. target->cpu_list = NULL;
  34. if (ret == TARGET_ERRNO__SUCCESS)
  35. ret = TARGET_ERRNO__BPF_OVERRIDE_CPU;
  36. }
  37. /* BPF and PID/TID are mutually exclusive */
  38. if (target->bpf_str && target->tid) {
  39. target->tid = NULL;
  40. if (ret == TARGET_ERRNO__SUCCESS)
  41. ret = TARGET_ERRNO__BPF_OVERRIDE_PID;
  42. }
  43. /* BPF and THREADS are mutually exclusive */
  44. if (target->bpf_str && target->per_thread) {
  45. target->per_thread = false;
  46. if (ret == TARGET_ERRNO__SUCCESS)
  47. ret = TARGET_ERRNO__BPF_OVERRIDE_THREAD;
  48. }
  49. /* THREAD and SYSTEM/CPU are mutually exclusive */
  50. if (target->per_thread && (target->system_wide || target->cpu_list)) {
  51. target->per_thread = false;
  52. if (ret == TARGET_ERRNO__SUCCESS)
  53. ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
  54. }
  55. return ret;
  56. }
  57. uid_t parse_uid(const char *str)
  58. {
  59. struct passwd pwd, *result;
  60. char buf[1024];
  61. if (str == NULL)
  62. return UINT_MAX;
  63. /* Try user name first */
  64. getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
  65. if (result == NULL) {
  66. /*
  67. * The user name not found. Maybe it's a UID number.
  68. */
  69. char *endptr;
  70. int uid = strtol(str, &endptr, 10);
  71. if (*endptr != '\0')
  72. return UINT_MAX;
  73. getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
  74. if (result == NULL)
  75. return UINT_MAX;
  76. }
  77. return result->pw_uid;
  78. }
  79. /*
  80. * This must have a same ordering as the enum target_errno.
  81. */
  82. static const char *target__error_str[] = {
  83. "PID/TID switch overriding CPU",
  84. "PID/TID switch overriding SYSTEM",
  85. "SYSTEM/CPU switch overriding PER-THREAD",
  86. "BPF switch overriding CPU",
  87. "BPF switch overriding PID/TID",
  88. "BPF switch overriding THREAD",
  89. };
  90. int target__strerror(struct target *target __maybe_unused, int errnum,
  91. char *buf, size_t buflen)
  92. {
  93. int idx;
  94. const char *msg;
  95. BUG_ON(buflen == 0);
  96. if (errnum >= 0) {
  97. str_error_r(errnum, buf, buflen);
  98. return 0;
  99. }
  100. if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
  101. return -1;
  102. idx = errnum - __TARGET_ERRNO__START;
  103. msg = target__error_str[idx];
  104. switch (errnum) {
  105. case TARGET_ERRNO__PID_OVERRIDE_CPU ...
  106. TARGET_ERRNO__BPF_OVERRIDE_THREAD:
  107. snprintf(buf, buflen, "%s", msg);
  108. break;
  109. default:
  110. /* cannot reach here */
  111. break;
  112. }
  113. return 0;
  114. }