Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/installer/corehost/cli/apphost/bundle/extractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ void extractor_t::determine_extraction_dir()
{
if (!pal::getenv(_X("DOTNET_BUNDLE_EXTRACT_BASE_DIR"), &m_extraction_dir))
{
if (!pal::get_temp_directory(m_extraction_dir))
if (!pal::get_default_bundle_extraction_base_dir(m_extraction_dir))
{
trace::error(_X("Failure processing application bundle."));
trace::error(_X("Failed to determine location for extracting embedded files."));
trace::error(_X("DOTNET_BUNDLE_EXTRACT_BASE_DIR is not set, and temp-directory doesn't exist or is not readable/writable."));
trace::error(_X("DOTNET_BUNDLE_EXTRACT_BASE_DIR is not set, and a read-write temp-directory couldn't be created."));
throw StatusCode::BundleExtractionFailure;
}

append_path(&m_extraction_dir, _X(".net"));
}

pal::string_t host_name = strip_executable_ext(get_filename(m_bundle_path));
Expand Down
4 changes: 4 additions & 0 deletions src/installer/corehost/cli/hostmisc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ namespace pal

bool get_temp_directory(string_t& tmp_dir);

// Returns a platform-specific, user-private directory within get_temp_directory()
// that can be used for extracting out components of a single-file app.
bool get_default_bundle_extraction_base_dir(string_t& extraction_dir);

int xtoi(const char_t* input);

bool get_loaded_library(const char_t *library_name, const char *symbol_name, /*out*/ dll_t *dll, /*out*/ string_t *path);
Expand Down
52 changes: 51 additions & 1 deletion src/installer/corehost/cli/hostmisc/pal.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <fcntl.h>
#include <fnmatch.h>
#include <ctime>
#include <pwd.h>

#if defined(__APPLE__)
#include <mach-o/dyld.h>
Expand Down Expand Up @@ -306,7 +307,7 @@ bool is_read_write_able_directory(pal::string_t& dir)
bool pal::get_temp_directory(pal::string_t& tmp_dir)
{
// First, check for the POSIX standard environment variable
if (pal::getenv(_X("TMPDIR"), &tmp_dir))
if (getenv(_X("TMPDIR"), &tmp_dir))
{
return is_read_write_able_directory(tmp_dir);
}
Expand All @@ -331,6 +332,55 @@ bool pal::get_temp_directory(pal::string_t& tmp_dir)
return false;
}

bool pal::get_default_bundle_extraction_base_dir(pal::string_t& extraction_dir)
{
if (!get_temp_directory(extraction_dir))
{
return false;
}

append_path(&extraction_dir, _X(".net"));
pal::string_t dotnetdir(extraction_dir);

// getuid() is the real user ID, and the call has no defined errors.
struct passwd* passwd = getpwuid(getuid());
if (passwd == nullptr || passwd->pw_name == nullptr)
{
return false;
}

append_path(&extraction_dir, passwd->pw_name);

if (is_read_write_able_directory(extraction_dir))
{
return true;
}

// Create $TMPDIR/.net accessible to everyone
if (::mkdir(dotnetdir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0)
{
// In the above mkdir() system call, some permissions are strangely dropped!
// Linux drops S_IWO and Mac drops S_IWG | S_IWO.
// So these are again explicitly set by calling chmod()
if (chmod(dotnetdir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0)
{
return false;
}
}
else if (errno != EEXIST)
{
return false;
}

// Create $TMPDIR/.net/username accessible only to the user
if (::mkdir(extraction_dir.c_str(), S_IRWXU | S_ISVTX) != 0 && errno != EEXIST)
{
return false;
}

return is_read_write_able_directory(extraction_dir);
}

bool pal::get_global_dotnet_dirs(std::vector<pal::string_t>* recv)
{
// No support for global directories in Unix.
Expand Down
30 changes: 28 additions & 2 deletions src/installer/corehost/cli/hostmisc/pal.windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,35 @@ bool pal::get_temp_directory(pal::string_t& tmp_dir)
assert(len < max_len);
tmp_dir.assign(temp_path);

return pal::realpath(&tmp_dir);
return realpath(&tmp_dir);
}

bool pal::get_default_bundle_extraction_base_dir(pal::string_t& extraction_dir)
{
if (!get_temp_directory(extraction_dir))
{
return false;
}

append_path(&extraction_dir, _X(".net"));
// Windows Temp-Path is already user-private.

if (realpath(&extraction_dir))
{
return true;
}

// Create the %TEMP%\.net directory
if (CreateDirectoryW(extraction_dir.c_str(), NULL) == 0 &&
GetLastError() != ERROR_ALREADY_EXISTS)
{
return false;
}

return realpath(&extraction_dir);
}


static bool wchar_convert_helper(DWORD code_page, const char* cstr, int len, pal::string_t* out)
{
out->clear();
Expand Down Expand Up @@ -779,4 +805,4 @@ void pal::mutex_t::lock()
void pal::mutex_t::unlock()
{
::LeaveCriticalSection(&_impl);
}
}