finally:
os.chdir(old_dir)
+ @unittest.skipIf(sys.platform != 'win32', "Win32 specific test")
+ def test_windows_trailing_space_path(self):
+ import pathlib
+
+ filename = self.create_file("file.txt")
+ path = self.path + " "
+
+ self.assertTrue(os.path.exists(path))
+ os.stat(path)
+ with open(filename + " ", "rb") as file:
+ self.assertEqual(file.read(), b"python")
+
+ self.assertEqual(os.listdir(path), ["file.txt"])
+ with os.scandir(path) as entries:
+ self.assertEqual([entry.name for entry in entries], ["file.txt"])
+ pathlib_entries = list(pathlib.Path(path).iterdir())
+ self.assertEqual([entry.name for entry in pathlib_entries], ["file.txt"])
+ del pathlib_entries
+
+ extended_path = "\\\\?\\" + path
+ self.assertFalse(os.path.exists(extended_path))
+ self.assertRaises(FileNotFoundError, os.listdir, extended_path)
+ self.assertRaises(FileNotFoundError, os.scandir, extended_path)
+
def test_repr(self):
entry = self.create_file_entry()
self.assertEqual(repr(entry), "<DirEntry 'file.txt'>")
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
+static wchar_t *
+join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
+ int normalize);
+
static PyObject *
_listdir_windows_no_opendir(path_t *path, PyObject *list)
{
PyObject *v;
HANDLE hFindFile = INVALID_HANDLE_VALUE;
BOOL result, return_bytes;
- wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
- /* only claim to have space for MAX_PATH */
- Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
wchar_t *wnamebuf = NULL;
WIN32_FIND_DATAW wFileData;
if (!path->wide) { /* Default arg: "." */
po_wchars = L".";
- len = 1;
return_bytes = 0;
} else {
po_wchars = path->wide;
- len = wcslen(path->wide);
return_bytes = PyBytes_Check(path->object);
}
- /* The +5 is so we can append "\\*.*\0" */
- wnamebuf = PyMem_New(wchar_t, len + 5);
- if (!wnamebuf) {
- PyErr_NoMemory();
+
+ wnamebuf = join_path_filenameW(po_wchars, L"*.*", 1);
+ if (wnamebuf == NULL) {
goto exit;
}
- wcscpy(wnamebuf, po_wchars);
- if (len > 0) {
- wchar_t wch = wnamebuf[len-1];
- if (wch != SEP && wch != ALTSEP && wch != L':')
- wnamebuf[len++] = SEP;
- wcscpy(wnamebuf + len, L"*.*");
- }
+
if ((list = PyList_New(0)) == NULL) {
goto exit;
}
#ifdef MS_WINDOWS
+static int
+is_extended_path(const wchar_t *path)
+{
+ return wcsncmp(path, L"\\\\?\\", 4) == 0;
+}
+
static wchar_t *
-join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
+join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename,
+ int normalize)
{
Py_ssize_t path_len;
- Py_ssize_t size;
wchar_t *result;
- wchar_t ch;
+ wchar_t *path_allocated = NULL;
if (!path_wide) { /* Default arg: "." */
path_wide = L".";
path_len = wcslen(path_wide);
}
- /* The +1's are for the path separator and the NUL */
- size = path_len + 1 + wcslen(filename) + 1;
+ if (path_len == 0) {
+ result = PyMem_New(wchar_t, 1);
+ if (result == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ result[0] = L'\0';
+ return result;
+ }
+
+ if (normalize && !is_extended_path(path_wide)) {
+ int err = _PyOS_getfullpathname(path_wide, &path_allocated);
+ if (err < 0) {
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+ if (path_allocated == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ path_wide = path_allocated;
+ path_len = wcslen(path_wide);
+ }
+
+ size_t size = (size_t)path_len + 1 + wcslen(filename) + 1;
result = PyMem_New(wchar_t, size);
- if (!result) {
+ if (result == NULL) {
+ PyMem_RawFree(path_allocated);
PyErr_NoMemory();
return NULL;
}
wcscpy(result, path_wide);
- if (path_len > 0) {
- ch = result[path_len - 1];
- if (ch != SEP && ch != ALTSEP && ch != L':')
- result[path_len++] = SEP;
- wcscpy(result + path_len, filename);
+ wchar_t ch = result[path_len - 1];
+ if (ch != SEP && ch != ALTSEP && ch != L':') {
+ result[path_len++] = SEP;
}
+ wcscpy(result + path_len, filename);
+ PyMem_RawFree(path_allocated);
return result;
}
goto error;
}
- joined_path = join_path_filenameW(path->wide, dataW->cFileName);
+ joined_path = join_path_filenameW(path->wide, dataW->cFileName, 0);
if (!joined_path)
goto error;
#ifdef MS_WINDOWS
iterator->first_time = 1;
- path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
+ path_strW = join_path_filenameW(iterator->path.wide, L"*.*", 1);
if (!path_strW)
goto error;