Skip to content

Commit

Permalink
Add extra mount path handling for GCC on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
kcgen committed Dec 17, 2021
1 parent 0d5fe2e commit 3db56fb
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/dos/dos_programs.cpp
Expand Up @@ -63,8 +63,10 @@ void DOS_SetupPrograms(void)
MSG_Add("PROGRAM_MOUNT_UMOUNT_NO_VIRTUAL","Virtual Drives can not be unMOUNTed.\n");
MSG_Add("PROGRAM_MOUNT_DRIVEID_ERROR", "'%c' is not a valid drive identifier.\n");
MSG_Add("PROGRAM_MOUNT_ROOT_PATH_WARNING",
"\033[31;1mWARNING: '%s' resolves to a root directory: '%s'\n"
"\033[31;1mWARNING: The path \"%s\" resolves to a root directory \"%s\"\n"
"Mounting a root directory is risky. Please use a subdirectory next time.\033[0m\n");
MSG_Add("PROGRAM_MOUNT_NO_DRIVE_PREFIX",
"The absolute path \"%s\" is missing a drive prefix, such as \"c:%s\"\n");
MSG_Add("PROGRAM_MOUNT_NO_OPTION","Warning: Ignoring unsupported option '%s'.\n");
MSG_Add("PROGRAM_MOUNT_OVERLAY_NO_BASE","A normal directory needs to be MOUNTed first before an overlay can be added on top.\n");
MSG_Add("PROGRAM_MOUNT_OVERLAY_INCOMPAT_BASE","The overlay is NOT compatible with the drive that is specified.\n");
Expand Down
48 changes: 48 additions & 0 deletions src/dos/program_mount.cpp
Expand Up @@ -243,7 +243,55 @@ void MOUNT::Run(void) {
if (!cmd->FindCommand(2, temp_line) || temp_line.empty()) {
goto showusage;
}

// Error-code to be used in throw-free std::filesystem calls
std::error_code ec;

// Extra handling for MinGW GCC build handles the following:
// - mount c ./ -> should behave like mount c .
// - mount c / -> should behave like mount c c:/
// - mount c c: -> should behave like mount c c:/
//
// Note: MSVC and Clang do not need this extra babysitting.
// Remove this block when MinGW's GCC std::filesystem is fixed.
//
#if defined(WIN32) && defined(__GNUC__) && !defined(__clang__)
const auto saved_line = temp_line;

// GCC on Windows has problems with traling slashes, so strip them
const bool has_drive_spec = (temp_line.size() > 1 && temp_line[1] == ':');
const size_t strip_slashes_up_to = has_drive_spec ? 3 : 1;
while (temp_line.size() > strip_slashes_up_to &&
(temp_line.back() == '/' || temp_line.back() == '\\'))
temp_line.pop_back();

// GCC on Windows doesn't upgrade drive-specs (d:) to absolute (d:\)
if (temp_line.size() == 2 && temp_line[1] == ':')
temp_line += '\\';

// GCC on Windows doesn't map absolute paths (/) to the current drive
const bool is_absolute = (temp_line.size() &&
(temp_line.front() == '/' ||
temp_line.front() == '\\'));

if (is_absolute) {
// Try to prepend the current-working drive
auto cp = std_fs::current_path(ec);
if (cp.has_root_name()) {
temp_line = cp.root_name().string() + temp_line;
} else {
WriteOut(MSG_Get("PROGRAM_MOUNT_NO_DRIVE_PREFIX"),
saved_line.c_str(), saved_line.c_str());
return;
}
}

// if we made it here, the path is relative or has a drive
// prefix, which is sufficient for GCC to handle properly
assert(temp_line.size());
#endif

// Construct a std::filesystem path from the string
std_fs::path host_path = temp_line;

// Check if the path is relative to the last config file
Expand Down
10 changes: 10 additions & 0 deletions src/misc/support.cpp
Expand Up @@ -396,6 +396,14 @@ const std_fs::path &GetExecutablePath()

bool is_path_a_root_path(const std_fs::path &test_path, std_fs::path &root_path)
{

// Special handling for GCC on Windows
#if defined(WIN32) && defined(__GNUC__) && !defined(__clang__)
const bool is_root_path = (test_path.string().length() == 3 && test_path.string()[1] == ':');
root_path = is_root_path ? test_path : std_fs::path("");
return is_root_path;
#endif

// Try to discover the root path dynamically, which means we can handle
// all variety of filesystems like MorphOS, AmigaOS, etc.
std::error_code ec;
Expand All @@ -408,6 +416,8 @@ bool is_path_a_root_path(const std_fs::path &test_path, std_fs::path &root_path)
root_path = test_path.root_directory();
else if (test_path.has_root_path())
root_path = test_path.root_path();
else if (std_fs::current_path(ec).has_root_path())
root_path = std_fs::current_path(ec).root_path();

// Otherwise fallback to our best guess of the root path
if (root_path.empty())
Expand Down

0 comments on commit 3db56fb

Please sign in to comment.