Make user's home specific to the prefix, provide a link to real home via LinuxHome

This commit is contained in:
Lubos Dolezel 2020-02-25 21:15:19 +01:00
parent c3ebd26366
commit 4da40f9cf5
4 changed files with 129 additions and 15 deletions

View File

@ -97,8 +97,6 @@ install(DIRECTORY DESTINATION libexec/darling/usr/local/share)
InstallSymlink(/Volumes/SystemRoot/dev ${CMAKE_INSTALL_PREFIX}/libexec/darling/dev)
InstallSymlink(private/tmp ${CMAKE_INSTALL_PREFIX}/libexec/darling/tmp)
InstallSymlink(/Volumes/SystemRoot/home ${CMAKE_INSTALL_PREFIX}/libexec/darling/Users)
InstallSymlink(Users ${CMAKE_INSTALL_PREFIX}/libexec/darling/home)
InstallSymlink(/proc/self/mounts ${CMAKE_INSTALL_PREFIX}/libexec/darling/etc/mtab)
InstallSymlink(/Volumes/SystemRoot/etc/passwd ${CMAKE_INSTALL_PREFIX}/libexec/darling/etc/passwd)

View File

@ -84,16 +84,36 @@ __attribute__((constructor))
static unsigned long processEnvVariable(const char* var)
{
if (strncmp(var, "HOME=/Users/", 12) == 0)
if (strncmp(var, "HOME=", 5) == 0)
{
const size_t len = strlen(var);
char* home = malloc(len); // 1 byte shorter
char* home = (char*) malloc(512);
char* symlink_path = (char*) malloc(strlen(var+5) + 10);
strcpy(home, "HOME=/home/");
strcpy(home + 11, var+12);
strcpy(symlink_path, var+5);
strcat(symlink_path, "/LinuxHome");
int len = readlink(symlink_path, home, 512-1);
free(symlink_path);
if (len < 0)
{
free(home);
goto out;
}
home[len] = '\0';
if (strncmp(home, SYSTEM_ROOT, sizeof(SYSTEM_ROOT) - 1) != 0)
{
free(home);
goto out;
}
strcpy(home, "HOME=");
memmove(home+5, home + sizeof(SYSTEM_ROOT) - 1, len - sizeof(SYSTEM_ROOT) + 2);
return (unsigned long) home;
}
out:
return (unsigned long) var;
}

View File

@ -1,7 +1,7 @@
/*
This file is part of Darling.
Copyright (C) 2016-2018 Lubos Dolezel
Copyright (C) 2016-2020 Lubos Dolezel
Darling is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -561,16 +561,16 @@ void spawnShell(const char** argv)
"/sbin:"
"/usr/local/bin");
const char *home = getenv("HOME");
if (home)
const char* login = getlogin();
if (!login)
{
if (sscanf(home, "/home/%4096s", buffer1) == 1)
snprintf(buffer2, sizeof(buffer2), "HOME=/Users/%s", buffer1);
else
snprintf(buffer2, sizeof(buffer2), "HOME=" SYSTEM_ROOT "%s", home);
pushShellspawnCommand(sockfd, SHELLSPAWN_SETENV, buffer2);
fprintf(stderr, "Cannot determine your user name\n");
exit(1);
}
snprintf(buffer2, sizeof(buffer2), "HOME=/Users/%s", login);
pushShellspawnCommand(sockfd, SHELLSPAWN_SETENV, buffer2);
// Push shell arguments
if (buffer != NULL)
{
@ -747,6 +747,8 @@ pid_t spawnInitProcess(void)
free(opts);
setupUserHome();
// This is executed once at prefix creation
if (g_fixPermissions)
fixDirectoryPermissions(prefix);
@ -1238,3 +1240,96 @@ void setupCoredumpPattern(void)
fclose(f);
}
}
const char* xdgDirectory(const char* name)
{
static char dir[4096];
char* cmd = (char*) malloc(16 + strlen(name));
sprintf(cmd, "xdg-user-dir %s", name);
FILE* proc = popen(cmd, "r");
free(cmd);
if (!proc)
return NULL;
fgets(dir, sizeof(dir)-1, proc);
pclose(proc);
size_t len = strlen(dir);
if (len <= 1)
return NULL;
if (dir[len-1] == '\n')
dir[len-1] = '\0';
return dir;
}
void setupUserHome(void)
{
char buf[4096], buf2[4096];
snprintf(buf, sizeof(buf), "%s/Users", prefix);
// Remove the old /Users symlink that may exist
unlink(buf);
// mkdir /Users
mkdir(buf, 0777);
// mkdir /Users/Shared
strcat(buf, "/Shared");
mkdir(buf, 0777);
const char* home = getenv("HOME");
const char* login = getlogin();
if (!login)
{
fprintf(stderr, "Cannot determine your user name\n");
exit(1);
}
if (!home)
{
fprintf(stderr, "Cannot determine your home directory\n");
exit(1);
}
snprintf(buf, sizeof(buf), "%s/Users/%s", prefix, login);
// mkdir /Users/$LOGIN
mkdir(buf, 0755);
snprintf(buf2, sizeof(buf2), "/Volumes/SystemRoot%s", home);
strcat(buf, "/LinuxHome");
unlink(buf);
// symlink /Users/$LOGIN/LinuxHome -> $HOME
symlink(buf2, buf);
static const char* xdgmap[][2] = {
{ "DESKTOP", "Desktop" },
{ "DOWNLOAD", "Downloads" },
{ "PUBLICSHARE", "Public" },
{ "DOCUMENTS", "Documents" },
{ "MUSIC", "Music" },
{ "PICTURES", "Pictures" },
{ "VIDEOS", "Movies" },
};
for (int i = 0; i < sizeof(xdgmap) / sizeof(xdgmap[0]); i++)
{
const char* dir = xdgDirectory(xdgmap[i][0]);
if (!dir)
continue;
snprintf(buf2, sizeof(buf2), "/Volumes/SystemRoot%s", dir);
snprintf(buf, sizeof(buf), "%s/Users/%s/%s", prefix, login, xdgmap[i][1]);
unlink(buf);
symlink(buf2, buf);
}
}

View File

@ -67,5 +67,6 @@ void loadKernelModule(void);
void joinNamespace(pid_t pid, int type, const char* typeName);
void setupCoredumpPattern(void);
void setupUserHome(void);
#endif