Use a class for system properties filenames.

This avoids copy & pasting the "did we overflow the string?" logic
everywhere.

Test: treehugger
Change-Id: Icbeb2fdb050a33efc08e1bbb7e9c1e46e48319fa
diff --git a/libc/system_properties/context_node.cpp b/libc/system_properties/context_node.cpp
index d392c0a..572bf97 100644
--- a/libc/system_properties/context_node.cpp
+++ b/libc/system_properties/context_node.cpp
@@ -49,17 +49,11 @@
     return true;
   }
 
-  char filename[PROP_FILENAME_MAX];
-  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", filename_, context_);
-  if (len < 0 || len >= PROP_FILENAME_MAX) {
-    lock_.unlock();
-    return false;
-  }
-
+  PropertiesFilename filename(filename_, context_);
   if (access_rw) {
-    pa_ = prop_area::map_prop_area_rw(filename, context_, fsetxattr_failed);
+    pa_ = prop_area::map_prop_area_rw(filename.c_str(), context_, fsetxattr_failed);
   } else {
-    pa_ = prop_area::map_prop_area(filename);
+    pa_ = prop_area::map_prop_area(filename.c_str());
   }
   lock_.unlock();
   return pa_;
@@ -84,13 +78,8 @@
 }
 
 bool ContextNode::CheckAccess() {
-  char filename[PROP_FILENAME_MAX];
-  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", filename_, context_);
-  if (len < 0 || len >= PROP_FILENAME_MAX) {
-    return false;
-  }
-
-  return access(filename, R_OK) == 0;
+  PropertiesFilename filename(filename_, context_);
+  return access(filename.c_str(), R_OK) == 0;
 }
 
 void ContextNode::Unmap() {
diff --git a/libc/system_properties/contexts_serialized.cpp b/libc/system_properties/contexts_serialized.cpp
index 6ccd46c..f05aaa0 100644
--- a/libc/system_properties/contexts_serialized.cpp
+++ b/libc/system_properties/contexts_serialized.cpp
@@ -66,18 +66,12 @@
 }
 
 bool ContextsSerialized::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed) {
-  char filename[PROP_FILENAME_MAX];
-  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial", filename_);
-  if (len < 0 || len >= PROP_FILENAME_MAX) {
-    serial_prop_area_ = nullptr;
-    return false;
-  }
-
+  PropertiesFilename filename(filename_, "properties_serial");
   if (access_rw) {
-    serial_prop_area_ =
-        prop_area::map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
+    serial_prop_area_ = prop_area::map_prop_area_rw(
+        filename.c_str(), "u:object_r:properties_serial:s0", fsetxattr_failed);
   } else {
-    serial_prop_area_ = prop_area::map_prop_area(filename);
+    serial_prop_area_ = prop_area::map_prop_area(filename.c_str());
   }
   return serial_prop_area_;
 }
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
index 7ba835a..3579f55 100644
--- a/libc/system_properties/contexts_split.cpp
+++ b/libc/system_properties/contexts_split.cpp
@@ -192,18 +192,12 @@
 }
 
 bool ContextsSplit::MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed) {
-  char filename[PROP_FILENAME_MAX];
-  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial", filename_);
-  if (len < 0 || len >= PROP_FILENAME_MAX) {
-    serial_prop_area_ = nullptr;
-    return false;
-  }
-
+  PropertiesFilename filename(filename_, "properties_serial");
   if (access_rw) {
-    serial_prop_area_ =
-        prop_area::map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
+    serial_prop_area_ = prop_area::map_prop_area_rw(
+        filename.c_str(), "u:object_r:properties_serial:s0", fsetxattr_failed);
   } else {
-    serial_prop_area_ = prop_area::map_prop_area(filename);
+    serial_prop_area_ = prop_area::map_prop_area(filename.c_str());
   }
   return serial_prop_area_;
 }
diff --git a/libc/system_properties/include/system_properties/system_properties.h b/libc/system_properties/include/system_properties/system_properties.h
index 0666e28..fa5e3de 100644
--- a/libc/system_properties/include/system_properties/system_properties.h
+++ b/libc/system_properties/include/system_properties/system_properties.h
@@ -37,7 +37,24 @@
 #include "contexts_serialized.h"
 #include "contexts_split.h"
 
-constexpr int PROP_FILENAME_MAX = 1024;
+class PropertiesFilename {
+ public:
+  PropertiesFilename() = default;
+  PropertiesFilename(const char* dir, const char* file) {
+    if (snprintf(filename_, sizeof(filename_), "%s/%s", dir, file) >=
+        static_cast<int>(sizeof(filename_))) {
+      abort();
+    }
+  }
+  void operator=(const char* value) {
+    if (strlen(value) >= sizeof(filename_)) abort();
+    strcpy(filename_, value);
+  }
+  const char* c_str() { return filename_; }
+
+ private:
+  char filename_[1024];
+};
 
 class SystemProperties {
  public:
@@ -86,5 +103,5 @@
   Contexts* contexts_;
 
   bool initialized_;
-  char property_filename_[PROP_FILENAME_MAX];
+  PropertiesFilename properties_filename_;
 };
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index 1cb15c3..049236f 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -67,26 +67,23 @@
     return true;
   }
 
-  if (strlen(filename) >= PROP_FILENAME_MAX) {
-    return false;
-  }
-  strcpy(property_filename_, filename);
+  properties_filename_ = filename;
 
-  if (is_dir(property_filename_)) {
+  if (is_dir(properties_filename_.c_str())) {
     if (access("/dev/__properties__/property_info", R_OK) == 0) {
       contexts_ = new (contexts_data_) ContextsSerialized();
-      if (!contexts_->Initialize(false, property_filename_, nullptr)) {
+      if (!contexts_->Initialize(false, properties_filename_.c_str(), nullptr)) {
         return false;
       }
     } else {
       contexts_ = new (contexts_data_) ContextsSplit();
-      if (!contexts_->Initialize(false, property_filename_, nullptr)) {
+      if (!contexts_->Initialize(false, properties_filename_.c_str(), nullptr)) {
         return false;
       }
     }
   } else {
     contexts_ = new (contexts_data_) ContextsPreSplit();
-    if (!contexts_->Initialize(false, property_filename_, nullptr)) {
+    if (!contexts_->Initialize(false, properties_filename_.c_str(), nullptr)) {
       return false;
     }
   }
@@ -95,13 +92,9 @@
 }
 
 bool SystemProperties::AreaInit(const char* filename, bool* fsetxattr_failed) {
-  if (strlen(filename) >= PROP_FILENAME_MAX) {
-    return false;
-  }
-  strcpy(property_filename_, filename);
-
+  properties_filename_ = filename;
   contexts_ = new (contexts_data_) ContextsSerialized();
-  if (!contexts_->Initialize(true, property_filename_, fsetxattr_failed)) {
+  if (!contexts_->Initialize(true, properties_filename_.c_str(), fsetxattr_failed)) {
     return false;
   }
   initialized_ = true;