Patch #954115: Fix os.stat handling of UNC roots.
Will backport to 2.3.
This commit is contained in:
parent
0659452b8b
commit
d8948725d2
|
@ -210,6 +210,8 @@ Core and builtins
|
||||||
Extension modules
|
Extension modules
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- nt now properly allows to refer to UNC roots, e.g. in nt.stat().
|
||||||
|
|
||||||
- the weakref module now supports additional objects: array.array,
|
- the weakref module now supports additional objects: array.array,
|
||||||
sre.pattern_objects, file objects, and sockets.
|
sre.pattern_objects, file objects, and sockets.
|
||||||
|
|
||||||
|
|
|
@ -892,6 +892,66 @@ _pystat_fromstructstat(STRUCT_STAT st)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
|
||||||
|
/* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\,
|
||||||
|
where / can be used in place of \ and the trailing slash is optional.
|
||||||
|
Both SERVER and SHARE must have at least one character.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ISSLASHA(c) ((c) == '\\' || (c) == '/')
|
||||||
|
#define ISSLASHW(c) ((c) == L'\\' || (c) == L'/')
|
||||||
|
#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
IsUNCRootA(char *path, int pathlen)
|
||||||
|
{
|
||||||
|
#define ISSLASH ISSLASHA
|
||||||
|
|
||||||
|
int i, share;
|
||||||
|
|
||||||
|
if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
|
||||||
|
/* minimum UNCRoot is \\x\y */
|
||||||
|
return FALSE;
|
||||||
|
for (i = 2; i < pathlen ; i++)
|
||||||
|
if (ISSLASH(path[i])) break;
|
||||||
|
if (i == 2 || i == pathlen)
|
||||||
|
/* do not allow \\\SHARE or \\SERVER */
|
||||||
|
return FALSE;
|
||||||
|
share = i+1;
|
||||||
|
for (i = share; i < pathlen; i++)
|
||||||
|
if (ISSLASH(path[i])) break;
|
||||||
|
return (i != share && (i == pathlen || i == pathlen-1));
|
||||||
|
|
||||||
|
#undef ISSLASH
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Py_WIN_WIDE_FILENAMES
|
||||||
|
static BOOL
|
||||||
|
IsUNCRootW(Py_UNICODE *path, int pathlen)
|
||||||
|
{
|
||||||
|
#define ISSLASH ISSLASHW
|
||||||
|
|
||||||
|
int i, share;
|
||||||
|
|
||||||
|
if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
|
||||||
|
/* minimum UNCRoot is \\x\y */
|
||||||
|
return FALSE;
|
||||||
|
for (i = 2; i < pathlen ; i++)
|
||||||
|
if (ISSLASH(path[i])) break;
|
||||||
|
if (i == 2 || i == pathlen)
|
||||||
|
/* do not allow \\\SHARE or \\SERVER */
|
||||||
|
return FALSE;
|
||||||
|
share = i+1;
|
||||||
|
for (i = share; i < pathlen; i++)
|
||||||
|
if (ISSLASH(path[i])) break;
|
||||||
|
return (i != share && (i == pathlen || i == pathlen-1));
|
||||||
|
|
||||||
|
#undef ISSLASH
|
||||||
|
}
|
||||||
|
#endif /* Py_WIN_WIDE_FILENAMES */
|
||||||
|
#endif /* MS_WINDOWS */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
posix_do_stat(PyObject *self, PyObject *args,
|
posix_do_stat(PyObject *self, PyObject *args,
|
||||||
char *format,
|
char *format,
|
||||||
|
@ -931,15 +991,22 @@ posix_do_stat(PyObject *self, PyObject *args,
|
||||||
/* Remove trailing slash or backslash, unless it's the current
|
/* Remove trailing slash or backslash, unless it's the current
|
||||||
drive root (/ or \) or a specific drive's root (like c:\ or c:/).
|
drive root (/ or \) or a specific drive's root (like c:\ or c:/).
|
||||||
*/
|
*/
|
||||||
if (pathlen > 0 &&
|
if (pathlen > 0) {
|
||||||
(wpath[pathlen-1]== L'\\' || wpath[pathlen-1] == L'/')) {
|
if (ISSLASHW(wpath[pathlen-1])) {
|
||||||
/* It does end with a slash -- exempt the root drive cases. */
|
/* It does end with a slash -- exempt the root drive cases. */
|
||||||
/* XXX UNC root drives should also be exempted? */
|
if (pathlen == 1 || (pathlen == 3 && wpath[1] == L':') ||
|
||||||
if (pathlen == 1 || (pathlen == 3 && wpath[1] == L':'))
|
IsUNCRootW(wpath, pathlen))
|
||||||
/* leave it alone */;
|
/* leave it alone */;
|
||||||
else {
|
else {
|
||||||
/* nuke the trailing backslash */
|
/* nuke the trailing backslash */
|
||||||
wpath[pathlen-1] = L'\0';
|
wpath[pathlen-1] = L'\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ISSLASHW(wpath[1]) && pathlen < ARRAYSIZE(wpath)-1 &&
|
||||||
|
IsUNCRootW(wpath, pathlen)) {
|
||||||
|
/* UNC root w/o trailing slash: add one when there's room */
|
||||||
|
wpath[pathlen++] = L'\\';
|
||||||
|
wpath[pathlen] = L'\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
@ -974,16 +1041,25 @@ posix_do_stat(PyObject *self, PyObject *args,
|
||||||
/* Remove trailing slash or backslash, unless it's the current
|
/* Remove trailing slash or backslash, unless it's the current
|
||||||
drive root (/ or \) or a specific drive's root (like c:\ or c:/).
|
drive root (/ or \) or a specific drive's root (like c:\ or c:/).
|
||||||
*/
|
*/
|
||||||
if (pathlen > 0 &&
|
if (pathlen > 0) {
|
||||||
(path[pathlen-1]== '\\' || path[pathlen-1] == '/')) {
|
if (ISSLASHA(path[pathlen-1])) {
|
||||||
/* It does end with a slash -- exempt the root drive cases. */
|
/* It does end with a slash -- exempt the root drive cases. */
|
||||||
/* XXX UNC root drives should also be exempted? */
|
if (pathlen == 1 || (pathlen == 3 && path[1] == ':') ||
|
||||||
if (pathlen == 1 || (pathlen == 3 && path[1] == ':'))
|
IsUNCRootA(path, pathlen))
|
||||||
/* leave it alone */;
|
/* leave it alone */;
|
||||||
else {
|
else {
|
||||||
/* nuke the trailing backslash */
|
/* nuke the trailing backslash */
|
||||||
|
strncpy(pathcopy, path, pathlen);
|
||||||
|
pathcopy[pathlen-1] = '\0';
|
||||||
|
path = pathcopy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ISSLASHA(path[1]) && pathlen < ARRAYSIZE(pathcopy)-1 &&
|
||||||
|
IsUNCRootA(path, pathlen)) {
|
||||||
|
/* UNC root w/o trailing slash: add one when there's room */
|
||||||
strncpy(pathcopy, path, pathlen);
|
strncpy(pathcopy, path, pathlen);
|
||||||
pathcopy[pathlen-1] = '\0';
|
pathcopy[pathlen++] = '\\';
|
||||||
|
pathcopy[pathlen] = '\0';
|
||||||
path = pathcopy;
|
path = pathcopy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue