target.c 3.4 KB

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