diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-06-25 13:02:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-25 13:02:43 (GMT) |
commit | 3939c321c90283b49eddde762656e4b1940e7150 (patch) | |
tree | f2b8429629e80925feac81280c7696a16a0328ea /Python/fileutils.c | |
parent | 080b6b40fa6c6ddc79dcfcadab575bb1be3f47e9 (diff) | |
download | cpython-3939c321c90283b49eddde762656e4b1940e7150.zip cpython-3939c321c90283b49eddde762656e4b1940e7150.tar.gz cpython-3939c321c90283b49eddde762656e4b1940e7150.tar.bz2 |
bpo-20443: _PyConfig_Read() gets the absolute path of run_filename (GH-14053)
Python now gets the absolute path of the script filename specified on
the command line (ex: "python3 script.py"): the __file__ attribute of
the __main__ module, sys.argv[0] and sys.path[0] become an absolute
path, rather than a relative path.
* Add _Py_isabs() and _Py_abspath() functions.
* _PyConfig_Read() now tries to get the absolute path of
run_filename, but keeps the relative path if _Py_abspath() fails.
* Reimplement os._getfullpathname() using _Py_abspath().
* Use _Py_isabs() in getpath.c.
Diffstat (limited to 'Python/fileutils.c')
-rw-r--r-- | Python/fileutils.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c index 93c093f..55bc194 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1734,6 +1734,103 @@ _Py_wrealpath(const wchar_t *path, } #endif + +#ifndef MS_WINDOWS +int +_Py_isabs(const wchar_t *path) +{ + return (path[0] == SEP); +} +#endif + + +/* Get an absolute path. + On error (ex: fail to get the current directory), return -1. + On memory allocation failure, set *abspath_p to NULL and return 0. + On success, return a newly allocated to *abspath_p to and return 0. + The string must be freed by PyMem_RawFree(). */ +int +_Py_abspath(const wchar_t *path, wchar_t **abspath_p) +{ +#ifdef MS_WINDOWS + wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; + DWORD result; + + result = GetFullPathNameW(path, + Py_ARRAY_LENGTH(woutbuf), woutbuf, + NULL); + if (!result) { + return -1; + } + + if (result > Py_ARRAY_LENGTH(woutbuf)) { + if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { + woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t)); + } + else { + woutbufp = NULL; + } + if (!woutbufp) { + *abspath_p = NULL; + return 0; + } + + result = GetFullPathNameW(path, result, woutbufp, NULL); + if (!result) { + PyMem_RawFree(woutbufp); + return -1; + } + } + + if (woutbufp != woutbuf) { + *abspath_p = woutbufp; + return 0; + } + + *abspath_p = _PyMem_RawWcsdup(woutbufp); + return 0; +#else + if (_Py_isabs(path)) { + *abspath_p = _PyMem_RawWcsdup(path); + return 0; + } + + wchar_t cwd[MAXPATHLEN + 1]; + cwd[Py_ARRAY_LENGTH(cwd) - 1] = 0; + if (!_Py_wgetcwd(cwd, Py_ARRAY_LENGTH(cwd) - 1)) { + /* unable to get the current directory */ + return -1; + } + + size_t cwd_len = wcslen(cwd); + size_t path_len = wcslen(path); + size_t len = cwd_len + 1 + path_len + 1; + if (len <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) { + *abspath_p = PyMem_RawMalloc(len * sizeof(wchar_t)); + } + else { + *abspath_p = NULL; + } + if (*abspath_p == NULL) { + return 0; + } + + wchar_t *abspath = *abspath_p; + memcpy(abspath, cwd, cwd_len * sizeof(wchar_t)); + abspath += cwd_len; + + *abspath = (wchar_t)SEP; + abspath++; + + memcpy(abspath, path, path_len * sizeof(wchar_t)); + abspath += path_len; + + *abspath = 0; + return 0; +#endif +} + + /* Get the current directory. buflen is the buffer size in wide characters including the null character. Decode the path from the locale encoding. |