Figure out the user's home directory if $HOME is not set
This commit is contained in:
		
							parent
							
								
									eba840c8a1
								
							
						
					
					
						commit
						465cb68244
					
				
					 8 changed files with 84 additions and 36 deletions
				
			
		|  | @ -16,8 +16,6 @@ | ||||||
|     <dict> |     <dict> | ||||||
|       <key>NIX_SSL_CERT_FILE</key> |       <key>NIX_SSL_CERT_FILE</key> | ||||||
|       <string>/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt</string> |       <string>/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt</string> | ||||||
|       <key>XDG_CACHE_HOME</key> |  | ||||||
|       <string>/root/.cache</string> |  | ||||||
|     </dict> |     </dict> | ||||||
|   </dict> |   </dict> | ||||||
| </plist> | </plist> | ||||||
|  |  | ||||||
|  | @ -7,5 +7,3 @@ ConditionPathIsReadWrite=@localstatedir@/nix/daemon-socket | ||||||
| [Service] | [Service] | ||||||
| ExecStart=@@bindir@/nix-daemon nix-daemon --daemon | ExecStart=@@bindir@/nix-daemon nix-daemon --daemon | ||||||
| KillMode=process | KillMode=process | ||||||
| Environment=XDG_CACHE_HOME=/root/.cache |  | ||||||
| Environment=XDG_CONFIG_HOME=/root/.config |  | ||||||
|  |  | ||||||
|  | @ -376,7 +376,7 @@ expr_simple | ||||||
|       $$ = stripIndentation(CUR_POS, data->symbols, *$2); |       $$ = stripIndentation(CUR_POS, data->symbols, *$2); | ||||||
|   } |   } | ||||||
|   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } |   | PATH { $$ = new ExprPath(absPath($1, data->basePath)); } | ||||||
|   | HPATH { $$ = new ExprPath(getEnv("HOME", "") + string{$1 + 1}); } |   | HPATH { $$ = new ExprPath(getHome() + string{$1 + 1}); } | ||||||
|   | SPATH { |   | SPATH { | ||||||
|       string path($1 + 1, strlen($1) - 2); |       string path($1 + 1, strlen($1) - 2); | ||||||
|       $$ = new ExprApp(CUR_POS, |       $$ = new ExprApp(CUR_POS, | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								src/libutil/lazy.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/libutil/lazy.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | #include <exception> | ||||||
|  | #include <functional> | ||||||
|  | #include <mutex> | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | /* A helper class for lazily-initialized variables.
 | ||||||
|  | 
 | ||||||
|  |      Lazy<T> var([]() { return value; }); | ||||||
|  | 
 | ||||||
|  |    declares a variable of type T that is initialized to 'value' (in a | ||||||
|  |    thread-safe way) on first use, that is, when var() is first | ||||||
|  |    called. If the initialiser code throws an exception, then all | ||||||
|  |    subsequent calls to var() will rethrow that exception. */ | ||||||
|  | template<typename T> | ||||||
|  | class Lazy | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     typedef std::function<T()> Init; | ||||||
|  | 
 | ||||||
|  |     Init init; | ||||||
|  | 
 | ||||||
|  |     std::once_flag done; | ||||||
|  | 
 | ||||||
|  |     T value; | ||||||
|  | 
 | ||||||
|  |     std::exception_ptr ex; | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 
 | ||||||
|  |     Lazy(Init init) : init(init) | ||||||
|  |     { } | ||||||
|  | 
 | ||||||
|  |     const T & operator () () | ||||||
|  |     { | ||||||
|  |         std::call_once(done, [&]() { | ||||||
|  |             try { | ||||||
|  |                 value = init(); | ||||||
|  |             } catch (...) { | ||||||
|  |                 ex = std::current_exception(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         if (ex) std::rethrow_exception(ex); | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -1,3 +1,4 @@ | ||||||
|  | #include "lazy.hh" | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
| #include "affinity.hh" | #include "affinity.hh" | ||||||
| #include "sync.hh" | #include "sync.hh" | ||||||
|  | @ -13,10 +14,12 @@ | ||||||
| #include <thread> | #include <thread> | ||||||
| #include <future> | #include <future> | ||||||
| 
 | 
 | ||||||
| #include <sys/wait.h> |  | ||||||
| #include <unistd.h> |  | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
|  | #include <pwd.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  | #include <sys/wait.h> | ||||||
|  | #include <unistd.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
| #include <sys/syscall.h> | #include <sys/syscall.h> | ||||||
|  | @ -417,14 +420,28 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | static Lazy<Path> getHome2([]() { | ||||||
|  |     Path homeDir = getEnv("HOME"); | ||||||
|  |     if (homeDir.empty()) { | ||||||
|  |         char buf[16384]; | ||||||
|  |         struct passwd pwbuf; | ||||||
|  |         struct passwd * pw; | ||||||
|  |         if (getpwuid_r(getuid(), &pwbuf, buf, sizeof(buf), &pw) != 0 | ||||||
|  |             || !pw || !pw->pw_dir || !pw->pw_dir[0]) | ||||||
|  |             throw Error("cannot determine user's home directory"); | ||||||
|  |         homeDir = pw->pw_dir; | ||||||
|  |     } | ||||||
|  |     return homeDir; | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | Path getHome() { return getHome2(); } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| Path getCacheDir() | Path getCacheDir() | ||||||
| { | { | ||||||
|     Path cacheDir = getEnv("XDG_CACHE_HOME"); |     Path cacheDir = getEnv("XDG_CACHE_HOME"); | ||||||
|     if (cacheDir.empty()) { |     if (cacheDir.empty()) | ||||||
|         Path homeDir = getEnv("HOME"); |         cacheDir = getHome() + "/.cache"; | ||||||
|         if (homeDir.empty()) throw Error("$XDG_CACHE_HOME and $HOME are not set"); |  | ||||||
|         cacheDir = homeDir + "/.cache"; |  | ||||||
|     } |  | ||||||
|     return cacheDir; |     return cacheDir; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -432,11 +449,8 @@ Path getCacheDir() | ||||||
| Path getConfigDir() | Path getConfigDir() | ||||||
| { | { | ||||||
|     Path configDir = getEnv("XDG_CONFIG_HOME"); |     Path configDir = getEnv("XDG_CONFIG_HOME"); | ||||||
|     if (configDir.empty()) { |     if (configDir.empty()) | ||||||
|         Path homeDir = getEnv("HOME"); |         configDir = getHome() + "/.config"; | ||||||
|         if (homeDir.empty()) throw Error("$XDG_CONFIG_HOME and $HOME are not set"); |  | ||||||
|         configDir = homeDir + "/.config"; |  | ||||||
|     } |  | ||||||
|     return configDir; |     return configDir; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -444,11 +458,8 @@ Path getConfigDir() | ||||||
| Path getDataDir() | Path getDataDir() | ||||||
| { | { | ||||||
|     Path dataDir = getEnv("XDG_DATA_HOME"); |     Path dataDir = getEnv("XDG_DATA_HOME"); | ||||||
|     if (dataDir.empty()) { |     if (dataDir.empty()) | ||||||
|         Path homeDir = getEnv("HOME"); |         dataDir = getHome() + "/.local/share"; | ||||||
|         if (homeDir.empty()) throw Error("$XDG_DATA_HOME and $HOME are not set"); |  | ||||||
|         dataDir = homeDir + "/.local/share"; |  | ||||||
|     } |  | ||||||
|     return dataDir; |     return dataDir; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -110,6 +110,9 @@ void deletePath(const Path & path, unsigned long long & bytesFreed); | ||||||
| Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", | Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", | ||||||
|     bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); |     bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); | ||||||
| 
 | 
 | ||||||
|  | /* Return $HOME or the user's home directory from /etc/passwd. */ | ||||||
|  | Path getHome(); | ||||||
|  | 
 | ||||||
| /* Return $XDG_CACHE_HOME or $HOME/.cache. */ | /* Return $XDG_CACHE_HOME or $HOME/.cache. */ | ||||||
| Path getCacheDir(); | Path getCacheDir(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -169,9 +169,7 @@ int main(int argc, char ** argv) | ||||||
|         setenv("NIX_DOWNLOAD_CACHE", channelCache.c_str(), 1); |         setenv("NIX_DOWNLOAD_CACHE", channelCache.c_str(), 1); | ||||||
| 
 | 
 | ||||||
|         // Figure out the name of the `.nix-channels' file to use
 |         // Figure out the name of the `.nix-channels' file to use
 | ||||||
|         auto home = getEnv("HOME"); |         auto home = getHome(); | ||||||
|         if (home.empty()) |  | ||||||
|             throw Error("$HOME not set"); |  | ||||||
|         channelsList = home + "/.nix-channels"; |         channelsList = home + "/.nix-channels"; | ||||||
|         nixDefExpr = home + "/.nix-defexpr"; |         nixDefExpr = home + "/.nix-defexpr"; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -192,17 +192,9 @@ static void loadDerivations(EvalState & state, Path nixExprPath, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static Path getHomeDir() |  | ||||||
| { |  | ||||||
|     Path homeDir(getEnv("HOME", "")); |  | ||||||
|     if (homeDir == "") throw Error("HOME environment variable not set"); |  | ||||||
|     return homeDir; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static Path getDefNixExprPath() | static Path getDefNixExprPath() | ||||||
| { | { | ||||||
|     return getHomeDir() + "/.nix-defexpr"; |     return getHome() + "/.nix-defexpr"; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1188,7 +1180,7 @@ static void opSwitchProfile(Globals & globals, Strings opFlags, Strings opArgs) | ||||||
|         throw UsageError(format("exactly one argument expected")); |         throw UsageError(format("exactly one argument expected")); | ||||||
| 
 | 
 | ||||||
|     Path profile = absPath(opArgs.front()); |     Path profile = absPath(opArgs.front()); | ||||||
|     Path profileLink = getHomeDir() + "/.nix-profile"; |     Path profileLink = getHome() + "/.nix-profile"; | ||||||
| 
 | 
 | ||||||
|     switchLink(profileLink, profile); |     switchLink(profileLink, profile); | ||||||
| } | } | ||||||
|  | @ -1413,7 +1405,7 @@ int main(int argc, char * * argv) | ||||||
|             globals.profile = getEnv("NIX_PROFILE", ""); |             globals.profile = getEnv("NIX_PROFILE", ""); | ||||||
| 
 | 
 | ||||||
|         if (globals.profile == "") { |         if (globals.profile == "") { | ||||||
|             Path profileLink = getHomeDir() + "/.nix-profile"; |             Path profileLink = getHome() + "/.nix-profile"; | ||||||
|             globals.profile = pathExists(profileLink) |             globals.profile = pathExists(profileLink) | ||||||
|                 ? absPath(readLink(profileLink), dirOf(profileLink)) |                 ? absPath(readLink(profileLink), dirOf(profileLink)) | ||||||
|                 : canonPath(settings.nixStateDir + "/profiles/default"); |                 : canonPath(settings.nixStateDir + "/profiles/default"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue