procpartition.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /*
  2. * Copyright (C) 2018 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <procpartition/procpartition.h>
  17. #include <android-base/file.h>
  18. namespace android {
  19. namespace procpartition {
  20. std::ostream& operator<<(std::ostream& os, Partition p) {
  21. switch (p) {
  22. case Partition::SYSTEM: return os << "system";
  23. case Partition::VENDOR: return os << "vendor";
  24. case Partition::ODM: return os << "odm";
  25. case Partition::UNKNOWN: // fallthrough
  26. default:
  27. return os << "(unknown)";
  28. }
  29. }
  30. std::string getExe(pid_t pid) {
  31. std::string exe;
  32. std::string real;
  33. if (!android::base::Readlink("/proc/" + std::to_string(pid) + "/exe", &exe)) {
  34. return "";
  35. }
  36. if (!android::base::Realpath(exe, &real)) {
  37. return "";
  38. }
  39. return real;
  40. }
  41. std::string getCmdline(pid_t pid) {
  42. std::string content;
  43. if (!android::base::ReadFileToString("/proc/" + std::to_string(pid) + "/cmdline", &content,
  44. false /* follow symlinks */)) {
  45. return "";
  46. }
  47. return std::string{content.c_str()};
  48. }
  49. Partition parsePartition(const std::string& s) {
  50. if (s == "system") {
  51. return Partition::SYSTEM;
  52. }
  53. if (s == "vendor") {
  54. return Partition::VENDOR;
  55. }
  56. if (s == "odm") {
  57. return Partition::ODM;
  58. }
  59. return Partition::UNKNOWN;
  60. }
  61. Partition getPartitionFromRealpath(const std::string& path) {
  62. if (path == "/system/bin/app_process64" ||
  63. path == "/system/bin/app_process32") {
  64. return Partition::UNKNOWN; // cannot determine
  65. }
  66. size_t backslash = path.find_first_of('/', 1);
  67. std::string partition = (backslash != std::string::npos) ? path.substr(1, backslash - 1) : path;
  68. return parsePartition(partition);
  69. }
  70. Partition getPartitionFromCmdline(pid_t pid) {
  71. const auto& cmdline = getCmdline(pid);
  72. if (cmdline == "system_server") {
  73. return Partition::SYSTEM;
  74. }
  75. if (cmdline.empty() || cmdline.front() != '/') {
  76. return Partition::UNKNOWN;
  77. }
  78. return getPartitionFromRealpath(cmdline);
  79. }
  80. Partition getPartitionFromExe(pid_t pid) {
  81. const auto& real = getExe(pid);
  82. if (real.empty() || real.front() != '/') {
  83. return Partition::UNKNOWN;
  84. }
  85. return getPartitionFromRealpath(real);
  86. }
  87. Partition getPartition(pid_t pid) {
  88. Partition partition = getPartitionFromExe(pid);
  89. if (partition == Partition::UNKNOWN) {
  90. partition = getPartitionFromCmdline(pid);
  91. }
  92. return partition;
  93. }
  94. } // namespace procpartition
  95. } // namespace android