mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-12 05:07:45 +02:00
Separate libutils and libsystemproperties
This commit is contained in:
@ -0,0 +1,224 @@
|
||||
//
|
||||
// Copyright (C) 2017 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef PROPERTY_INFO_PARSER_H
|
||||
#define PROPERTY_INFO_PARSER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace android {
|
||||
namespace properties {
|
||||
|
||||
// The below structs intentionally do not end with char name[0] or other tricks to allocate
|
||||
// with a dynamic size, such that they can be added onto in the future without breaking
|
||||
// backwards compatibility.
|
||||
struct PropertyEntry {
|
||||
uint32_t name_offset;
|
||||
uint32_t namelen;
|
||||
|
||||
// This is the context match for this node_; ~0u if it doesn't correspond to any.
|
||||
uint32_t context_index;
|
||||
// This is the type for this node_; ~0u if it doesn't correspond to any.
|
||||
uint32_t type_index;
|
||||
};
|
||||
|
||||
struct TrieNodeInternal {
|
||||
// This points to a property entry struct, which includes the name for this node
|
||||
uint32_t property_entry;
|
||||
|
||||
// Children are a sorted list of child nodes_; binary search them.
|
||||
uint32_t num_child_nodes;
|
||||
uint32_t child_nodes;
|
||||
|
||||
// Prefixes are terminating prefix matches at this node, sorted longest to smallest
|
||||
// Take the first match sequentially found with StartsWith().
|
||||
uint32_t num_prefixes;
|
||||
uint32_t prefix_entries;
|
||||
|
||||
// Exact matches are a sorted list of exact matches at this node_; binary search them.
|
||||
uint32_t num_exact_matches;
|
||||
uint32_t exact_match_entries;
|
||||
};
|
||||
|
||||
struct PropertyInfoAreaHeader {
|
||||
// The current version of this data as created by property service.
|
||||
uint32_t current_version;
|
||||
// The lowest version of libc that can properly parse this data.
|
||||
uint32_t minimum_supported_version;
|
||||
uint32_t size;
|
||||
uint32_t contexts_offset;
|
||||
uint32_t types_offset;
|
||||
uint32_t root_offset;
|
||||
};
|
||||
|
||||
class SerializedData {
|
||||
public:
|
||||
uint32_t size() const {
|
||||
return reinterpret_cast<const PropertyInfoAreaHeader*>(data_base_)->size;
|
||||
}
|
||||
|
||||
const char* c_string(uint32_t offset) const {
|
||||
if (offset != 0 && offset > size()) return nullptr;
|
||||
return static_cast<const char*>(data_base_ + offset);
|
||||
}
|
||||
|
||||
const uint32_t* uint32_array(uint32_t offset) const {
|
||||
if (offset != 0 && offset > size()) return nullptr;
|
||||
return reinterpret_cast<const uint32_t*>(data_base_ + offset);
|
||||
}
|
||||
|
||||
uint32_t uint32(uint32_t offset) const {
|
||||
if (offset != 0 && offset > size()) return ~0u;
|
||||
return *reinterpret_cast<const uint32_t*>(data_base_ + offset);
|
||||
}
|
||||
|
||||
const char* data_base() const { return data_base_; }
|
||||
|
||||
private:
|
||||
const char data_base_[0];
|
||||
};
|
||||
|
||||
class TrieNode {
|
||||
public:
|
||||
TrieNode() : serialized_data_(nullptr), trie_node_base_(nullptr) {}
|
||||
TrieNode(const SerializedData* data_base, const TrieNodeInternal* trie_node_base)
|
||||
: serialized_data_(data_base), trie_node_base_(trie_node_base) {}
|
||||
|
||||
const char* name() const {
|
||||
return serialized_data_->c_string(node_property_entry()->name_offset);
|
||||
}
|
||||
|
||||
uint32_t context_index() const { return node_property_entry()->context_index; }
|
||||
uint32_t type_index() const { return node_property_entry()->type_index; }
|
||||
|
||||
uint32_t num_child_nodes() const { return trie_node_base_->num_child_nodes; }
|
||||
TrieNode child_node(int n) const {
|
||||
uint32_t child_node_offset = serialized_data_->uint32_array(trie_node_base_->child_nodes)[n];
|
||||
const TrieNodeInternal* trie_node_base =
|
||||
reinterpret_cast<const TrieNodeInternal*>(serialized_data_->data_base() + child_node_offset);
|
||||
return TrieNode(serialized_data_, trie_node_base);
|
||||
}
|
||||
|
||||
bool FindChildForString(const char* input, uint32_t namelen, TrieNode* child) const;
|
||||
|
||||
uint32_t num_prefixes() const { return trie_node_base_->num_prefixes; }
|
||||
const PropertyEntry* prefix(int n) const {
|
||||
uint32_t prefix_entry_offset =
|
||||
serialized_data_->uint32_array(trie_node_base_->prefix_entries)[n];
|
||||
return reinterpret_cast<const PropertyEntry*>(serialized_data_->data_base() +
|
||||
prefix_entry_offset);
|
||||
}
|
||||
|
||||
uint32_t num_exact_matches() const { return trie_node_base_->num_exact_matches; }
|
||||
const PropertyEntry* exact_match(int n) const {
|
||||
uint32_t exact_match_entry_offset =
|
||||
serialized_data_->uint32_array(trie_node_base_->exact_match_entries)[n];
|
||||
return reinterpret_cast<const PropertyEntry*>(serialized_data_->data_base() +
|
||||
exact_match_entry_offset);
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyEntry* node_property_entry() const {
|
||||
return reinterpret_cast<const PropertyEntry*>(serialized_data_->data_base() +
|
||||
trie_node_base_->property_entry);
|
||||
}
|
||||
|
||||
const SerializedData* serialized_data_;
|
||||
const TrieNodeInternal* trie_node_base_;
|
||||
};
|
||||
|
||||
class PropertyInfoArea : private SerializedData {
|
||||
public:
|
||||
void GetPropertyInfoIndexes(const char* name, uint32_t* context_index, uint32_t* type_index) const;
|
||||
void GetPropertyInfo(const char* property, const char** context, const char** type) const;
|
||||
|
||||
int FindContextIndex(const char* context) const;
|
||||
int FindTypeIndex(const char* type) const;
|
||||
|
||||
const char* context(uint32_t index) const {
|
||||
uint32_t context_array_size_offset = contexts_offset();
|
||||
const uint32_t* context_array = uint32_array(context_array_size_offset + sizeof(uint32_t));
|
||||
return data_base() + context_array[index];
|
||||
}
|
||||
|
||||
const char* type(uint32_t index) const {
|
||||
uint32_t type_array_size_offset = types_offset();
|
||||
const uint32_t* type_array = uint32_array(type_array_size_offset + sizeof(uint32_t));
|
||||
return data_base() + type_array[index];
|
||||
}
|
||||
|
||||
uint32_t current_version() const { return header()->current_version; }
|
||||
uint32_t minimum_supported_version() const { return header()->minimum_supported_version; }
|
||||
|
||||
uint32_t size() const { return SerializedData::size(); }
|
||||
|
||||
uint32_t num_contexts() const { return uint32_array(contexts_offset())[0]; }
|
||||
uint32_t num_types() const { return uint32_array(types_offset())[0]; }
|
||||
|
||||
TrieNode root_node() const { return trie(header()->root_offset); }
|
||||
|
||||
private:
|
||||
void CheckPrefixMatch(const char* remaining_name, const TrieNode& trie_node,
|
||||
uint32_t* context_index, uint32_t* type_index) const;
|
||||
|
||||
const PropertyInfoAreaHeader* header() const {
|
||||
return reinterpret_cast<const PropertyInfoAreaHeader*>(data_base());
|
||||
}
|
||||
uint32_t contexts_offset() const { return header()->contexts_offset; }
|
||||
uint32_t contexts_array_offset() const { return contexts_offset() + sizeof(uint32_t); }
|
||||
uint32_t types_offset() const { return header()->types_offset; }
|
||||
uint32_t types_array_offset() const { return types_offset() + sizeof(uint32_t); }
|
||||
|
||||
TrieNode trie(uint32_t offset) const {
|
||||
if (offset != 0 && offset > size()) return TrieNode();
|
||||
const TrieNodeInternal* trie_node_base =
|
||||
reinterpret_cast<const TrieNodeInternal*>(data_base() + offset);
|
||||
return TrieNode(this, trie_node_base);
|
||||
}
|
||||
};
|
||||
|
||||
// This is essentially a smart pointer for read only mmap region for property contexts.
|
||||
class PropertyInfoAreaFile {
|
||||
public:
|
||||
PropertyInfoAreaFile() : mmap_base_(nullptr), mmap_size_(0) {}
|
||||
~PropertyInfoAreaFile() { Reset(); }
|
||||
|
||||
PropertyInfoAreaFile(const PropertyInfoAreaFile&) = delete;
|
||||
void operator=(const PropertyInfoAreaFile&) = delete;
|
||||
PropertyInfoAreaFile(PropertyInfoAreaFile&&) = default;
|
||||
PropertyInfoAreaFile& operator=(PropertyInfoAreaFile&&) = default;
|
||||
|
||||
bool LoadDefaultPath();
|
||||
bool LoadPath(const char* filename);
|
||||
|
||||
const PropertyInfoArea* operator->() const {
|
||||
return reinterpret_cast<const PropertyInfoArea*>(mmap_base_);
|
||||
}
|
||||
|
||||
explicit operator bool() const { return mmap_base_ != nullptr; }
|
||||
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
void* mmap_base_;
|
||||
size_t mmap_size_;
|
||||
};
|
||||
|
||||
} // namespace properties
|
||||
} // namespace android
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user