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