diff options
author | B. Stack <bgstack15@gmail.com> | 2021-04-05 15:59:11 +0000 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2021-04-05 15:59:11 +0000 |
commit | 8d28254d708c88ae4aaebbc82cbb6c91726aa390 (patch) | |
tree | dafb5e266c513a5ed9863401e62d246742861e0c /zen/sys_info.cpp | |
parent | Merge branch '11.7' into 'master' (diff) | |
parent | add upstream 11.9 (diff) | |
download | FreeFileSync-8d28254d708c88ae4aaebbc82cbb6c91726aa390.tar.gz FreeFileSync-8d28254d708c88ae4aaebbc82cbb6c91726aa390.tar.bz2 FreeFileSync-8d28254d708c88ae4aaebbc82cbb6c91726aa390.zip |
Merge branch '11.9' into 'master'11.9
add upstream 11.9
See merge request opensource-tracking/FreeFileSync!32
Diffstat (limited to 'zen/sys_info.cpp')
-rw-r--r-- | zen/sys_info.cpp | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/zen/sys_info.cpp b/zen/sys_info.cpp index 1a0d18f5..6eeab276 100644 --- a/zen/sys_info.cpp +++ b/zen/sys_info.cpp @@ -9,6 +9,7 @@ #include "file_access.h" #include "sys_version.h" #include "symlink_target.h" +#include "time.h" #include "file_io.h" #include <ifaddrs.h> @@ -23,16 +24,50 @@ using namespace zen; -std::wstring zen::getUserName() //throw FileError +Zstring zen::getUserName() //throw FileError { - //https://linux.die.net/man/3/getlogin - //https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getlogin.2.html - const char* loginUser = ::getlogin(); - if (!loginUser) - THROW_LAST_FILE_ERROR(_("Cannot get process information."), "getlogin"); + const uid_t userIdNo = ::getuid(); //never fails + + if (userIdNo != 0) //nofail; root(0) => consider as request for elevation, NOT impersonation + { + std::vector<char> buf(std::max<long>(10000, ::sysconf(_SC_GETPW_R_SIZE_MAX))); //::sysconf may return long(-1) + passwd buf2 = {}; + passwd* pwsEntry = nullptr; + if (::getpwuid_r(userIdNo, //uid_t uid + &buf2, //struct passwd* pwd + &buf[0], //char* buf + buf.size(), //size_t buflen + &pwsEntry) != 0) //struct passwd** result + THROW_LAST_FILE_ERROR(_("Cannot get process information."), "getpwuid_r"); + + if (!pwsEntry) + throw FileError(_("Cannot get process information."), L"no login found"); //should not happen? + + return pwsEntry->pw_name; + } + //else root(0): what now!? + //getlogin() is smarter than simply evaluating $LOGNAME! even in contexts without //$LOGNAME, e.g. "sudo su" on Ubuntu, it returns the correct non-root user! - return utfTo<std::wstring>(loginUser); + if (const char* loginUser = ::getlogin()) //https://linux.die.net/man/3/getlogin + if (strLength(loginUser) > 0 && !equalString(loginUser, "root")) + return loginUser; + //BUT: getlogin() can fail with ENOENT on Linux Mint: https://freefilesync.org/forum/viewtopic.php?t=8181 + + auto tryGetNonRootUser = [](const char* varName) -> const char* + { + if (const char* buf = ::getenv(varName)) //no extended error reporting + if (strLength(buf) > 0 && !equalString(buf, "root")) + return buf; + return nullptr; + }; + //getting a little desperate: variables used by installer.sh + if (const char* userName = tryGetNonRootUser("USER")) return userName; + if (const char* userName = tryGetNonRootUser("SUDO_USER")) return userName; + if (const char* userName = tryGetNonRootUser("LOGNAME")) return userName; + + throw FileError(_("Cannot get process information."), L"Failed to determine non-root user name"); //should not happen? + } @@ -94,6 +129,7 @@ ComputerModel zen::getComputerModel() //throw FileError + std::wstring zen::getOsDescription() //throw FileError { try @@ -123,7 +159,7 @@ Zstring zen::getUserDataPath() //throw FileError xdgCfgPath && xdgCfgPath[0] != 0) return xdgCfgPath; - return Zstring("/home/") + utfTo<Zstring>(getUserName()) + "/.config"; //throw FileError + return "/home/" + getUserName() + "/.config"; //throw FileError } @@ -133,13 +169,13 @@ Zstring zen::getUserDownloadsPath() //throw FileError { const Zstring cmdLine = ::getuid() == 0 ? //nofail; root(0) => consider as request for elevation, NOT impersonation //sudo better be installed :> - "sudo -u " + utfTo<Zstring>(getUserName()) + " xdg-user-dir DOWNLOAD" : //throw FileError + "sudo -u " + getUserName() + " xdg-user-dir DOWNLOAD" : //throw FileError "xdg-user-dir DOWNLOAD"; const auto& [exitCode, output] = consoleExecute(cmdLine, std::nullopt /*timeoutMs*/); //throw SysError - if (exitCode != 0) - throw SysError(formatSystemError(cmdLine.c_str(), - replaceCpy(_("Exit code %x"), L"%x", numberTo<std::wstring>(exitCode)), utfTo<std::wstring>(output))); + if (exitCode != 0) //fallback: probably correct 99.9% of the time anyway... + return "/home/" + getUserName() + "/Downloads"; //throw FileError + const Zstring& downloadsPath = trimCpy(output); ASSERT_SYSERROR(!downloadsPath.empty()); return downloadsPath; |