target.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 target_errno target__validate(struct target *target)
  13. {
  14. enum target_errno ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  21. ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  27. ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  33. ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  39. ret = TARGET_ERRNO__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 == TARGET_ERRNO__SUCCESS)
  45. ret = TARGET_ERRNO__UID_OVERRIDE_SYSTEM;
  46. }
  47. /* THREAD and SYSTEM/CPU are mutually exclusive */
  48. if (target->per_thread && (target->system_wide || target->cpu_list)) {
  49. target->per_thread = false;
  50. if (ret == TARGET_ERRNO__SUCCESS)
  51. ret = TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD;
  52. }
  53. return ret;
  54. }
  55. enum target_errno target__parse_uid(struct target *target)
  56. {
  57. struct passwd pwd, *result;
  58. char buf[1024];
  59. const char *str = target->uid_str;
  60. target->uid = UINT_MAX;
  61. if (str == NULL)
  62. return TARGET_ERRNO__SUCCESS;
  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 TARGET_ERRNO__INVALID_UID;
  73. getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
  74. if (result == NULL)
  75. return TARGET_ERRNO__USER_NOT_FOUND;
  76. }
  77. target->uid = result->pw_uid;
  78. return TARGET_ERRNO__SUCCESS;
  79. }
  80. /*
  81. * This must have a same ordering as the enum target_errno.
  82. */
  83. static const char *target__error_str[] = {
  84. "PID/TID switch overriding CPU",
  85. "PID/TID switch overriding UID",
  86. "UID switch overriding CPU",
  87. "PID/TID switch overriding SYSTEM",
  88. "UID switch overriding SYSTEM",
  89. "SYSTEM/CPU switch overriding PER-THREAD",
  90. "Invalid User: %s",
  91. "Problems obtaining information for user %s",
  92. };
  93. int target__strerror(struct target *target, int errnum,
  94. char *buf, size_t buflen)
  95. {
  96. int idx;
  97. const char *msg;
  98. BUG_ON(buflen == 0);
  99. if (errnum >= 0) {
  100. const char *err = strerror_r(errnum, buf, buflen);
  101. if (err != buf)
  102. scnprintf(buf, buflen, "%s", err);
  103. return 0;
  104. }
  105. if (errnum < __TARGET_ERRNO__START || errnum >= __TARGET_ERRNO__END)
  106. return -1;
  107. idx = errnum - __TARGET_ERRNO__START;
  108. msg = target__error_str[idx];
  109. switch (errnum) {
  110. case TARGET_ERRNO__PID_OVERRIDE_CPU ...
  111. TARGET_ERRNO__SYSTEM_OVERRIDE_THREAD:
  112. snprintf(buf, buflen, "%s", msg);
  113. break;
  114. case TARGET_ERRNO__INVALID_UID:
  115. case TARGET_ERRNO__USER_NOT_FOUND:
  116. snprintf(buf, buflen, msg, target->uid_str);
  117. break;
  118. default:
  119. /* cannot reach here */
  120. break;
  121. }
  122. return 0;
  123. }