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