refactoring:
- simplify sys_get_executable_name interface - return OsPath directly, rename to sys_ExecutablePathname - add validation of path components in GetDirectoryEntries - replace multiple calls to GetModuleFileNameW with sys_ExecutablePathname - lift nearly all MAX_PATH limitations (required at work) This was SVN commit r9109.
This commit is contained in:
parent
64a02932e3
commit
0999ba0941
@ -44,11 +44,7 @@ static const OsPath& def_get_log_dir()
|
||||
{
|
||||
static OsPath logDir;
|
||||
if(logDir.empty())
|
||||
{
|
||||
OsPath exePathname;
|
||||
(void)sys_get_executable_name(exePathname);
|
||||
logDir = exePathname.Parent();
|
||||
}
|
||||
logDir = sys_ExecutablePathname().Parent();
|
||||
return logDir;
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ extern void ah_override_gl_upload_caps();
|
||||
* return path to directory into which crash dumps should be written.
|
||||
*
|
||||
* must be callable at any time - in particular, before VFS init.
|
||||
* paths are typically relative to sys_get_executable_name.
|
||||
* paths are typically relative to sys_ExecutablePathname.
|
||||
*
|
||||
* @return path ending with directory separator (e.g. '/').
|
||||
**/
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#if OS_WIN
|
||||
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
#include "lib/external_libraries/dbghelp.h"
|
||||
|
||||
@ -42,7 +43,7 @@ void dbghelp_ImportFunctions()
|
||||
// application loaded.") and then the system directory, whose
|
||||
// dbghelp.dll is too old. we therefore specify the full path
|
||||
// to our executable directory, which contains a newer dbghelp.dll.
|
||||
const OsPath pathname = wutil_DetectExecutablePath()/"dbghelp.dll";
|
||||
const OsPath pathname = sys_ExecutablePathname().Parent()/"dbghelp.dll";
|
||||
HMODULE hDbghelp = LoadLibraryW(OsString(pathname).c_str());
|
||||
debug_assert(hDbghelp);
|
||||
#define FUNC(ret, name, params) p##name = (ret (__stdcall*) params)GetProcAddress(hDbghelp, #name);
|
||||
|
@ -59,8 +59,9 @@ LibError GetDirectoryEntries(const OsPath& path, FileInfos* files, DirectoryName
|
||||
return LibError_from_errno();
|
||||
}
|
||||
|
||||
for(size_t i = 0; osEnt->d_name[i] != '\0'; i++)
|
||||
RETURN_ERR(Path::Validate(osEnt->d_name[i]));
|
||||
const OsPath name(osEnt->d_name);
|
||||
RETURN_ERR(name.Validate());
|
||||
|
||||
// get file information (mode, size, mtime)
|
||||
struct stat s;
|
||||
|
@ -32,9 +32,8 @@
|
||||
|
||||
#include "lib/utf8.h"
|
||||
|
||||
|
||||
ERROR_ASSOCIATE(ERR::PATH_EMPTY, L"path is an empty string", -1);
|
||||
ERROR_ASSOCIATE(ERR::PATH_COMPONENT_SEPARATOR, L"path component contains dir separator", -1);
|
||||
ERROR_ASSOCIATE(ERR::PATH_CHARACTER_ILLEGAL, L"illegal path character", -1);
|
||||
ERROR_ASSOCIATE(ERR::PATH_CHARACTER_UNSAFE, L"unsafe path character", -1);
|
||||
ERROR_ASSOCIATE(ERR::PATH_NOT_FOUND, L"path not found", -1);
|
||||
|
||||
|
||||
@ -93,3 +92,33 @@ const wchar_t* path_name_only(const wchar_t* path)
|
||||
const wchar_t* name = std::max(slash1, slash2)+1;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ LibError Path::Validate(String::value_type c)
|
||||
{
|
||||
if(c < 32)
|
||||
return ERR::PATH_CHARACTER_UNSAFE;
|
||||
|
||||
#if !OS_WIN
|
||||
if(c >= UCHAR_MAX)
|
||||
return ERR::PATH_CHARACTER_UNSAFE;
|
||||
#endif
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case '\\':
|
||||
case '/':
|
||||
case ':':
|
||||
case '"':
|
||||
case '?':
|
||||
case '*':
|
||||
case '<':
|
||||
case '>':
|
||||
case '|':
|
||||
case '^':
|
||||
return ERR::PATH_CHARACTER_ILLEGAL;
|
||||
|
||||
default:
|
||||
return INFO::OK;
|
||||
}
|
||||
}
|
||||
|
@ -43,8 +43,8 @@
|
||||
|
||||
namespace ERR
|
||||
{
|
||||
const LibError PATH_EMPTY = -100300;
|
||||
const LibError PATH_COMPONENT_SEPARATOR = -100301;
|
||||
const LibError PATH_CHARACTER_ILLEGAL = -100300;
|
||||
const LibError PATH_CHARACTER_UNSAFE = -100301;
|
||||
const LibError PATH_NOT_FOUND = -100302;
|
||||
}
|
||||
|
||||
@ -177,14 +177,7 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
LibError Validate() const
|
||||
{
|
||||
for(size_t i = 0; i < path.length(); i++)
|
||||
{
|
||||
}
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
static LibError Validate(String::value_type c);
|
||||
|
||||
private:
|
||||
String path;
|
||||
|
@ -30,30 +30,23 @@
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
LibError sys_get_executable_name(OsPath& pathname)
|
||||
OsPath sys_ExecutablePathname()
|
||||
{
|
||||
const char* path;
|
||||
Dl_info dl_info;
|
||||
|
||||
// Find the executable's filename
|
||||
Dl_info dl_info;
|
||||
memset(&dl_info, 0, sizeof(dl_info));
|
||||
if (!T::dladdr((void *)sys_get_executable_name, &dl_info) ||
|
||||
!dl_info.dli_fname )
|
||||
{
|
||||
return ERR::NO_SYS;
|
||||
}
|
||||
path = dl_info.dli_fname;
|
||||
if (!T::dladdr((void *)sys_ExecutablePathname, &dl_info) || !dl_info.dli_fname)
|
||||
return OsPath();
|
||||
const char* path = dl_info.dli_fname;
|
||||
|
||||
// If this looks like an absolute path, use realpath to get the normalized
|
||||
// path (with no '.' or '..')
|
||||
if (path[0] == '/')
|
||||
{
|
||||
char resolvedBuf[PATH_MAX];
|
||||
char* resolved = realpath(path, resolvedBuf);
|
||||
if (!resolved)
|
||||
return ERR::FAIL;
|
||||
pathname = resolved;
|
||||
return INFO::OK;
|
||||
char resolved[PATH_MAX];
|
||||
if (!realpath(path, resolved))
|
||||
return OsPath();
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// If this looks like a relative path, resolve against cwd and use realpath
|
||||
@ -61,22 +54,20 @@ LibError sys_get_executable_name(OsPath& pathname)
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
if (!T::getcwd(cwd, PATH_MAX))
|
||||
return ERR::NO_SYS;
|
||||
return OsPath();
|
||||
|
||||
char absolute[PATH_MAX];
|
||||
int ret = snprintf(absolute, PATH_MAX, "%s/%s", cwd, path);
|
||||
if (ret < 0 || ret >= PATH_MAX)
|
||||
return ERR::NO_SYS; // path too long, or other error
|
||||
char resolvedBuf[PATH_MAX];
|
||||
char* resolved = realpath(absolute, resolvedBuf);
|
||||
if (!resolved)
|
||||
return ERR::NO_SYS;
|
||||
pathname = resolved;
|
||||
return INFO::OK;
|
||||
return OsPath(); // path too long, or other error
|
||||
char resolved[PATH_MAX];
|
||||
if (!realpath(absolute, resolved))
|
||||
return OsPath();
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// If it's not a path at all, i.e. it's just a filename, we'd
|
||||
// probably have to search through PATH to find it.
|
||||
// That's complex and should be uncommon, so don't bother.
|
||||
return ERR::NO_SYS;
|
||||
return OsPath();
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq)
|
||||
}
|
||||
|
||||
|
||||
LibError sys_get_executable_name(OsPath& pathname)
|
||||
OsPath sys_ExecutablePathname()
|
||||
{
|
||||
static char name[PATH_MAX];
|
||||
static bool init = false;
|
||||
@ -88,9 +88,7 @@ LibError sys_get_executable_name(OsPath& pathname)
|
||||
char temp[PATH_MAX];
|
||||
u32 size = PATH_MAX;
|
||||
if (_NSGetExecutablePath( temp, &size ))
|
||||
{
|
||||
return ERR::NO_SYS;
|
||||
}
|
||||
return OsPath();
|
||||
realpath(temp, name);
|
||||
}
|
||||
|
||||
@ -102,7 +100,5 @@ LibError sys_get_executable_name(OsPath& pathname)
|
||||
debug_printf(L"app bundle name: %hs\n", name);
|
||||
}
|
||||
|
||||
pathname = name;
|
||||
|
||||
return INFO::OK;
|
||||
return name;
|
||||
}
|
||||
|
@ -59,27 +59,26 @@ filesystem;
|
||||
|
||||
// called from the first filetime_to_time_t() call, not win.cpp init;
|
||||
// this means we can rely on the current directory having been set to
|
||||
// the app's directory (and therefore its appendant volume - see above).
|
||||
// the app's directory (and the corresponding volume - see above).
|
||||
static void detect_filesystem()
|
||||
{
|
||||
wchar_t root_path[MAX_PATH] = L"c:\\"; // default in case GCD fails
|
||||
DWORD gcd_ret = GetCurrentDirectoryW(ARRAY_SIZE(root_path), root_path);
|
||||
debug_assert(gcd_ret != 0);
|
||||
// if this fails, no problem - we have the default from above.
|
||||
root_path[3] = '\0'; // cut off after "c:\"
|
||||
const DWORD length = GetCurrentDirectoryW(0, 0);
|
||||
debug_assert(length != 0);
|
||||
std::wstring rootPath(length, '\0');
|
||||
const DWORD charsWritten = GetCurrentDirectoryW(length, &rootPath[0]);
|
||||
debug_assert(charsWritten == length-1);
|
||||
|
||||
wchar_t fs_name[32] = {0};
|
||||
BOOL ret = GetVolumeInformationW(root_path, 0,0,0,0,0, fs_name, sizeof(fs_name));
|
||||
fs_name[ARRAY_SIZE(fs_name)-1] = '\0';
|
||||
wchar_t drive[_MAX_DRIVE];
|
||||
debug_assert(_wsplitpath_s(&rootPath[0], drive, ARRAY_SIZE(drive), 0,0, 0,0, 0,0) == 0);
|
||||
|
||||
wchar_t filesystemName[MAX_PATH+1] = {0}; // mandated by GetVolumeInformationW
|
||||
BOOL ret = GetVolumeInformationW(OsString(OsPath(drive)/"").c_str(), 0,0,0,0,0, filesystemName, ARRAY_SIZE(filesystemName));
|
||||
debug_assert(ret != 0);
|
||||
// if this fails, no problem - we really only care if fs is FAT,
|
||||
// and will assume that's not the case (since fs_name != "FAT").
|
||||
|
||||
filesystem = FS_UNKNOWN;
|
||||
|
||||
if(!wcsncmp(fs_name, L"FAT", 3)) // e.g. FAT32
|
||||
if(!wcsncmp(filesystemName, L"FAT", 3)) // e.g. FAT32
|
||||
filesystem = FS_FAT;
|
||||
else if(!wcscmp(fs_name, L"NTFS"))
|
||||
else if(!wcscmp(filesystemName, L"NTFS"))
|
||||
filesystem = FS_NTFS;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include "lib/module_init.h"
|
||||
#include "lib/posix/posix_pthread.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
#include "lib/sysdep/os/win/winit.h"
|
||||
#include "lib/sysdep/os/win/wmi.h" // for SDL_GetVideoInfo
|
||||
@ -1477,21 +1478,6 @@ void SDL_Quit()
|
||||
}
|
||||
|
||||
|
||||
static OsPath GetStdoutPathname()
|
||||
{
|
||||
// the current directory is unreliable, so use the full path to
|
||||
// the current executable.
|
||||
wchar_t pathnameEXE[MAX_PATH];
|
||||
const DWORD charsWritten = GetModuleFileNameW(0, pathnameEXE, ARRAY_SIZE(pathnameEXE));
|
||||
debug_assert(charsWritten);
|
||||
|
||||
// add the EXE name to the filename to allow multiple executables
|
||||
// with their own redirections. (we can't use wutil_ExecutablePath
|
||||
// because it doesn't return the basename)
|
||||
OsPath pathname = OsPath(pathnameEXE).ChangeExtension(L"_stdout.txt");
|
||||
return pathname;
|
||||
}
|
||||
|
||||
static void RedirectStdout()
|
||||
{
|
||||
// this process is apparently attached to a console, and users might be
|
||||
@ -1499,7 +1485,10 @@ static void RedirectStdout()
|
||||
if(wutil_IsValidHandle(GetStdHandle(STD_OUTPUT_HANDLE)))
|
||||
return;
|
||||
|
||||
const OsPath pathname = GetStdoutPathname();
|
||||
// this code may be included in multiple executables sharing the same
|
||||
// directory, so include the executable's name in the filename. use its
|
||||
// full path since the current directory is unreliable.
|
||||
const OsPath pathname = sys_ExecutablePathname().ChangeExtension(L"_stdout.txt");
|
||||
|
||||
// ignore BoundsChecker warnings here. subsystem is set to "Windows"
|
||||
// to prevent the OS from opening a console on startup (ugly).
|
||||
|
@ -363,6 +363,19 @@ LibError sys_error_description_r(int user_err, wchar_t* buf, size_t max_chars)
|
||||
}
|
||||
|
||||
|
||||
static LibError GetModulePathname(HMODULE hModule, OsPath& pathname)
|
||||
{
|
||||
wchar_t pathnameBuf[32768]; // NTFS limit
|
||||
const DWORD length = (DWORD)ARRAY_SIZE(pathnameBuf);
|
||||
const DWORD charsWritten = GetModuleFileNameW(hModule, pathnameBuf, length);
|
||||
if(charsWritten == 0) // failed
|
||||
return LibError_from_GLE();
|
||||
debug_assert(charsWritten < length); // why would the above buffer ever be exceeded?
|
||||
pathname = pathnameBuf;
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
|
||||
LibError sys_get_module_filename(void* addr, OsPath& pathname)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
@ -370,27 +383,15 @@ LibError sys_get_module_filename(void* addr, OsPath& pathname)
|
||||
if(!bytesWritten)
|
||||
return LibError_from_GLE();
|
||||
debug_assert(bytesWritten >= sizeof(mbi));
|
||||
const HMODULE hModule = (HMODULE)mbi.AllocationBase;
|
||||
|
||||
wchar_t pathnameBuf[MAX_PATH+1];
|
||||
const DWORD charsWritten = GetModuleFileNameW(hModule, pathnameBuf, (DWORD)ARRAY_SIZE(pathnameBuf));
|
||||
if(charsWritten == 0)
|
||||
return LibError_from_GLE();
|
||||
debug_assert(charsWritten < ARRAY_SIZE(pathnameBuf));
|
||||
pathname = pathnameBuf;
|
||||
return INFO::OK;
|
||||
return GetModulePathname((HMODULE)mbi.AllocationBase, pathname);
|
||||
}
|
||||
|
||||
|
||||
LibError sys_get_executable_name(OsPath& pathname)
|
||||
OsPath sys_ExecutablePathname()
|
||||
{
|
||||
wchar_t pathnameBuf[MAX_PATH+1];
|
||||
const DWORD charsWritten = GetModuleFileNameW(0, pathnameBuf, (DWORD)ARRAY_SIZE(pathnameBuf));
|
||||
if(charsWritten == 0)
|
||||
return LibError_from_GLE();
|
||||
debug_assert(charsWritten < ARRAY_SIZE(pathnameBuf));
|
||||
pathname = pathnameBuf;
|
||||
return INFO::OK;
|
||||
OsPath pathname;
|
||||
debug_assert(GetModulePathname(0, pathname) == INFO::OK);
|
||||
return pathname;
|
||||
}
|
||||
|
||||
|
||||
@ -437,7 +438,7 @@ LibError sys_pick_directory(OsPath& path)
|
||||
return INFO::SKIPPED;
|
||||
|
||||
// translate ITEMIDLIST to string
|
||||
wchar_t pathBuf[MAX_PATH];
|
||||
wchar_t pathBuf[MAX_PATH]; // mandated by SHGetPathFromIDListW
|
||||
const BOOL ok = SHGetPathFromIDListW(pidl, pathBuf);
|
||||
|
||||
// free the ITEMIDLIST
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "lib/file/file.h"
|
||||
#include "lib/file/vfs/vfs.h"
|
||||
#include "lib/posix/posix.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
#include "lib/sysdep/os/win/win.h"
|
||||
#include "lib/sysdep/os/win/wdbg.h" // wdbg_assert
|
||||
#include "lib/sysdep/os/win/winit.h"
|
||||
@ -266,14 +267,6 @@ bool wutil_HasCommandLineArgument(const wchar_t* arg)
|
||||
//-----------------------------------------------------------------------------
|
||||
// directories
|
||||
|
||||
OsPath wutil_DetectExecutablePath()
|
||||
{
|
||||
wchar_t modulePathname[MAX_PATH+1] = {0};
|
||||
const DWORD len = GetModuleFileNameW(GetModuleHandle(0), modulePathname, MAX_PATH);
|
||||
debug_assert(len != 0);
|
||||
return OsPath(modulePathname).Parent();
|
||||
}
|
||||
|
||||
// (NB: wutil_Init is called before static ctors => use placement new)
|
||||
static OsPath* systemPath;
|
||||
static OsPath* executablePath;
|
||||
@ -298,22 +291,25 @@ const OsPath& wutil_AppdataPath()
|
||||
static void GetDirectories()
|
||||
{
|
||||
WinScopedPreserveLastError s;
|
||||
wchar_t path[MAX_PATH+1] = {0};
|
||||
|
||||
// system directory
|
||||
{
|
||||
const UINT charsWritten = GetSystemDirectoryW(path, MAX_PATH);
|
||||
debug_assert(charsWritten != 0);
|
||||
const UINT length = GetSystemDirectoryW(0, 0);
|
||||
debug_assert(length != 0);
|
||||
std::wstring path(length, '\0');
|
||||
const UINT charsWritten = GetSystemDirectoryW(&path[0], length);
|
||||
debug_assert(charsWritten == length-1);
|
||||
systemPath = new(wutil_Allocate(sizeof(OsPath))) OsPath(path);
|
||||
}
|
||||
|
||||
// executable's directory
|
||||
executablePath = new(wutil_Allocate(sizeof(OsPath))) OsPath(wutil_DetectExecutablePath());
|
||||
executablePath = new(wutil_Allocate(sizeof(OsPath))) OsPath(sys_ExecutablePathname().Parent());
|
||||
|
||||
// application data
|
||||
{
|
||||
HWND hwnd = 0; // ignored unless a dial-up connection is needed to access the folder
|
||||
HANDLE token = 0;
|
||||
wchar_t path[MAX_PATH]; // mandated by SHGetFolderPathW
|
||||
const HRESULT ret = SHGetFolderPathW(hwnd, CSIDL_APPDATA, token, 0, path);
|
||||
debug_assert(SUCCEEDED(ret));
|
||||
appdataPath = new(wutil_Allocate(sizeof(OsPath))) OsPath(path);
|
||||
|
@ -168,10 +168,6 @@ extern bool wutil_HasCommandLineArgument(const wchar_t* arg);
|
||||
//-----------------------------------------------------------------------------
|
||||
// directories
|
||||
|
||||
// used by wutil_ExecutablePath, but provided in case other code
|
||||
// needs to know this before our wutil_Init runs.
|
||||
extern OsPath wutil_DetectExecutablePath();
|
||||
|
||||
extern const OsPath& wutil_SystemPath();
|
||||
extern const OsPath& wutil_ExecutablePath();
|
||||
extern const OsPath& wutil_AppdataPath();
|
||||
|
@ -114,14 +114,11 @@ extern LibError sys_error_description_r(int err, wchar_t* buf, size_t max_chars)
|
||||
LibError sys_get_module_filename(void* addr, OsPath& pathname);
|
||||
|
||||
/**
|
||||
* Get path to the current executable.
|
||||
*
|
||||
* @param pathname Full path to executable (unchanged unless INFO::OK is returned).
|
||||
* @return LibError
|
||||
* @return full pathname of the current executable.
|
||||
*
|
||||
* this is useful for determining installation directory, e.g. for VFS.
|
||||
**/
|
||||
LIB_API LibError sys_get_executable_name(OsPath& pathname);
|
||||
LIB_API OsPath sys_ExecutablePathname();
|
||||
|
||||
/**
|
||||
* Get the current user's login name.
|
||||
|
@ -47,13 +47,12 @@ public:
|
||||
TS_ASSERT_DIFFERS(a, b);
|
||||
}
|
||||
|
||||
void test_sys_get_executable_name()
|
||||
void test_sys_ExecutablePathname()
|
||||
{
|
||||
OsPath path;
|
||||
OsPath path = sys_ExecutablePathname();
|
||||
|
||||
// Try it first with the real executable (i.e. the
|
||||
// one that's running this test code)
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
|
||||
// Check it's absolute
|
||||
TSM_ASSERT(L"Path: "+path.string(), path_is_absolute(path.string().c_str()));
|
||||
// Check the file exists
|
||||
@ -61,7 +60,7 @@ public:
|
||||
TSM_ASSERT_EQUALS(L"Path: "+path.string(), wstat(path, &s), 0);
|
||||
|
||||
// Do some platform-specific tests, based on the
|
||||
// implementations of sys_get_executable_name:
|
||||
// implementations of sys_ExecutablePathname:
|
||||
|
||||
#if OS_LINUX
|
||||
// Since the implementation uses realpath, the tested files need to
|
||||
@ -110,39 +109,34 @@ public:
|
||||
// Try with absolute paths
|
||||
{
|
||||
Mock_dladdr d(rootstr+"/example/executable");
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
|
||||
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
|
||||
TS_ASSERT_PATH_EQUALS(sys_ExecutablePathname(), rootstrw/L"example/executable");
|
||||
}
|
||||
{
|
||||
Mock_dladdr d(rootstr+"/example/./a/b/../e/../../executable");
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
|
||||
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
|
||||
TS_ASSERT_PATH_EQUALS(sys_ExecutablePathname(), rootstrw/L"example/executable");
|
||||
}
|
||||
|
||||
// Try with relative paths
|
||||
{
|
||||
Mock_dladdr d("./executable");
|
||||
Mock_getcwd m(rootstr+"/example");
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
|
||||
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
|
||||
TS_ASSERT_PATH_EQUALS(sys_ExecutablePathname(), rootstrw/L"example/executable");
|
||||
}
|
||||
{
|
||||
Mock_dladdr d("./executable");
|
||||
Mock_getcwd m(rootstr+"/example/");
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
|
||||
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
|
||||
TS_ASSERT_PATH_EQUALS(sys_ExecutablePathname(), rootstrw/L"example/executable");
|
||||
}
|
||||
{
|
||||
Mock_dladdr d("../d/../../f/executable");
|
||||
Mock_getcwd m(rootstr+"/example/a/b/c");
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
|
||||
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/a/f/executable");
|
||||
TS_ASSERT_PATH_EQUALS(sys_ExecutablePathname(), rootstrw/L"example/a/f/executable");
|
||||
}
|
||||
|
||||
// Try with pathless names
|
||||
{
|
||||
Mock_dladdr d("executable");
|
||||
TS_ASSERT_EQUALS(sys_get_executable_name(path), ERR::NO_SYS);
|
||||
TS_ASSERT_PATH_EQUALS(sys_ExecutablePathname(), OsPath());
|
||||
}
|
||||
|
||||
// Clean up the temporary files
|
||||
@ -161,7 +155,7 @@ public:
|
||||
#endif // OS_LINUX
|
||||
}
|
||||
|
||||
// Mock classes for test_sys_get_executable_name
|
||||
// Mock classes for test_sys_ExecutablePathname
|
||||
#if OS_LINUX
|
||||
class Mock_dladdr : public T::Base_dladdr
|
||||
{
|
||||
|
@ -73,11 +73,9 @@ Paths::Paths(const CmdLineArgs& args)
|
||||
/*static*/ OsPath Paths::Root(const OsPath& argv0)
|
||||
{
|
||||
// get full path to executable
|
||||
OsPath pathname;
|
||||
// .. first try safe, but system-dependent version
|
||||
if(sys_get_executable_name(pathname) != INFO::OK)
|
||||
OsPath pathname = sys_ExecutablePathname(); // safe, but requires OS-specific implementation
|
||||
if(pathname.empty()) // failed, use argv[0] instead
|
||||
{
|
||||
// .. failed; use argv[0]
|
||||
errno = 0;
|
||||
pathname = wrealpath(argv0);
|
||||
if(pathname.empty())
|
||||
|
@ -90,12 +90,10 @@ bool ts_str_contains(const std::wstring& str1, const std::wstring& str2)
|
||||
// we need the (version-controlled) binaries/data directory because it
|
||||
// contains input files (it is assumed that developer's machines have
|
||||
// write access to those directories). note that argv0 isn't
|
||||
// available, so we use sys_get_executable_name.
|
||||
// available, so we use sys_ExecutablePathname.
|
||||
OsPath DataDir()
|
||||
{
|
||||
OsPath path;
|
||||
TS_ASSERT_OK(sys_get_executable_name(path));
|
||||
return path.Parent()/"../data";
|
||||
return sys_ExecutablePathname().Parent()/"../data";
|
||||
}
|
||||
|
||||
// Script-based testing setup:
|
||||
|
Loading…
Reference in New Issue
Block a user