Move libsystemproperties to external

This commit is contained in:
topjohnwu
2020-12-31 15:06:19 -08:00
parent f9bde347bc
commit 4e97b18977
30 changed files with 3 additions and 2 deletions

View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _INCLUDE_SYS__SYSTEM_PROPERTIES_H
#define _INCLUDE_SYS__SYSTEM_PROPERTIES_H
#include <sys/cdefs.h>
#include <stdint.h>
#ifndef _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#error you should #include <sys/system_properties.h> instead
#endif
//#include <sys/system_properties.h>
#include "system_properties.h"
__BEGIN_DECLS
#define PROP_SERVICE_NAME "property_service"
#define PROP_FILENAME "/dev/__properties__"
#define PROP_MSG_SETPROP 1
#define PROP_MSG_SETPROP2 0x00020001
#define PROP_SUCCESS 0
#define PROP_ERROR_READ_CMD 0x0004
#define PROP_ERROR_READ_DATA 0x0008
#define PROP_ERROR_READ_ONLY_PROPERTY 0x000B
#define PROP_ERROR_INVALID_NAME 0x0010
#define PROP_ERROR_INVALID_VALUE 0x0014
#define PROP_ERROR_PERMISSION_DENIED 0x0018
#define PROP_ERROR_INVALID_CMD 0x001B
#define PROP_ERROR_HANDLE_CONTROL_MESSAGE 0x0020
#define PROP_ERROR_SET_FAILED 0x0024
/*
** This was previously for testing, but now that SystemProperties is its own testable class,
** there is never a reason to call this function and its implementation simply returns -1.
*/
int __system_property_set_filename(const char* __filename);
/*
** Initialize the area to be used to store properties. Can
** only be done by a single process that has write access to
** the property area.
*/
int __system_property_area_init(void);
/* Read the global serial number of the system properties
**
** Called to predict if a series of cached __system_property_find
** objects will have seen __system_property_serial values change.
** But also aids the converse, as changes in the global serial can
** also be used to predict if a failed __system_property_find
** could in-turn now find a new object; thus preventing the
** cycles of effort to poll __system_property_find.
**
** Typically called at beginning of a cache cycle to signal if _any_ possible
** changes have occurred since last. If there is, one may check each individual
** __system_property_serial to confirm dirty, or __system_property_find
** to check if the property now exists. If a call to __system_property_add
** or __system_property_update has completed between two calls to
** __system_property_area_serial then the second call will return a larger
** value than the first call. Beware of race conditions as changes to the
** properties are not atomic, the main value of this call is to determine
** whether the expensive __system_property_find is worth retrying to see if
** a property now exists.
**
** Returns the serial number on success, -1 on error.
*/
uint32_t __system_property_area_serial(void);
/* Add a new system property. Can only be done by a single
** process that has write access to the property area, and
** that process must handle sequencing to ensure the property
** does not already exist and that only one property is added
** or updated at a time.
**
** Returns 0 on success, -1 if the property area is full.
*/
int __system_property_add(const char* __name, unsigned int __name_length, const char* __value, unsigned int __value_length);
/* Delete a system property. Added in resetprop
**
** Returns 0 on success, -1 if the property area is full.
*/
int __system_property_delete(const char *__name);
/* Update the value of a system property returned by
** __system_property_find. Can only be done by a single process
** that has write access to the property area, and that process
** must handle sequencing to ensure that only one property is
** updated at a time.
**
** Returns 0 on success, -1 if the parameters are incorrect.
*/
int __system_property_update(prop_info* __pi, const char* __value, unsigned int __value_length);
/* Read the serial number of a system property returned by
** __system_property_find.
**
** Returns the serial number on success, -1 on error.
*/
uint32_t __system_property_serial(const prop_info* __pi);
/* Initialize the system properties area in read only mode.
* Should be done by all processes that need to read system
* properties.
*
* Returns 0 on success, -1 otherwise.
*/
int __system_properties_init(void);
/* Deprecated: use __system_property_wait instead. */
uint32_t __system_property_wait_any(uint32_t __old_serial);
__END_DECLS
#endif

View File

