Dynamically allocate path name buffer for Unicode

path name in listdir. Fixes #1431582.
Stop overallocating MAX_PATH characters for ANSI
path names. Stop assigning to errno.
This commit is contained in:
Martin v. Löwis 2006-05-12 12:27:28 +00:00
parent b06d28c160
commit 682b1bb95f
2 changed files with 33 additions and 19 deletions

View File

@ -72,6 +72,9 @@ Core and builtins
Extension Modules Extension Modules
----------------- -----------------
- On Win32, os.listdir now supports arbitrarily-long Unicode path names
(up to the system limit of 32K characters).
- Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}. - Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
As a result, these functions now raise WindowsError instead of OSError. As a result, these functions now raise WindowsError instead of OSError.

View File

@ -1782,37 +1782,46 @@ posix_listdir(PyObject *self, PyObject *args)
HANDLE hFindFile; HANDLE hFindFile;
BOOL result; BOOL result;
WIN32_FIND_DATA FileData; WIN32_FIND_DATA FileData;
/* MAX_PATH characters could mean a bigger encoded string */ char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
char namebuf[MAX_PATH*2+5];
char *bufptr = namebuf; char *bufptr = namebuf;
Py_ssize_t len = sizeof(namebuf)/sizeof(namebuf[0]); Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
#ifdef Py_WIN_WIDE_FILENAMES #ifdef Py_WIN_WIDE_FILENAMES
/* If on wide-character-capable OS see if argument /* If on wide-character-capable OS see if argument
is Unicode and if so use wide API. */ is Unicode and if so use wide API. */
if (unicode_file_names()) { if (unicode_file_names()) {
PyUnicodeObject *po; PyObject *po;
if (PyArg_ParseTuple(args, "U:listdir", &po)) { if (PyArg_ParseTuple(args, "U:listdir", &po)) {
WIN32_FIND_DATAW wFileData; WIN32_FIND_DATAW wFileData;
Py_UNICODE wnamebuf[MAX_PATH*2+5]; Py_UNICODE *wnamebuf;
Py_UNICODE wch; Py_UNICODE wch;
wcsncpy(wnamebuf, PyUnicode_AS_UNICODE(po), MAX_PATH); /* Overallocate for \\*.*\0 */
wnamebuf[MAX_PATH] = L'\0'; len = PyUnicode_GET_SIZE(po);
len = wcslen(wnamebuf); wnamebuf = malloc((len + 5) * sizeof(wchar_t));
wch = (len > 0) ? wnamebuf[len-1] : L'\0'; if (!wnamebuf) {
if (wch != L'/' && wch != L'\\' && wch != L':') PyErr_NoMemory();
wnamebuf[len++] = L'/';
wcscpy(wnamebuf + len, L"*.*");
if ((d = PyList_New(0)) == NULL)
return NULL; return NULL;
}
wcscpy(wnamebuf, PyUnicode_AS_UNICODE(po));
wch = len > 0 ? wnamebuf[len-1] : '\0';
if (wch != L'/' && wch != L'\\' && wch != L':')
wnamebuf[len++] = L'\\';
wcscpy(wnamebuf + len, L"*.*");
if ((d = PyList_New(0)) == NULL) {
free(wnamebuf);
return NULL;
}
hFindFile = FindFirstFileW(wnamebuf, &wFileData); hFindFile = FindFirstFileW(wnamebuf, &wFileData);
if (hFindFile == INVALID_HANDLE_VALUE) { if (hFindFile == INVALID_HANDLE_VALUE) {
errno = GetLastError(); int error = GetLastError();
if (errno == ERROR_FILE_NOT_FOUND) { if (error == ERROR_FILE_NOT_FOUND) {
free(wnamebuf);
return d; return d;
} }
Py_DECREF(d); Py_DECREF(d);
return win32_error_unicode("FindFirstFileW", wnamebuf); win32_error_unicode("FindFirstFileW", wnamebuf);
free(wnamebuf);
return NULL;
} }
do { do {
/* Skip over . and .. */ /* Skip over . and .. */
@ -1839,7 +1848,9 @@ posix_listdir(PyObject *self, PyObject *args)
if (FindClose(hFindFile) == FALSE) { if (FindClose(hFindFile) == FALSE) {
Py_DECREF(d); Py_DECREF(d);
return win32_error_unicode("FindClose", wnamebuf); win32_error_unicode("FindClose", wnamebuf);
free(wnamebuf);
return NULL;
} }
return d; return d;
} }
@ -1864,8 +1875,8 @@ posix_listdir(PyObject *self, PyObject *args)
hFindFile = FindFirstFile(namebuf, &FileData); hFindFile = FindFirstFile(namebuf, &FileData);
if (hFindFile == INVALID_HANDLE_VALUE) { if (hFindFile == INVALID_HANDLE_VALUE) {
errno = GetLastError(); int error = GetLastError();
if (errno == ERROR_FILE_NOT_FOUND) if (error == ERROR_FILE_NOT_FOUND)
return d; return d;
Py_DECREF(d); Py_DECREF(d);
return win32_error("FindFirstFile", namebuf); return win32_error("FindFirstFile", namebuf);