summaryrefslogtreecommitdiff
path: root/zen/file_path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zen/file_path.cpp')
-rw-r--r--zen/file_path.cpp78
1 files changed, 74 insertions, 4 deletions
diff --git a/zen/file_path.cpp b/zen/file_path.cpp
index d06ab6bd..7ef78569 100644
--- a/zen/file_path.cpp
+++ b/zen/file_path.cpp
@@ -36,13 +36,13 @@ std::optional<PathComponents> zen::parsePathComponents(const Zstring& itemPath)
pc = doParse(3 /*sepCountVolumeRoot*/, false /*rootWithSep*/);
if (!pc && startsWith(itemPath, "/media/")) //Ubuntu: e.g. /media/zenju/DEVICE_NAME
- if (const char* username = ::getenv("USER")) //no ownership transfer + no extended error reporting
- if (startsWith(itemPath, std::string("/media/") + username + "/"))
+ if (const std::optional<Zstring> username = getEnvironmentVar("USER"))
+ if (startsWith(itemPath, std::string("/media/") + *username + "/"))
pc = doParse(4 /*sepCountVolumeRoot*/, false /*rootWithSep*/);
if (!pc && startsWith(itemPath, "/run/media/")) //CentOS, Suse: e.g. /run/media/zenju/DEVICE_NAME
- if (const char* username = ::getenv("USER"))
- if (startsWith(itemPath, std::string("/run/media/") + username + "/"))
+ if (const std::optional<Zstring> username = getEnvironmentVar("USER"))
+ if (startsWith(itemPath, std::string("/run/media/") + *username + "/"))
pc = doParse(5 /*sepCountVolumeRoot*/, false /*rootWithSep*/);
if (!pc && startsWith(itemPath, "/run/user/")) //Ubuntu, e.g.: /run/user/1000/gvfs/smb-share:server=192.168.62.145,share=folder
@@ -154,3 +154,73 @@ std::weak_ordering zen::compareNativePath(const Zstring& lhs, const Zstring& rhs
}
+namespace
+{
+std::unordered_map<Zstring, Zstring> getAllEnvVars()
+{
+ assert(runningOnMainThread());
+
+ std::unordered_map<Zstring, Zstring> envVars;
+ if (char** line = environ)
+ for (; *line; ++line)
+ {
+ const std::string_view l(*line);
+ envVars.emplace(beforeFirst(l, '=', IfNotFoundReturn::all),
+ afterFirst(l, '=', IfNotFoundReturn::none));
+ }
+ return envVars;
+}
+
+constinit Global<std::unordered_map<Zstring, Zstring>> globalEnvVars;
+GLOBAL_RUN_ONCE(
+ //*INDENT-OFF*
+ //mitigate static initialization order fiasco: (whatever comes first)
+ if (!globalEnvVars.get())
+ globalEnvVars.set(std::make_unique<std::unordered_map<Zstring, Zstring>>(getAllEnvVars()))
+ //*INDENT-ON*
+);
+}
+
+
+std::optional<Zstring> zen::getEnvironmentVar(const ZstringView name)
+{
+ /* const char* buffer = ::getenv(name); => NO! *not* thread-safe: returns pointer to internal memory!
+ might change after setenv(), allegedly possible even after another getenv()!
+
+ getenv_s() to the rescue!? not implemented on GCC, apparently *still* not threadsafe!!!
+
+ => *eff* this: make a global copy during start up! */
+ std::shared_ptr<std::unordered_map<Zstring, Zstring>> envVars = globalEnvVars.get();
+ if (!envVars) //access during static init or shutdown?
+ {
+ if (globalEnvVars.wasDestroyed())
+ {
+ assert(false);
+ return {}; //SOL!
+ }
+ //mitigate static initialization order fiasco: (whatever comes first)
+ globalEnvVars.set(std::make_unique<std::unordered_map<Zstring, Zstring>>(getAllEnvVars()));
+ envVars = globalEnvVars.get();
+ }
+
+ auto it = envVars->find(name);
+ if (it == envVars->end())
+ return {};
+
+ Zstring value = it->second;
+
+ //some postprocessing (good idea!? Is this even needed!?
+ warn_static("let's find out!")
+#if 0
+ trim(value); //remove leading, trailing blanks
+
+ //remove leading, trailing double-quotes
+ if (startsWith(value, Zstr('"')) &&
+ endsWith (value, Zstr('"')) &&
+ value.length() >= 2)
+ value = Zstring(value.c_str() + 1, value.length() - 2);
+#endif
+ return value;
+}
+
+
bgstack15