@@ -0,0 +1,4 @@
#pragma once
#define async_safe_format_buffer snprintf
#define async_safe_format_log(...) /* NOP */

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2013 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.
*/
#pragma once
#include <errno.h>
#include "bionic_macros.h"
class ErrnoRestorer {
public:
explicit ErrnoRestorer() : saved_errno_(errno) {
}
~ErrnoRestorer() {
errno = saved_errno_;
}
void override(int new_errno) {
saved_errno_ = new_errno;
}
private:
int saved_errno_;
BIONIC_DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer);
};

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2017 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __BIONIC_PRIVATE_BIONIC_DEFS_H_
#define __BIONIC_PRIVATE_BIONIC_DEFS_H_
/*
* This label is used to mark libc/libdl symbols that may need to be replaced
* by native bridge implementation.
*/
#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE __attribute__((__weak__, __noinline__))
#define __BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE __attribute__((__weak__))
#endif /* __BIONIC_PRIVATE_BIONIC_DEFS_H_ */

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _BIONIC_FUTEX_H
#define _BIONIC_FUTEX_H
#include <errno.h>
#include <linux/futex.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/cdefs.h>
#include <sys/syscall.h>
#include <unistd.h>
struct timespec;
static inline __always_inline int __futex(volatile void* ftx, int op, int value,
const timespec* timeout, int bitset) {
// Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
int saved_errno = errno;
int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);
if (__predict_false(result == -1)) {
result = -errno;
errno = saved_errno;
}
return result;
}
static inline int __futex_wake(volatile void* ftx, int count) {
return __futex(ftx, FUTEX_WAKE, count, nullptr, 0);
}
static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {
return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, nullptr, 0);
}
static inline int __futex_wait(volatile void* ftx, int value, const timespec* timeout) {
return __futex(ftx, FUTEX_WAIT, value, timeout, 0);
}
static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value) {
return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value, nullptr,
FUTEX_BITSET_MATCH_ANY);
}
__LIBC_HIDDEN__ int __futex_wait_ex(volatile void* ftx, bool shared, int value,
bool use_realtime_clock, const timespec* abs_timeout);
static inline int __futex_pi_unlock(volatile void* ftx, bool shared) {
return __futex(ftx, shared ? FUTEX_UNLOCK_PI : FUTEX_UNLOCK_PI_PRIVATE, 0, nullptr, 0);
}
__LIBC_HIDDEN__ int __futex_pi_lock_ex(volatile void* ftx, bool shared, bool use_realtime_clock,
const timespec* abs_timeout);
#endif /* _BIONIC_FUTEX_H */

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <stdatomic.h>
#include "private/bionic_futex.h"
#include "private/bionic_macros.h"
// Lock is used in places like pthread_rwlock_t, which can be initialized without calling
// an initialization function. So make sure Lock can be initialized by setting its memory to 0.
class Lock {
private:
enum LockState {
Unlocked = 0,
LockedWithoutWaiter,
LockedWithWaiter,
};
_Atomic(LockState) state;
bool process_shared;
public:
void init(bool process_shared) {
atomic_init(&state, Unlocked);
this->process_shared = process_shared;
}
bool trylock() {
LockState old_state = Unlocked;
return __predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed));
}
void lock() {
LockState old_state = Unlocked;
if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed))) {
return;
}
while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
// TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
__futex_wait_ex(&state, process_shared, LockedWithWaiter);
}
return;
}
void unlock() {
bool shared = process_shared; /* cache to local variable */
if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) {
__futex_wake_ex(&state, shared, 1);
}
}
};
class LockGuard {
public:
explicit LockGuard(Lock& lock) : lock_(lock) {
lock_.lock();
}
~LockGuard() {
lock_.unlock();
}
BIONIC_DISALLOW_COPY_AND_ASSIGN(LockGuard);
private:
Lock& lock_;
};

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2010 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.
*/
#pragma once
#include <stdint.h>
#define BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&) = delete; \
void operator=(const TypeName&) = delete
#define BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
TypeName() = delete; \
BIONIC_DISALLOW_COPY_AND_ASSIGN(TypeName)
#define BIONIC_ROUND_UP_POWER_OF_2(value) \
((sizeof(value) == 8) \
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
static constexpr uintptr_t align_down(uintptr_t p, size_t align) {
return p & ~(align - 1);
}
static constexpr uintptr_t align_up(uintptr_t p, size_t align) {
return (p + align - 1) & ~(align - 1);
}
template <typename T>
static inline T* align_down(T* p, size_t align) {
return reinterpret_cast<T*>(align_down(reinterpret_cast<uintptr_t>(p), align));
}
template <typename T>
static inline T* align_up(T* p, size_t align) {
return reinterpret_cast<T*>(align_up(reinterpret_cast<uintptr_t>(p), align));
}
#if defined(__arm__)
// Do not emit anything for arm, clang does not allow emiting an arm unwind
// directive.
// #define BIONIC_STOP_UNWIND asm volatile(".cantunwind")
#define BIONIC_STOP_UNWIND
#elif defined(__aarch64__)
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined x30")
#elif defined(__i386__)
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%eip")
#elif defined(__x86_64__)
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%rip")
#elif defined (__mips__)
#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined $ra")
#endif
// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example. If you use arraysize on
// a pointer by mistake, you will get a compile-time error.
//
// One caveat is that arraysize() doesn't accept any array of an
// anonymous type or a type defined inside a function.
//
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
// Used to inform clang's -Wimplicit-fallthrough that a fallthrough is intended. There's no way to
// silence (or enable, apparently) -Wimplicit-fallthrough in C yet.
#ifdef __cplusplus
#define __BIONIC_FALLTHROUGH [[clang::fallthrough]]
#else
#define __BIONIC_FALLTHROUGH
#endif

View File

@@ -0,0 +1,35 @@
#pragma once
#include <stdio.h>
#include <syscall.h>
// Missing defines
#ifndef PR_SET_VMA
#define PR_SET_VMA 0x53564d41
#endif
#ifndef PR_SET_VMA_ANON_NAME
#define PR_SET_VMA_ANON_NAME 0
#endif
// Missing functions
#define fsetxattr(...) syscall(__NR_fsetxattr, __VA_ARGS__)
#define getline compat_getline
ssize_t compat_getline(char **, size_t *, FILE *);
// Rename symbols
#pragma redefine_extname __system_property_set _system_property_set2
#pragma redefine_extname __system_property_find _system_property_find2
#pragma redefine_extname __system_property_read_callback _system_property_read_callback2
#pragma redefine_extname __system_property_foreach __system_property_foreach2
#pragma redefine_extname __system_property_wait __system_property_wait2
#pragma redefine_extname __system_property_read __system_property_read2
#pragma redefine_extname __system_property_get __system_property_get2
#pragma redefine_extname __system_property_find_nth __system_property_find_nth2
#pragma redefine_extname __system_property_set_filename __system_property_set_filename2
#pragma redefine_extname __system_property_area_init __system_property_area_init2
#pragma redefine_extname __system_property_area_serial __system_property_area_serial2
#pragma redefine_extname __system_property_add __system_property_add2
#pragma redefine_extname __system_property_update __system_property_update2
#pragma redefine_extname __system_property_serial __system_property_serial2
#pragma redefine_extname __system_properties_init __system_properties_init2
#pragma redefine_extname __system_property_wait_any __system_property_wait_any2

View File

@@ -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

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _INCLUDE_SYS_SYSTEM_PROPERTIES_H
#define _INCLUDE_SYS_SYSTEM_PROPERTIES_H
#include <sys/cdefs.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "private/hacks.h"
__BEGIN_DECLS
typedef struct prop_info prop_info;
#define PROP_VALUE_MAX 92
/*
* Sets system property `name` to `value`, creating the system property if it doesn't already exist.
*/
int __system_property_set(const char* __name, const char* __value) __INTRODUCED_IN(12);
/*
* Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist.
* Use __system_property_read_callback to query the current value.
*
* Property lookup is expensive, so it can be useful to cache the result of this function.
*/
const prop_info* __system_property_find(const char* __name);
/*
* Calls `callback` with a consistent trio of name, value, and serial number for property `pi`.
*/
void __system_property_read_callback(const prop_info* __pi,
void (*__callback)(void* __cookie, const char* __name, const char* __value, uint32_t __serial),
void* __cookie) __INTRODUCED_IN(26);
/*
* Passes a `prop_info` for each system property to the provided
* callback. Use __system_property_read_callback() to read the value.
*
* This method is for inspecting and debugging the property system, and not generally useful.
*/
int __system_property_foreach(void (*__callback)(const prop_info* __pi, void* __cookie), void* __cookie)
__INTRODUCED_IN(19);
/*
* Waits for the specific system property identified by `pi` to be updated
* past `old_serial`. Waits no longer than `relative_timeout`, or forever
* if `relaive_timeout` is null.
*
* If `pi` is null, waits for the global serial number instead.
*
* If you don't know the current serial, use 0.
*
* Returns true and updates `*new_serial_ptr` on success, or false if the call
* timed out.
*/
struct timespec;
bool __system_property_wait(const prop_info* __pi, uint32_t __old_serial, uint32_t* __new_serial_ptr, const struct timespec* __relative_timeout)
__INTRODUCED_IN(26);
/* Deprecated. In Android O and above, there's no limit on property name length. */
#define PROP_NAME_MAX 32
/* Deprecated. Use __system_property_read_callback instead. */
int __system_property_read(const prop_info* __pi, char* __name, char* __value);
/* Deprecated. Use __system_property_read_callback instead. */
int __system_property_get(const char* __name, char* __value);
/* Deprecated. Use __system_property_foreach instead. */
const prop_info* __system_property_find_nth(unsigned __n);
__END_DECLS
#endif

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include "private/bionic_lock.h"
#include "prop_area.h"
class ContextNode {
public:
ContextNode(const char* context, const char* filename)
: context_(context), pa_(nullptr), no_access_(false), filename_(filename) {
lock_.init(false);
}
~ContextNode() {
Unmap();
}
BIONIC_DISALLOW_COPY_AND_ASSIGN(ContextNode);
bool Open(bool access_rw, bool* fsetxattr_failed);
bool CheckAccessAndOpen();
void ResetAccess();
void Unmap();
const char* context() const {
return context_;
}
prop_area* pa() {
return pa_;
}
private:
bool CheckAccess();
Lock lock_;
const char* context_;
prop_area* pa_;
bool no_access_;
const char* filename_;
};

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include "prop_area.h"
#include "prop_info.h"
class Contexts {
public:
virtual ~Contexts() {
}
virtual bool Initialize(bool writable, const char* filename, bool* fsetxattr_failed) = 0;
virtual prop_area* GetPropAreaForName(const char* name) = 0;
virtual prop_area* GetSerialPropArea() = 0;
virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) = 0;
virtual void ResetAccess() = 0;
virtual void FreeAndUnmap() = 0;
};

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include "contexts.h"
#include "prop_area.h"
#include "prop_info.h"
class ContextsPreSplit : public Contexts {
public:
virtual ~ContextsPreSplit() override {
}
// We'll never initialize this legacy option as writable, so don't even check the arg.
virtual bool Initialize(bool, const char* filename, bool*) override {
pre_split_prop_area_ = prop_area::map_prop_area(filename);
return pre_split_prop_area_ != nullptr;
}
virtual prop_area* GetPropAreaForName(const char*) override {
return pre_split_prop_area_;
}
virtual prop_area* GetSerialPropArea() override {
return pre_split_prop_area_;
}
virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override {
pre_split_prop_area_->foreach (propfn, cookie);
}
// This is a no-op for pre-split properties as there is only one property file and it is
// accessible by all domains
virtual void ResetAccess() override {
}
virtual void FreeAndUnmap() override {
prop_area::unmap_prop_area(&pre_split_prop_area_);
}
private:
prop_area* pre_split_prop_area_ = nullptr;
};

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2017 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <property_info_parser/property_info_parser.h>
#include "context_node.h"
#include "contexts.h"
class ContextsSerialized : public Contexts {
public:
virtual ~ContextsSerialized() override {
}
virtual bool Initialize(bool writable, const char* filename, bool* fsetxattr_failed) override;
virtual prop_area* GetPropAreaForName(const char* name) override;
virtual prop_area* GetSerialPropArea() override {
return serial_prop_area_;
}
virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override;
virtual void ResetAccess() override;
virtual void FreeAndUnmap() override;
private:
bool InitializeContextNodes();
bool InitializeProperties();
bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
const char* filename_;
android::properties::PropertyInfoAreaFile property_info_area_file_;
ContextNode* context_nodes_ = nullptr;
size_t num_context_nodes_ = 0;
size_t context_nodes_mmap_size_ = 0;
prop_area* serial_prop_area_ = nullptr;
};

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include "contexts.h"
struct PrefixNode;
class ContextListNode;
class ContextsSplit : public Contexts {
public:
virtual ~ContextsSplit() override {
}
virtual bool Initialize(bool writable, const char* filename, bool* fsetxattr_failed) override;
virtual prop_area* GetPropAreaForName(const char* name) override;
virtual prop_area* GetSerialPropArea() override {
return serial_prop_area_;
}
virtual void ForEach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) override;
virtual void ResetAccess() override;
virtual void FreeAndUnmap() override;
private:
bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
bool InitializePropertiesFromFile(const char* filename);
bool InitializeProperties();
PrefixNode* prefixes_ = nullptr;
ContextListNode* contexts_ = nullptr;
prop_area* serial_prop_area_ = nullptr;
const char* filename_ = nullptr;
};

