1 #include <android-base/unique_fd.h>
2 #include <sys/mman.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <errno.h>
6 #include <string.h>
7
8 #include "rust/cxx.h"
9 #include "aconfig_storage/lib.rs.h"
10 #include "aconfig_storage/aconfig_storage_read_api.hpp"
11
12 namespace aconfig_storage {
13
14 /// Storage location pb file
15 static constexpr char kStorageDir[] = "/metadata/aconfig";
16
17 /// destructor
~MappedStorageFile()18 MappedStorageFile::~MappedStorageFile() {
19 munmap(file_ptr, file_size);
20 }
21
22 /// Get storage file path
find_storage_file(std::string const & storage_dir,std::string const & container,StorageFileType file_type)23 static Result<std::string> find_storage_file(
24 std::string const& storage_dir,
25 std::string const& container,
26 StorageFileType file_type) {
27 switch(file_type) {
28 case StorageFileType::package_map:
29 return storage_dir + "/maps/" + container + ".package.map";
30 case StorageFileType::flag_map:
31 return storage_dir + "/maps/" + container + ".flag.map";
32 case StorageFileType::flag_val:
33 return storage_dir + "/boot/" + container + ".val";
34 case StorageFileType::flag_info:
35 return storage_dir + "/boot/" + container + ".info";
36 default:
37 auto result = Result<std::string>();
38 result.errmsg = "Invalid storage file type";
39 return result;
40 }
41 }
42
43 namespace private_internal_api {
44
45 /// Get mapped file implementation.
get_mapped_file_impl(std::string const & storage_dir,std::string const & container,StorageFileType file_type)46 Result<MappedStorageFile*> get_mapped_file_impl(
47 std::string const& storage_dir,
48 std::string const& container,
49 StorageFileType file_type) {
50 auto file_result = find_storage_file(storage_dir, container, file_type);
51 if (!file_result.ok()) {
52 auto result = Result<MappedStorageFile*>();
53 result.errmsg = file_result.error();
54 return result;
55 }
56 return map_storage_file(*file_result);
57 }
58
59 } // namespace private internal api
60
61 /// Map a storage file
map_storage_file(std::string const & file)62 Result<MappedStorageFile*> map_storage_file(std::string const& file) {
63 android::base::unique_fd ufd(open(file.c_str(), O_CLOEXEC | O_NOFOLLOW | O_RDONLY));
64 if (ufd.get() == -1) {
65 auto result = Result<MappedStorageFile*>();
66 result.errmsg = std::string("failed to open ") + file + ": " + strerror(errno);
67 return result;
68 };
69
70 struct stat fd_stat;
71 if (fstat(ufd.get(), &fd_stat) < 0) {
72 auto result = Result<MappedStorageFile*>();
73 result.errmsg = std::string("fstat failed: ") + strerror(errno);
74 return result;
75 }
76 size_t file_size = fd_stat.st_size;
77
78 void* const map_result = mmap(nullptr, file_size, PROT_READ, MAP_SHARED, ufd.get(), 0);
79 if (map_result == MAP_FAILED) {
80 auto result = Result<MappedStorageFile*>();
81 result.errmsg = std::string("mmap failed: ") + strerror(errno);
82 return result;
83 }
84
85 auto mapped_file = new MappedStorageFile();
86 mapped_file->file_ptr = map_result;
87 mapped_file->file_size = file_size;
88
89 return mapped_file;
90 }
91
92 /// Map from StoredFlagType to FlagValueType
map_to_flag_value_type(StoredFlagType stored_type)93 Result<FlagValueType> map_to_flag_value_type(
94 StoredFlagType stored_type) {
95 switch (stored_type) {
96 case StoredFlagType::ReadWriteBoolean:
97 case StoredFlagType::ReadOnlyBoolean:
98 case StoredFlagType::FixedReadOnlyBoolean:
99 return FlagValueType::Boolean;
100 default:
101 auto result = Result<FlagValueType>();
102 result.errmsg = "Unsupported stored flag type";
103 return result;
104 }
105 }
106
107 /// Get mapped storage file
get_mapped_file(std::string const & container,StorageFileType file_type)108 Result<MappedStorageFile*> get_mapped_file(
109 std::string const& container,
110 StorageFileType file_type) {
111 return private_internal_api::get_mapped_file_impl(
112 kStorageDir, container, file_type);
113 }
114
115 /// Get storage file version number
get_storage_file_version(std::string const & file_path)116 Result<uint32_t> get_storage_file_version(
117 std::string const& file_path) {
118 auto version_cxx = get_storage_file_version_cxx(
119 rust::Str(file_path.c_str()));
120 if (version_cxx.query_success) {
121 return version_cxx.version_number;
122 } else {
123 auto result = Result<uint32_t>();
124 result.errmsg = version_cxx.error_message.c_str();
125 return result;
126 }
127 }
128
129 /// Get package context
get_package_read_context(MappedStorageFile const & file,std::string const & package)130 Result<PackageReadContext> get_package_read_context(
131 MappedStorageFile const& file,
132 std::string const& package) {
133 auto content = rust::Slice<const uint8_t>(
134 static_cast<uint8_t*>(file.file_ptr), file.file_size);
135 auto context_cxx = get_package_read_context_cxx(content, rust::Str(package.c_str()));
136 if (context_cxx.query_success) {
137 auto context = PackageReadContext();
138 context.package_exists = context_cxx.package_exists;
139 context.package_id = context_cxx.package_id;
140 context.boolean_start_index = context_cxx.boolean_start_index;
141 return context;
142 } else {
143 auto result = Result<PackageReadContext>();
144 result.errmsg = context_cxx.error_message.c_str();
145 return result;
146 }
147 }
148
149 /// Get flag read context
get_flag_read_context(MappedStorageFile const & file,uint32_t package_id,std::string const & flag_name)150 Result<FlagReadContext> get_flag_read_context(
151 MappedStorageFile const& file,
152 uint32_t package_id,
153 std::string const& flag_name){
154 auto content = rust::Slice<const uint8_t>(
155 static_cast<uint8_t*>(file.file_ptr), file.file_size);
156 auto context_cxx = get_flag_read_context_cxx(content, package_id, rust::Str(flag_name.c_str()));
157 if (context_cxx.query_success) {
158 auto context = FlagReadContext();
159 context.flag_exists = context_cxx.flag_exists;
160 context.flag_type = static_cast<StoredFlagType>(context_cxx.flag_type);
161 context.flag_index = context_cxx.flag_index;
162 return context;
163 } else {
164 auto result = Result<FlagReadContext>();
165 result.errmsg = context_cxx.error_message.c_str();
166 return result;
167 }
168 }
169
170 /// Get boolean flag value
get_boolean_flag_value(MappedStorageFile const & file,uint32_t index)171 Result<bool> get_boolean_flag_value(
172 MappedStorageFile const& file,
173 uint32_t index) {
174 auto content = rust::Slice<const uint8_t>(
175 static_cast<uint8_t*>(file.file_ptr), file.file_size);
176 auto value_cxx = get_boolean_flag_value_cxx(content, index);
177 if (value_cxx.query_success) {
178 return value_cxx.flag_value;
179 } else {
180 auto result = Result<bool>();
181 result.errmsg = value_cxx.error_message.c_str();
182 return result;
183 }
184 }
185
186 /// Get boolean flag attribute
get_flag_attribute(MappedStorageFile const & file,FlagValueType value_type,uint32_t index)187 Result<uint8_t> get_flag_attribute(
188 MappedStorageFile const& file,
189 FlagValueType value_type,
190 uint32_t index) {
191 auto content = rust::Slice<const uint8_t>(
192 static_cast<uint8_t*>(file.file_ptr), file.file_size);
193 auto info_cxx = get_flag_attribute_cxx(
194 content, static_cast<uint16_t>(value_type), index);
195 if (info_cxx.query_success) {
196 return info_cxx.flag_attribute;
197 } else {
198 auto result = Result<uint8_t>();
199 result.errmsg = info_cxx.error_message.c_str();
200 return result;
201 }
202 }
203 } // namespace aconfig_storage
204