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