Bug 1001842 part 1: record the umask in NS_InitXPCOM2 and expose it to JS via nsSystemInfo. r=bsmedberg
authorZack Weinberg <zackw@panix.com>
Sat, 26 Apr 2014 10:56:54 -0400
changeset 180869 5fe8306c6409dfe6cd8151f06ae27ab1e29dd552
parent 180868 b9ed93ef1d238e04ae9a9ee107538fc6ddc20d11
child 180870 ea4471fb806febd3454ccd076ca7ef4cddf55a72
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbsmedberg
bugs1001842
milestone31.0a1
Bug 1001842 part 1: record the umask in NS_InitXPCOM2 and expose it to JS via nsSystemInfo. r=bsmedberg
xpcom/base/nsSystemInfo.cpp
xpcom/base/nsSystemInfo.h
xpcom/build/nsXPComInit.cpp
xpcom/tests/unit/test_systemInfo.js
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -35,16 +35,23 @@ using namespace mozilla::widget::android
 #endif
 
 #ifdef ANDROID
 extern "C" {
 NS_EXPORT int android_sdk_version;
 }
 #endif
 
+// Slot for NS_InitXPCOM2 to pass information to nsSystemInfo::Init.
+// Only set to nonzero (potentially) if XP_UNIX.  On such systems, the
+// system call to discover the appropriate value is not thread-safe,
+// so we must call it before going multithreaded, but nsSystemInfo::Init
+// only happens well after that point.
+uint32_t nsSystemInfo::gUserUmask = 0;
+
 #if defined(XP_WIN)
 namespace {
 nsresult GetHDDInfo(const char* aSpecialDirName, nsAutoCString& aModel,
                     nsAutoCString& aRevision)
 {
     aModel.Truncate();
     aRevision.Truncate();
 
@@ -193,16 +200,17 @@ nsSystemInfo::Init()
 #endif
 
     // Additional informations not available through PR_GetSystemInfo.
     SetInt32Property(NS_LITERAL_STRING("pagesize"), PR_GetPageSize());
     SetInt32Property(NS_LITERAL_STRING("pageshift"), PR_GetPageShift());
     SetInt32Property(NS_LITERAL_STRING("memmapalign"), PR_GetMemMapAlignment());
     SetInt32Property(NS_LITERAL_STRING("cpucount"), PR_GetNumberOfProcessors());
     SetUint64Property(NS_LITERAL_STRING("memsize"), PR_GetPhysicalMemorySize());
+    SetUint32Property(NS_LITERAL_STRING("umask"), nsSystemInfo::gUserUmask);
 
     for (uint32_t i = 0; i < ArrayLength(cpuPropItems); i++) {
         rv = SetPropertyAsBool(NS_ConvertASCIItoUTF16(cpuPropItems[i].name),
                                cpuPropItems[i].propfun());
         if (NS_WARN_IF(NS_FAILED(rv)))
           return rv;
     }
 
@@ -302,16 +310,29 @@ nsSystemInfo::SetInt32Property(const nsA
     nsresult rv =
 #endif
       SetPropertyAsInt32(aPropertyName, aValue);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
   }
 }
 
 void
+nsSystemInfo::SetUint32Property(const nsAString &aPropertyName,
+                                const uint32_t aValue)
+{
+  // Only one property is currently set via this function.
+  // It may legitimately be zero.
+#ifdef DEBUG
+  nsresult rv =
+#endif
+    SetPropertyAsUint32(aPropertyName, aValue);
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Unable to set property");
+}
+
+void
 nsSystemInfo::SetUint64Property(const nsAString &aPropertyName,
                                 const uint64_t aValue)
 {
   NS_WARN_IF_FALSE(aValue > 0, "Unable to read system value");
   if (aValue > 0) {
 #ifdef DEBUG
     nsresult rv =
 #endif
--- a/xpcom/base/nsSystemInfo.h
+++ b/xpcom/base/nsSystemInfo.h
@@ -9,19 +9,25 @@
 #include "nsHashPropertyBag.h"
 
 class nsSystemInfo : public nsHashPropertyBag {
 public:
     nsSystemInfo();
 
     nsresult Init();
 
+    // Slot for NS_InitXPCOM2 to pass information to nsSystemInfo::Init.
+    // See comments above the variable definition and in NS_InitXPCOM2.
+    static uint32_t gUserUmask;
+
 protected:
     void SetInt32Property(const nsAString &aPropertyName,
                           const int32_t aValue);
+    void SetUint32Property(const nsAString &aPropertyName,
+                           const uint32_t aValue);
     void SetUint64Property(const nsAString &aPropertyName,
                            const uint64_t aValue);
 
 private:
     ~nsSystemInfo();
 };
 
 #define NS_SYSTEMINFO_CONTRACTID "@mozilla.org/system-info;1"
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -456,16 +456,27 @@ NS_InitXPCOM2(nsIServiceManager* *result
 
      // We are not shutting down
     gXPCOMShuttingDown = false;
 
     // Initialize the available memory tracker before other threads have had a
     // chance to start up, because the initialization is not thread-safe.
     mozilla::AvailableMemoryTracker::Init();
 
+#ifdef XP_UNIX
+    // Discover the current value of the umask, and save it where
+    // nsSystemInfo::Init can retrieve it when necessary.  There is no way
+    // to read the umask without changing it, and the setting is process-
+    // global, so this must be done while we are still single-threaded; the
+    // nsSystemInfo object is typically created much later, when some piece
+    // of chrome JS wants it.  The system call is specified as unable to fail.
+    nsSystemInfo::gUserUmask = ::umask(0777);
+    ::umask(nsSystemInfo::gUserUmask);
+#endif
+
     NS_LogInit();
 
     // Set up chromium libs
     NS_ASSERTION(!sExitManager && !sMessageLoop, "Bad logic!");
 
     if (!AtExitManager::AlreadyRegistered()) {
         sExitManager = new AtExitManager();
     }
--- a/xpcom/tests/unit/test_systemInfo.js
+++ b/xpcom/tests/unit/test_systemInfo.js
@@ -8,9 +8,13 @@ function run_test() {
   let sysInfo = Components.classes["@mozilla.org/system-info;1"].
                 getService(Components.interfaces.nsIPropertyBag2);
 
   PROPERTIES.forEach(function(aPropertyName) {
     print("Testing property: " + aPropertyName);
     let value = sysInfo.getProperty(aPropertyName);
     do_check_true(!!value);
   });
+
+  // This property must exist, but its value might be zero.
+  print("Testing property: umask")
+  do_check_eq(typeof sysInfo.getProperty("umask"), "number");
 }