blob: 10c1adbec846ec6cee7e67a008c1669d7d0459d9 [file] [log] [blame]
Tom Cherryfd44b9f2017-11-08 14:01:00 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <stdatomic.h>
30#include <stdint.h>
31#include <string.h>
Tom Cherryf76bbf52017-11-08 14:01:00 -080032#include <sys/mman.h>
Tom Cherryfd44b9f2017-11-08 14:01:00 -080033
34#include "private/bionic_macros.h"
35
36#include "prop_info.h"
37
38#ifndef SYSTEM_PROPERTIES_PROP_AREA_H
39#define SYSTEM_PROPERTIES_PROP_AREA_H
40
41// Properties are stored in a hybrid trie/binary tree structure.
42// Each property's name is delimited at '.' characters, and the tokens are put
43// into a trie structure. Siblings at each level of the trie are stored in a
44// binary tree. For instance, "ro.secure"="1" could be stored as follows:
45//
46// +-----+ children +----+ children +--------+
47// | |-------------->| ro |-------------->| secure |
48// +-----+ +----+ +--------+
49// / \ / |
50// left / \ right left / | prop +===========+
51// v v v +-------->| ro.secure |
52// +-----+ +-----+ +-----+ +-----------+
53// | net | | sys | | com | | 1 |
54// +-----+ +-----+ +-----+ +===========+
55
56// Represents a node in the trie.
57struct prop_bt {
58 uint32_t namelen;
59
60 // The property trie is updated only by the init process (single threaded) which provides
61 // property service. And it can be read by multiple threads at the same time.
62 // As the property trie is not protected by locks, we use atomic_uint_least32_t types for the
63 // left, right, children "pointers" in the trie node. To make sure readers who see the
64 // change of "pointers" can also notice the change of prop_bt structure contents pointed by
65 // the "pointers", we always use release-consume ordering pair when accessing these "pointers".
66
67 // prop "points" to prop_info structure if there is a propery associated with the trie node.
68 // Its situation is similar to the left, right, children "pointers". So we use
69 // atomic_uint_least32_t and release-consume ordering to protect it as well.
70
71 // We should also avoid rereading these fields redundantly, since not
72 // all processor implementations ensure that multiple loads from the
73 // same field are carried out in the right order.
74 atomic_uint_least32_t prop;
75
76 atomic_uint_least32_t left;
77 atomic_uint_least32_t right;
78
79 atomic_uint_least32_t children;
80
81 char name[0];
82
83 prop_bt(const char* name, const uint32_t name_length) {
84 this->namelen = name_length;
85 memcpy(this->name, name, name_length);
86 this->name[name_length] = '\0';
87 }
88
89 private:
90 DISALLOW_COPY_AND_ASSIGN(prop_bt);
91};
92
93class prop_area {
94 public:
95 static prop_area* map_prop_area_rw(const char* filename, const char* context,
96 bool* fsetxattr_failed);
97 static prop_area* map_prop_area(const char* filename);
Tom Cherryf76bbf52017-11-08 14:01:00 -080098 static void unmap_prop_area(prop_area** pa) {
99 if (*pa) {
100 munmap(*pa, pa_size_);
101 *pa = nullptr;
102 }
103 }
Tom Cherryfd44b9f2017-11-08 14:01:00 -0800104
105 prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
106 atomic_init(&serial_, 0);
107 memset(reserved_, 0, sizeof(reserved_));
108 // Allocate enough space for the root node.
109 bytes_used_ = sizeof(prop_bt);
110 }
111
112 const prop_info* find(const char* name);
113 bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen);
114
115 bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie);
116
117 atomic_uint_least32_t* serial() {
118 return &serial_;
119 }
120 uint32_t magic() const {
121 return magic_;
122 }
123 uint32_t version() const {
124 return version_;
125 }
126
127 private:
128 static prop_area* map_fd_ro(const int fd);
129
130 void* allocate_obj(const size_t size, uint_least32_t* const off);
131 prop_bt* new_prop_bt(const char* name, uint32_t namelen, uint_least32_t* const off);
132 prop_info* new_prop_info(const char* name, uint32_t namelen, const char* value, uint32_t valuelen,
133 uint_least32_t* const off);
134 void* to_prop_obj(uint_least32_t off);
135 prop_bt* to_prop_bt(atomic_uint_least32_t* off_p);
136 prop_info* to_prop_info(atomic_uint_least32_t* off_p);
137
138 prop_bt* root_node();
139
140 prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed);
141
142 const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen,
143 const char* value, uint32_t valuelen, bool alloc_if_needed);
144
145 bool foreach_property(prop_bt* const trie, void (*propfn)(const prop_info* pi, void* cookie),
146 void* cookie);
147
Tom Cherryf76bbf52017-11-08 14:01:00 -0800148 // The original design doesn't include pa_size or pa_data_size in the prop_area struct itself.
149 // Since we'll need to be backwards compatible with that design, we don't gain much by adding it
150 // now, especially since we don't have any plans to make different property areas different sizes,
151 // and thus we share these two variables among all instances.
152 static size_t pa_size_;
153 static size_t pa_data_size_;
154
Tom Cherryfd44b9f2017-11-08 14:01:00 -0800155 uint32_t bytes_used_;
156 atomic_uint_least32_t serial_;
157 uint32_t magic_;
158 uint32_t version_;
159 uint32_t reserved_[28];
160 char data_[0];
161
162 DISALLOW_COPY_AND_ASSIGN(prop_area);
163};
164
165#endif