Split system_properties.cpp into its component pieces

system_properties.cpp is a little bit unmanageable in its current
form, and is overdue for a refactoring into more clearly defined
components.

Of particular interest, is creating of a Contexts interface that
handles mapping of system property name -> SEContext and its
associated prop_area, and creating two classes that implement the
current and legacy functionality.  This is needed as there will likely
be a third even newer way to do this mapping.

Bug: 36001741
Test: boot bullhead, system property unit tests
Change-Id: Ie75ec6fea1a95f90813918f54669d533e51327c6
diff --git a/libc/system_properties/prop_area.h b/libc/system_properties/prop_area.h
new file mode 100644
index 0000000..6b74e10
--- /dev/null
+++ b/libc/system_properties/prop_area.h
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include <stdatomic.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "private/bionic_macros.h"
+
+#include "prop_info.h"
+
+#ifndef SYSTEM_PROPERTIES_PROP_AREA_H
+#define SYSTEM_PROPERTIES_PROP_AREA_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:
+  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);
+
+  prop_area(const uint32_t magic, const uint32_t version) : magic_(magic), version_(version) {
+    atomic_init(&serial_, 0);
+    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);
+
+  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_ro(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();
+
+  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);
+
+  uint32_t bytes_used_;
+  atomic_uint_least32_t serial_;
+  uint32_t magic_;
+  uint32_t version_;
+  uint32_t reserved_[28];
+  char data_[0];
+
+  DISALLOW_COPY_AND_ASSIGN(prop_area);
+};
+
+#endif