View File

@@ -0,0 +1,167 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <stdatomic.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#include "private/bionic_macros.h"
#include "prop_info.h"
// Properties are stored in a hybrid trie/binary tree structure.
// Each property's name is delimited at '.' characters, and the tokens are put
// into a trie structure. Siblings at each level of the trie are stored in a
// binary tree. For instance, "ro.secure"="1" could be stored as follows:
//
// +-----+ children +----+ children +--------+
// | |-------------->| ro |-------------->| secure |
// +-----+ +----+ +--------+
// / \ / |
// left / \ right left / | prop +===========+
// v v v +-------->| ro.secure |
// +-----+ +-----+ +-----+ +-----------+
// | net | | sys | | com | | 1 |
// +-----+ +-----+ +-----+ +===========+
// Represents a node in the trie.
struct prop_bt {
uint32_t namelen;
// The property trie is updated only by the init process (single threaded) which provides
// property service. And it can be read by multiple threads at the same time.
// As the property trie is not protected by locks, we use atomic_uint_least32_t types for the
// left, right, children "pointers" in the trie node. To make sure readers who see the
// change of "pointers" can also notice the change of prop_bt structure contents pointed by
// the "pointers", we always use release-consume ordering pair when accessing these "pointers".
// prop "points" to prop_info structure if there is a propery associated with the trie node.
// Its situation is similar to the left, right, children "pointers". So we use
// atomic_uint_least32_t and release-consume ordering to protect it as well.
// We should also avoid rereading these fields redundantly, since not
// all processor implementations ensure that multiple loads from the
// same field are carried out in the right order.
atomic_uint_least32_t prop;
atomic_uint_least32_t left;
atomic_uint_least32_t right;
atomic_uint_least32_t children;
char name[0];
prop_bt(const char* name, const uint32_t name_length) {
this->namelen = name_length;
memcpy(this->name, name, name_length);
this->name[name_length] = '\0';
}
private:
BIONIC_DISALLOW_COPY_AND_ASSIGN(prop_bt);
};
class prop_area {
public:
static prop_area* map_prop_area_rw(const char* filename, const char* context,
bool* fsetxattr_failed);
static prop_area* map_prop_area(const char* filename);
static void unmap_prop_area(prop_area** pa) {
if (*pa) {
munmap(*pa, pa_size_);
*pa = nullptr;
}
}
prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
atomic_init(&serial_, 0u);
memset(reserved_, 0, sizeof(reserved_));
// Allocate enough space for the root node.
bytes_used_ = sizeof(prop_bt);
}
const prop_info* find(const char* name);
bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
/* resetprop */
bool del(const char *name);
bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
atomic_uint_least32_t* serial() {
return &serial_;
}
uint32_t magic() const {
return magic_;
}
uint32_t version() const {
return version_;
}
private:
static prop_area* map_fd_rw(const int fd);
void* allocate_obj(const size_t size, uint_least32_t* const off);
prop_bt* new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off);
prop_info* new_prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen,
uint_least32_t* const off);
void* to_prop_obj(uint_least32_t off);
prop_bt* to_prop_bt(atomic_uint_least32_t* off_p);
prop_info* to_prop_info(atomic_uint_least32_t* off_p);
prop_bt* root_node();
/* resetprop: Traverse through the trie and find the node */
prop_bt *find_prop_bt(prop_bt *const bt, const char* name, bool alloc_if_needed);
prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed);
const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
const char* value, uint32_t valuelen, bool alloc_if_needed);
bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
void* cookie);
// The original design doesn't include pa_size or pa_data_size in the prop_area struct itself.
// Since we'll need to be backwards compatible with that design, we don't gain much by adding it
// now, especially since we don't have any plans to make different property areas different sizes,
// and thus we share these two variables among all instances.
static size_t pa_size_;
static size_t pa_data_size_;
uint32_t bytes_used_;
atomic_uint_least32_t serial_;
uint32_t magic_;
uint32_t version_;
uint32_t reserved_[28];
char data_[0];
BIONIC_DISALLOW_COPY_AND_ASSIGN(prop_area);
};

