1 /*
2 * Copyright (C) 2017 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
17 #include <getopt.h>
18 #include <sys/system_properties.h>
19
20 #include <algorithm>
21 #include <iostream>
22 #include <string>
23 #include <vector>
24
25 #include <android-base/properties.h>
26 #include <property_info_parser/property_info_parser.h>
27
28 using android::base::GetProperty;
29 using android::properties::PropertyInfoAreaFile;
30
31 PropertyInfoAreaFile property_info_file;
32
33 enum class ResultType {
34 Value,
35 Context,
36 Type,
37 };
38
PrintAllProperties(ResultType result_type)39 void PrintAllProperties(ResultType result_type) {
40 std::vector<std::pair<std::string, std::string>> properties;
41 __system_property_foreach(
42 [](const prop_info* pi, void* cookie) {
43 __system_property_read_callback(
44 pi,
45 [](void* cookie, const char* name, const char* value, unsigned) {
46 auto properties =
47 reinterpret_cast<std::vector<std::pair<std::string, std::string>>*>(cookie);
48 properties->emplace_back(name, value);
49 },
50 cookie);
51 },
52 &properties);
53
54 std::sort(properties.begin(), properties.end());
55
56 if (result_type != ResultType::Value) {
57 for (auto& [name, value] : properties) {
58 const char* context = nullptr;
59 const char* type = nullptr;
60 property_info_file->GetPropertyInfo(name.c_str(), &context, &type);
61 if (result_type == ResultType::Context) {
62 value = context;
63 } else {
64 value = type;
65 }
66 }
67 }
68
69 for (const auto& [name, value] : properties) {
70 std::cout << "[" << name << "]: [" << value << "]" << std::endl;
71 }
72 }
73
PrintProperty(const char * name,const char * default_value,ResultType result_type)74 void PrintProperty(const char* name, const char* default_value, ResultType result_type) {
75 switch (result_type) {
76 case ResultType::Value:
77 std::cout << GetProperty(name, default_value) << std::endl;
78 break;
79 case ResultType::Context: {
80 const char* context = nullptr;
81 property_info_file->GetPropertyInfo(name, &context, nullptr);
82 std::cout << context << std::endl;
83 break;
84 }
85 case ResultType::Type: {
86 const char* type = nullptr;
87 property_info_file->GetPropertyInfo(name, nullptr, &type);
88 std::cout << type << std::endl;
89 break;
90 }
91 }
92 }
93
getprop_main(int argc,char ** argv)94 extern "C" int getprop_main(int argc, char** argv) {
95 auto result_type = ResultType::Value;
96
97 while (true) {
98 static const struct option long_options[] = {
99 {"help", no_argument, nullptr, 'h'},
100 {nullptr, 0, nullptr, 0},
101 };
102
103 int arg = getopt_long(argc, argv, "TZ", long_options, nullptr);
104
105 if (arg == -1) {
106 break;
107 }
108
109 switch (arg) {
110 case 'h':
111 std::cout << "usage: getprop [-TZ] [NAME [DEFAULT]]\n"
112 "\n"
113 "Gets an Android system property, or lists them all.\n"
114 "\n"
115 "-T\tShow property types instead of values\n"
116 "-Z\tShow property contexts instead of values\n"
117 << std::endl;
118 return 0;
119 case 'T':
120 if (result_type != ResultType::Value) {
121 std::cerr << "Only one of -T or -Z may be specified" << std::endl;
122 return -1;
123 }
124 result_type = ResultType::Type;
125 break;
126 case 'Z':
127 if (result_type != ResultType::Value) {
128 std::cerr << "Only one of -T or -Z may be specified" << std::endl;
129 return -1;
130 }
131 result_type = ResultType::Context;
132 break;
133 case '?':
134 return -1;
135 default:
136 std::cerr << "getprop: getopt returned invalid result: " << arg << std::endl;
137 return -1;
138 }
139 }
140
141 if (result_type != ResultType::Value) {
142 property_info_file.LoadDefaultPath();
143 if (!property_info_file) {
144 std::cerr << "Unable to load property info file" << std::endl;
145 return -1;
146 }
147 }
148
149 if (optind >= argc) {
150 PrintAllProperties(result_type);
151 return 0;
152 }
153
154 if (optind < argc - 2) {
155 std::cerr << "getprop: Max 2 arguments (see \"getprop --help\")" << std::endl;
156 return -1;
157 }
158
159 PrintProperty(argv[optind], (optind == argc - 1) ? "" : argv[optind + 1], result_type);
160
161 return 0;
162 }
163