View File

@@ -0,0 +1,90 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <stdatomic.h>
#include <stdint.h>
//#include <sys/system_properties.h>
#include "../system_properties.h"
#include "private/bionic_macros.h"
// The C11 standard doesn't allow atomic loads from const fields,
// though C++11 does. Fudge it until standards get straightened out.
static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, memory_order mo) {
atomic_uint_least32_t* non_const_s = const_cast<atomic_uint_least32_t*>(s);
return atomic_load_explicit(non_const_s, mo);
}
struct prop_info {
// Read only properties will not set anything but the bottom most bit of serial and the top byte.
// We borrow the 2nd from the top byte for extra flags, and use the bottom most bit of that for
// our first user, kLongFlag.
constexpr static uint32_t kLongFlag = 1 << 16;
// The error message fits in part of a union with the previous 92 char property value so there
// must be room left over after the error message for the offset to the new longer property value
// and future expansion fields if needed. Note that this value cannot ever increase. The offset
// to the new longer property value appears immediately after it, so an increase of this size will
// break compatibility.
constexpr static size_t kLongLegacyErrorBufferSize = 56;
public:
atomic_uint_least32_t serial;
// we need to keep this buffer around because the property
// value can be modified whereas name is constant.
union {
char value[PROP_VALUE_MAX];
struct {
char error_message[kLongLegacyErrorBufferSize];
uint32_t offset;
} long_property;
};
char name[0];
bool is_long() const {
return (load_const_atomic(&serial, memory_order_relaxed) & kLongFlag) != 0;
}
const char* long_value() const {
// We can't store pointers here since this is shared memory that will have different absolute
// pointers in different processes. We don't have data_ from prop_area, but since we know
// `this` is data_ + some offset and long_value is data_ + some other offset, we calculate the
// offset from `this` to long_value and store it as long_property.offset.
return reinterpret_cast<const char*>(this) + long_property.offset;
}
prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen);
prop_info(const char* name, uint32_t namelen, uint32_t long_offset);
private:
BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
};
static_assert(sizeof(prop_info) == 96, "sizeof struct prop_info must be 96 bytes");

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma once
#include <stdint.h>
#include <sys/param.h>
//#include <sys/system_properties.h>
#include "../system_properties.h"
#include "contexts.h"
#include "contexts_pre_split.h"
#include "contexts_serialized.h"
#include "contexts_split.h"
constexpr int PROP_FILENAME_MAX = 1024;
class SystemProperties {
public:
friend struct LocalPropertyTestState;
friend class SystemPropertiesTest;
// Note that system properties are initialized before libc calls static initializers, so
// doing any initialization in this constructor is an error. Even a Constructor that zero
// initializes this class will clobber the previous property initialization.
// We rely on the static SystemProperties in libc to be placed in .bss and zero initialized.
SystemProperties() = default;
// Special constructor for testing that also zero initializes the important members.
explicit SystemProperties(bool initialized) : initialized_(initialized) {
}
BIONIC_DISALLOW_COPY_AND_ASSIGN(SystemProperties);
bool Init(const char* filename);
bool AreaInit(const char* filename, bool* fsetxattr_failed);
uint32_t AreaSerial();
const prop_info* Find(const char* name);
int Read(const prop_info* pi, char* name, char* value);
void ReadCallback(const prop_info* pi,
void (*callback)(void* cookie, const char* name, const char* value,
uint32_t serial),
void* cookie);
int Get(const char* name, char* value);
int Update(prop_info* pi, const char* value, unsigned int len);
int Add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
int Delete(const char *name);
uint32_t Serial(const prop_info* pi);
uint32_t WaitAny(uint32_t old_serial);
bool Wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr,
const timespec* relative_timeout);
const prop_info* FindNth(unsigned n);
int Foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
private:
// We don't want to use new or malloc in properties (b/31659220), and we don't want to waste a
// full page by using mmap(), so we set aside enough space to create any context of the three
// contexts.
static constexpr size_t kMaxContextsAlign =
MAX(alignof(ContextsSerialized), MAX(alignof(ContextsSplit), alignof(ContextsPreSplit)));
static constexpr size_t kMaxContextsSize =
MAX(sizeof(ContextsSerialized), MAX(sizeof(ContextsSplit), sizeof(ContextsPreSplit)));
alignas(kMaxContextsAlign) char contexts_data_[kMaxContextsSize];
Contexts* contexts_;
bool initialized_;
char property_filename_[PROP_FILENAME_MAX];
};