Index: Include/pyerrors.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pyerrors.h,v retrieving revision 2.60 diff -c -r2.60 pyerrors.h *** Include/pyerrors.h 15 Sep 2002 14:09:21 -0000 2.60 --- Include/pyerrors.h 30 Sep 2002 12:47:28 -0000 *************** *** 81,96 **** PyAPI_FUNC(int) PyErr_BadArgument(void); PyAPI_FUNC(PyObject *) PyErr_NoMemory(void); PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(PyObject *, char *); PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...) Py_GCC_ATTRIBUTE((format(printf, 2, 3))); #ifdef MS_WINDOWS ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename(int, const char *); PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( PyObject *,int, const char *); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); ! #endif /* Export the old function so that the existing API remains available: */ PyAPI_FUNC(void) PyErr_BadInternalCall(void); --- 81,117 ---- PyAPI_FUNC(int) PyErr_BadArgument(void); PyAPI_FUNC(PyObject *) PyErr_NoMemory(void); PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); + PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObject( + PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(PyObject *, char *); + #ifdef Py_WIN_WIDE_FILENAMES + PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename( + PyObject *, Py_UNICODE *); + #endif /* Py_WIN_WIDE_FILENAMES */ + PyAPI_FUNC(PyObject *) PyErr_Format(PyObject *, const char *, ...) Py_GCC_ATTRIBUTE((format(printf, 2, 3))); + #ifdef MS_WINDOWS ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenameObject( ! int, const char *); ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilename( ! int, const char *); ! #ifdef Py_WIN_WIDE_FILENAMES ! PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename( ! int, const Py_UNICODE *); ! #endif /* Py_WIN_WIDE_FILENAMES */ PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); + PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject( + PyObject *,int, PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( PyObject *,int, const char *); + #ifdef Py_WIN_WIDE_FILENAMES + PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename( + PyObject *,int, const Py_UNICODE *); + #endif /* Py_WIN_WIDE_FILENAMES */ PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); ! #endif /* MS_WINDOWS */ /* Export the old function so that the existing API remains available: */ PyAPI_FUNC(void) PyErr_BadInternalCall(void); Index: Lib/test/test_unicode_file.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/test/test_unicode_file.py,v retrieving revision 1.5 diff -c -r1.5 test_unicode_file.py *** Lib/test/test_unicode_file.py 23 Jul 2002 19:04:08 -0000 1.5 --- Lib/test/test_unicode_file.py 30 Sep 2002 12:47:28 -0000 *************** *** 40,45 **** --- 40,49 ---- os.chmod(TESTFN_UNICODE, 0777) # Test rename + try: + os.unlink(TESTFN_ENCODED + ".new") + except os.error: + pass os.rename(TESTFN_ENCODED, TESTFN_ENCODED + ".new") os.rename(TESTFN_UNICODE+".new", TESTFN_ENCODED) Index: Modules/posixmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/posixmodule.c,v retrieving revision 2.260 diff -c -r2.260 posixmodule.c *** Modules/posixmodule.c 19 Sep 2002 08:03:20 -0000 2.260 --- Modules/posixmodule.c 30 Sep 2002 12:47:32 -0000 *************** *** 367,372 **** --- 367,381 ---- return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); } + #ifdef Py_WIN_WIDE_FILENAMES + static PyObject * + posix_error_with_unicode_filename(Py_UNICODE* name) + { + return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name); + } + #endif /* Py_WIN_WIDE_FILENAMES */ + + static PyObject * posix_error_with_allocated_filename(char* name) { *************** *** 390,395 **** --- 399,438 ---- else return PyErr_SetFromWindowsErr(errno); } + + #ifdef Py_WIN_WIDE_FILENAMES + static PyObject * + win32_error_unicode(char* function, Py_UNICODE* filename) + { + /* XXX - see win32_error for comments on 'function' */ + errno = GetLastError(); + if (filename) + return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename); + else + return PyErr_SetFromWindowsErr(errno); + } + + static PyObject *_PyUnicode_FromFileSystemEncodedObject(register PyObject *obj) + { + /* XXX Perhaps we should make this API an alias of + PyObject_Unicode() instead ?! */ + if (PyUnicode_CheckExact(obj)) { + Py_INCREF(obj); + return obj; + } + if (PyUnicode_Check(obj)) { + /* For a Unicode subtype that's not a Unicode object, + return a true Unicode object with the same data. */ + return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(obj), + PyUnicode_GET_SIZE(obj)); + } + return PyUnicode_FromEncodedObject(obj, + Py_FileSystemDefaultEncoding, + "strict"); + } + + #endif /* Py_WIN_WIDE_FILENAMES */ + #endif #if defined(PYOS_OS2) *************** *** 487,497 **** return Py_None; } static PyObject * ! posix_1str(PyObject *args, char *format, int (*func)(const char*)) { char *path1 = NULL; int res; if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1)) return NULL; --- 530,579 ---- return Py_None; } + #ifdef Py_WIN_WIDE_FILENAMES + static int + unicode_file_names(void) + { + static int canusewide = -1; + if (canusewide == -1) { + /* As per doc for ::GetVersion(), this is the correct test for + the Windows NT family. */ + canusewide = (GetVersion() < 0x80000000) ? 1 : 0; + } + return canusewide; + } + #endif + static PyObject * ! posix_1str(PyObject *args, char *format, int (*func)(const char*), ! char *wformat, int (*wfunc)(const Py_UNICODE*)) { char *path1 = NULL; int res; + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, wformat, &po)) { + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread + lock as it is a simple dereference. */ + res = (*wfunc)(PyUnicode_AS_UNICODE(po)); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; + } + /* Drop the argument parsing error as narrow + strings are also valid. */ + PyErr_Clear(); + } + #else + /* Platforms that don't support Unicode filenames + shouldn't be passing these extra params */ + assert(wformat==NULL && wfunc == NULL); + #endif + if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1)) return NULL; *************** *** 506,516 **** } static PyObject * ! posix_2str(PyObject *args, char *format, ! int (*func)(const char *, const char *)) { char *path1 = NULL, *path2 = NULL; int res; if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1, Py_FileSystemDefaultEncoding, &path2)) --- 588,638 ---- } static PyObject * ! posix_2str(PyObject *args, ! char *format, ! int (*func)(const char *, const char *), ! char *wformat, ! int (*wfunc)(const Py_UNICODE *, const Py_UNICODE *)) { char *path1 = NULL, *path2 = NULL; int res; + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyObject *po1; + PyObject *po2; + if (PyArg_ParseTuple(args, wformat, &po1, &po2)) { + if (PyUnicode_Check(po1) || PyUnicode_Check(po2)) { + PyObject *wpath1; + PyObject *wpath2; + wpath1 = _PyUnicode_FromFileSystemEncodedObject(po1); + wpath2 = _PyUnicode_FromFileSystemEncodedObject(po2); + if (!wpath1 || !wpath2) + return NULL; + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread + lock as it is a simple dereference. */ + res = (*wfunc)(PyUnicode_AS_UNICODE(wpath1), + PyUnicode_AS_UNICODE(wpath2)); + Py_END_ALLOW_THREADS + Py_XDECREF(wpath1); + Py_XDECREF(wpath2); + if (res != 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; + } + /* Else flow through as neither is Unicode. */ + } + /* Drop the argument parsing error as narrow + strings are also valid. */ + PyErr_Clear(); + } + #else + /* Platforms that don't support Unicode filenames + shouldn't be passing these extra params */ + assert(wformat==NULL && wfunc == NULL); + #endif + if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path1, Py_FileSystemDefaultEncoding, &path2)) *************** *** 692,699 **** } static PyObject * ! posix_do_stat(PyObject *self, PyObject *args, char *format, ! int (*statfunc)(const char *, STRUCT_STAT *)) { STRUCT_STAT st; char *path = NULL; /* pass this to stat; do not free() it */ --- 814,824 ---- } static PyObject * ! posix_do_stat(PyObject *self, PyObject *args, ! char *format, ! int (*statfunc)(const char *, STRUCT_STAT *), ! char *wformat, ! int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *)) { STRUCT_STAT st; char *path = NULL; /* pass this to stat; do not free() it */ *************** *** 705,710 **** --- 830,879 ---- char pathcopy[MAX_PATH]; #endif /* MS_WINDOWS */ + + #ifdef Py_WIN_WIDE_FILENAMES + /* If on wide-character-capable OS see if argument + is Unicode and if so use wide API. */ + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, wformat, &po)) { + Py_UNICODE wpath[MAX_PATH+1]; + pathlen = wcslen(PyUnicode_AS_UNICODE(po)); + /* the library call can blow up if the file name is too long! */ + if (pathlen > MAX_PATH) { + errno = ENAMETOOLONG; + return posix_error(); + } + wcscpy(wpath, PyUnicode_AS_UNICODE(po)); + /* Remove trailing slash or backslash, unless it's the current + drive root (/ or \) or a specific drive's root (like c:\ or c:/). + */ + if (pathlen > 0 && + (wpath[pathlen-1]== L'\\' || wpath[pathlen-1] == L'/')) { + /* 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':')) + /* leave it alone */; + else { + /* nuke the trailing backslash */ + wpath[pathlen-1] = L'\0'; + } + } + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE result OK without + thread lock as it is a simple dereference. */ + res = wstatfunc(wpath, &st); + Py_END_ALLOW_THREADS + if (res != 0) + return posix_error_with_unicode_filename(wpath); + return _pystat_fromstructstat(st); + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, format, Py_FileSystemDefaultEncoding, &path)) return NULL; *************** *** 839,848 **** static PyObject * posix_chdir(PyObject *self, PyObject *args) { ! #if defined(PYOS_OS2) && defined(PYCC_GCC) ! return posix_1str(args, "et:chdir", _chdir2); #else ! return posix_1str(args, "et:chdir", chdir); #endif } --- 1008,1019 ---- static PyObject * posix_chdir(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_1str(args, "et:chdir", chdir, "U:chdir", _wchdir); ! #elif defined(PYOS_OS2) && defined(PYCC_GCC) ! return posix_1str(args, "et:chdir", _chdir2, NULL, NULL); #else ! return posix_1str(args, "et:chdir", chdir, NULL, NULL); #endif } *************** *** 892,898 **** static PyObject * posix_chroot(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:chroot", chroot); } #endif --- 1063,1069 ---- static PyObject * posix_chroot(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:chroot", chroot, NULL, NULL); } #endif *************** *** 1004,1009 **** --- 1175,1217 ---- return posix_error(); return PyString_FromString(buf); } + + PyDoc_STRVAR(posix_getcwdu__doc__, + "getcwdu() -> path\n\n\ + Return a unicode string representing the current working directory."); + + static PyObject * + posix_getcwdu(PyObject *self, PyObject *args) + { + char buf[1026]; + char *res; + if (!PyArg_ParseTuple(args, ":getcwd")) + return NULL; + + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + wchar_t *wres; + wchar_t wbuf[1026]; + Py_BEGIN_ALLOW_THREADS + wres = _wgetcwd(wbuf, sizeof wbuf/ sizeof wbuf[0]); + Py_END_ALLOW_THREADS + if (wres == NULL) + return posix_error(); + return PyUnicode_FromWideChar(wbuf, wcslen(wbuf)); + } + #endif + + Py_BEGIN_ALLOW_THREADS + #if defined(PYOS_OS2) && defined(PYCC_GCC) + res = _getcwd2(buf, sizeof buf); + #else + res = getcwd(buf, sizeof buf); + #endif + Py_END_ALLOW_THREADS + if (res == NULL) + return posix_error(); + return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict"); + } #endif *************** *** 1015,1021 **** static PyObject * posix_link(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:link", link); } #endif /* HAVE_LINK */ --- 1223,1229 ---- static PyObject * posix_link(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:link", link, NULL, NULL); } #endif /* HAVE_LINK */ *************** *** 1044,1049 **** --- 1252,1317 ---- char *bufptr = namebuf; int len = sizeof(namebuf)/sizeof(namebuf[0]); + #ifdef Py_WIN_WIDE_FILENAMES + /* If on wide-character-capable OS see if argument + is Unicode and if so use wide API. */ + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U:listdir", &po)) { + WIN32_FIND_DATAW wFileData; + Py_UNICODE wnamebuf[MAX_PATH*2+5]; + Py_UNICODE wch; + wcsncpy(wnamebuf, PyUnicode_AS_UNICODE(po), MAX_PATH); + wnamebuf[MAX_PATH] = L'\0'; + len = wcslen(wnamebuf); + wch = (len > 0) ? wnamebuf[len-1] : L'\0'; + if (wch != L'/' && wch != L'\\' && wch != L':') + wnamebuf[len++] = L'/'; + wcscpy(wnamebuf + len, L"*.*"); + if ((d = PyList_New(0)) == NULL) + return NULL; + hFindFile = FindFirstFileW(wnamebuf, &wFileData); + if (hFindFile == INVALID_HANDLE_VALUE) { + errno = GetLastError(); + if (errno == ERROR_FILE_NOT_FOUND) { + return d; + } + Py_DECREF(d); + return win32_error_unicode("FindFirstFileW", wnamebuf); + } + do { + if (wFileData.cFileName[0] == L'.' && + (wFileData.cFileName[1] == L'\0' || + wFileData.cFileName[1] == L'.' && + wFileData.cFileName[2] == L'\0')) + continue; + v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName)); + if (v == NULL) { + Py_DECREF(d); + d = NULL; + break; + } + if (PyList_Append(d, v) != 0) { + Py_DECREF(v); + Py_DECREF(d); + d = NULL; + break; + } + Py_DECREF(v); + } while (FindNextFileW(hFindFile, &wFileData) == TRUE); + + if (FindClose(hFindFile) == FALSE) { + Py_DECREF(d); + return win32_error_unicode("FindClose", wnamebuf); + } + return d; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, "et#:listdir", Py_FileSystemDefaultEncoding, &bufptr, &len)) return NULL; *************** *** 1061,1067 **** if (hFindFile == INVALID_HANDLE_VALUE) { errno = GetLastError(); if (errno == ERROR_FILE_NOT_FOUND) ! return PyList_New(0); return win32_error("FindFirstFile", namebuf); } do { --- 1329,1336 ---- if (hFindFile == INVALID_HANDLE_VALUE) { errno = GetLastError(); if (errno == ERROR_FILE_NOT_FOUND) ! return d; ! Py_DECREF(d); return win32_error("FindFirstFile", namebuf); } do { *************** *** 1085,1092 **** Py_DECREF(v); } while (FindNextFile(hFindFile, &FileData) == TRUE); ! if (FindClose(hFindFile) == FALSE) return win32_error("FindClose", namebuf); return d; --- 1354,1363 ---- Py_DECREF(v); } while (FindNextFile(hFindFile, &FileData) == TRUE); ! if (FindClose(hFindFile) == FALSE) { ! Py_DECREF(d); return win32_error("FindClose", namebuf); + } return d; *************** *** 1213,1218 **** --- 1484,1506 ---- int insize = sizeof(inbuf)/sizeof(inbuf[0]); char outbuf[MAX_PATH*2]; char *temp; + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) { + Py_UNICODE woutbuf[MAX_PATH*2]; + Py_UNICODE *wtemp; + if (!GetFullPathNameW(PyUnicode_AS_UNICODE(po), + sizeof(woutbuf)/sizeof(woutbuf[0]), + woutbuf, &wtemp)) + return win32_error("GetFullPathName", ""); + return PyUnicode_FromUnicode(woutbuf, wcslen(woutbuf)); + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif if (!PyArg_ParseTuple (args, "et#:_getfullpathname", Py_FileSystemDefaultEncoding, &inbufp, &insize)) *************** *** 1234,1239 **** --- 1522,1548 ---- int res; char *path = NULL; int mode = 0777; + + #ifdef Py_WIN_WIDE_FILENAMES + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "U|i:mkdir", &po)) { + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread lock as + it is a simple dereference. */ + res = _wmkdir(PyUnicode_AS_UNICODE(po)); + Py_END_ALLOW_THREADS + if (res < 0) + return posix_error(); + Py_INCREF(Py_None); + return Py_None; + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, "et|i:mkdir", Py_FileSystemDefaultEncoding, &path, &mode)) return NULL; *************** *** 1302,1308 **** static PyObject * posix_rename(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:rename", rename); } --- 1611,1621 ---- static PyObject * posix_rename(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_2str(args, "etet:rename", rename, "OO:rename", _wrename); ! #else ! return posix_2str(args, "etet:rename", rename, NULL, NULL); ! #endif } *************** *** 1313,1319 **** static PyObject * posix_rmdir(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:rmdir", rmdir); } --- 1626,1636 ---- static PyObject * posix_rmdir(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_1str(args, "et:rmdir", rmdir, "U:rmdir", _wrmdir); ! #else ! return posix_1str(args, "et:rmdir", rmdir, NULL, NULL); ! #endif } *************** *** 1324,1330 **** static PyObject * posix_stat(PyObject *self, PyObject *args) { ! return posix_do_stat(self, args, "et:stat", STAT); } --- 1641,1651 ---- static PyObject * posix_stat(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_do_stat(self, args, "et:stat", STAT, "U:stat", _wstati64); ! #else ! return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL); ! #endif } *************** *** 1376,1382 **** static PyObject * posix_unlink(PyObject *self, PyObject *args) { ! return posix_1str(args, "et:remove", unlink); } --- 1697,1707 ---- static PyObject * posix_unlink(PyObject *self, PyObject *args) { ! #ifdef MS_WINDOWS ! return posix_1str(args, "et:remove", unlink, "U:remove", _wunlink); ! #else ! return posix_1str(args, "et:remove", unlink, NULL, NULL); ! #endif } *************** *** 4150,4158 **** posix_lstat(PyObject *self, PyObject *args) { #ifdef HAVE_LSTAT ! return posix_do_stat(self, args, "et:lstat", lstat); #else /* !HAVE_LSTAT */ ! return posix_do_stat(self, args, "et:lstat", STAT); #endif /* !HAVE_LSTAT */ } --- 4475,4487 ---- posix_lstat(PyObject *self, PyObject *args) { #ifdef HAVE_LSTAT ! return posix_do_stat(self, args, "et:lstat", lstat, NULL, NULL); #else /* !HAVE_LSTAT */ ! #ifdef MS_WINDOWS ! return posix_do_stat(self, args, "et:lstat", STAT, "u:lstat", _wstati64); ! #else ! return posix_do_stat(self, args, "et:lstat", STAT, NULL, NULL); ! #endif #endif /* !HAVE_LSTAT */ } *************** *** 4188,4194 **** static PyObject * posix_symlink(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:symlink", symlink); } #endif /* HAVE_SYMLINK */ --- 4517,4523 ---- static PyObject * posix_symlink(PyObject *self, PyObject *args) { ! return posix_2str(args, "etet:symlink", symlink, NULL, NULL); } #endif /* HAVE_SYMLINK */ *************** *** 4369,4374 **** --- 4698,4723 ---- int flag; int mode = 0777; int fd; + + #ifdef MS_WINDOWS + if (unicode_file_names()) { + PyUnicodeObject *po; + if (PyArg_ParseTuple(args, "Ui|i:mkdir", &po, &flag, &mode)) { + Py_BEGIN_ALLOW_THREADS + /* PyUnicode_AS_UNICODE OK without thread + lock as it is a simple dereference. */ + fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode); + Py_END_ALLOW_THREADS + if (fd < 0) + return posix_error(); + return PyInt_FromLong((long)fd); + } + /* Drop the argument parsing error as narrow strings + are also valid. */ + PyErr_Clear(); + } + #endif + if (!PyArg_ParseTuple(args, "eti|i", Py_FileSystemDefaultEncoding, &file, &flag, &mode)) *************** *** 6341,6346 **** --- 6690,6696 ---- #endif #ifdef HAVE_GETCWD {"getcwd", posix_getcwd, METH_VARARGS, posix_getcwd__doc__}, + {"getcwdu", posix_getcwdu, METH_VARARGS, posix_getcwdu__doc__}, #endif #ifdef HAVE_LINK {"link", posix_link, METH_VARARGS, posix_link__doc__}, Index: Objects/fileobject.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v retrieving revision 2.168 diff -c -r2.168 fileobject.c *** Objects/fileobject.c 14 Aug 2002 21:01:41 -0000 2.168 --- Objects/fileobject.c 30 Sep 2002 12:47:34 -0000 *************** *** 15,20 **** --- 15,26 ---- #include #endif + #ifdef _MSC_VER + /* Need GetVersion to see if on NT so safe to use _wfopen */ + #define WIN32_LEAN_AND_MEAN + #include + #endif /* _MSC_VER */ + #ifdef macintosh #ifdef USE_GUSI #define HAVE_FTRUNCATE *************** *** 102,108 **** static PyObject * fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode, ! int (*close)(FILE *)) { assert(f != NULL); assert(PyFile_Check(f)); --- 108,114 ---- static PyObject * fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode, ! int (*close)(FILE *), PyObject *wname) { assert(f != NULL); assert(PyFile_Check(f)); *************** *** 110,116 **** Py_DECREF(f->f_name); Py_DECREF(f->f_mode); ! f->f_name = PyString_FromString(name); f->f_mode = PyString_FromString(mode); f->f_close = close; --- 116,125 ---- Py_DECREF(f->f_name); Py_DECREF(f->f_mode); ! if (wname) ! f->f_name = PyUnicode_FromObject(wname); ! else ! f->f_name = PyString_FromString(name); f->f_mode = PyString_FromString(mode); f->f_close = close; *************** *** 135,141 **** --- 144,155 ---- { assert(f != NULL); assert(PyFile_Check(f)); + #ifdef MS_WINDOWS + /* windows ignores the passed name in order to support Unicode */ + assert(f->f_name != NULL); + #else assert(name != NULL); + #endif assert(mode != NULL); assert(f->f_fp == NULL); *************** *** 156,162 **** else #endif { - Py_BEGIN_ALLOW_THREADS #ifdef WITH_UNIVERSAL_NEWLINES if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0) mode = "rb"; --- 170,175 ---- *************** *** 168,175 **** if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0) mode = "r"; #endif ! f->f_fp = fopen(name, mode); ! Py_END_ALLOW_THREADS } if (f->f_fp == NULL) { #ifdef NO_FOPEN_ERRNO --- 181,206 ---- if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0) mode = "r"; #endif ! #ifdef MS_WINDOWS ! if (PyUnicode_Check(f->f_name)) { ! PyObject *wmode; ! wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL); ! if (f->f_name && wmode) { ! Py_BEGIN_ALLOW_THREADS ! /* PyUnicode_AS_UNICODE OK without thread ! lock as it is a simple dereference. */ ! f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name), ! PyUnicode_AS_UNICODE(wmode)); ! Py_END_ALLOW_THREADS ! } ! Py_XDECREF(wmode); ! } ! #endif ! if (NULL == f->f_fp && NULL != name) { ! Py_BEGIN_ALLOW_THREADS ! f->f_fp = fopen(name, mode); ! Py_END_ALLOW_THREADS ! } } if (f->f_fp == NULL) { #ifdef NO_FOPEN_ERRNO *************** *** 201,207 **** --- 232,242 ---- PyErr_Format(PyExc_IOError, "invalid mode: %s", mode); else + #ifdef MS_WINDOWS + PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name); + #else PyErr_SetFromErrnoWithFilename(PyExc_IOError, name); + #endif /* MS_WINDOWS */ f = NULL; } if (f != NULL) *************** *** 215,221 **** PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type, NULL, NULL); if (f != NULL) { ! if (fill_file_fields(f, fp, name, mode, close) == NULL) { Py_DECREF(f); f = NULL; } --- 250,256 ---- PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type, NULL, NULL); if (f != NULL) { ! if (fill_file_fields(f, fp, name, mode, close, NULL) == NULL) { Py_DECREF(f); f = NULL; } *************** *** 293,303 **** static PyObject * file_repr(PyFileObject *f) { ! return PyString_FromFormat("<%s file '%s', mode '%s' at %p>", f->f_fp == NULL ? "closed" : "open", PyString_AsString(f->f_name), PyString_AsString(f->f_mode), f); } static PyObject * --- 328,351 ---- static PyObject * file_repr(PyFileObject *f) { ! if (PyUnicode_Check(f->f_name)) { ! PyObject *ret = NULL; ! PyObject *name; ! name = PyUnicode_AsUnicodeEscapeString(f->f_name); ! ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>", ! f->f_fp == NULL ? "closed" : "open", ! PyString_AsString(name), ! PyString_AsString(f->f_mode), ! f); ! Py_XDECREF(name); ! return ret; ! } else { ! return PyString_FromFormat("<%s file '%s', mode '%s' at %p>", f->f_fp == NULL ? "closed" : "open", PyString_AsString(f->f_name), PyString_AsString(f->f_mode), f); + } } static PyObject * *************** *** 1766,1771 **** --- 1814,1820 ---- char *name = NULL; char *mode = "r"; int bufsize = -1; + int wideargument = 0; assert(PyFile_Check(self)); if (foself->f_fp != NULL) { *************** *** 1776,1787 **** Py_DECREF(closeresult); } ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist, ! Py_FileSystemDefaultEncoding, &name, ! &mode, &bufsize)) ! return -1; ! if (fill_file_fields(foself, NULL, name, mode, fclose) == NULL) ! goto Error; if (open_the_file(foself, name, mode) == NULL) goto Error; PyFile_SetBufSize(self, bufsize); --- 1825,1857 ---- Py_DECREF(closeresult); } ! #ifdef Py_WIN_WIDE_FILENAMES ! if (GetVersion() < 0x80000000) { /* On NT, so wide API available */ ! PyObject *po; ! if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file", ! kwlist, &po, &mode, &bufsize)) { ! wideargument = 1; ! if (fill_file_fields(foself, NULL, name, mode, ! fclose, po) == NULL) ! goto Error; ! } else { ! /* Drop the argument parsing error as narrow ! strings are also valid. */ ! PyErr_Clear(); ! } ! } ! #endif ! ! if (!wideargument) { ! if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist, ! Py_FileSystemDefaultEncoding, ! &name, ! &mode, &bufsize)) ! return -1; ! if (fill_file_fields(foself, NULL, name, mode, ! fclose, NULL) == NULL) ! goto Error; ! } if (open_the_file(foself, name, mode) == NULL) goto Error; PyFile_SetBufSize(self, bufsize); Index: PC/pyconfig.h =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/pyconfig.h,v retrieving revision 1.14 diff -c -r1.14 pyconfig.h *** PC/pyconfig.h 19 Jul 2002 06:55:41 -0000 1.14 --- PC/pyconfig.h 30 Sep 2002 12:47:34 -0000 *************** *** 400,405 **** --- 400,409 ---- Include/unicodeobject.h). */ #if Py_UNICODE_SIZE == 2 #define HAVE_USABLE_WCHAR_T + + /* Define to indicate that the Python Unicode representation can be passed + as-is to Win32 Wide API. */ + #define Py_WIN_WIDE_FILENAMES #endif /* Use Python's own small-block memory-allocator. */ Index: Python/errors.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v retrieving revision 2.71 diff -c -r2.71 errors.c *** Python/errors.c 29 Jul 2002 14:27:41 -0000 2.71 --- Python/errors.c 30 Sep 2002 12:47:35 -0000 *************** *** 259,265 **** } PyObject * ! PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) { PyObject *v; char *s; --- 259,265 ---- } PyObject * ! PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) { PyObject *v; char *s; *************** *** 314,321 **** } #endif /* Unix/Windows */ #endif /* PLAN 9*/ ! if (filename != NULL) ! v = Py_BuildValue("(iss)", i, s, filename); else v = Py_BuildValue("(is)", i, s); if (v != NULL) { --- 314,321 ---- } #endif /* Unix/Windows */ #endif /* PLAN 9*/ ! if (filenameObject != NULL) ! v = Py_BuildValue("(isO)", i, s, filenameObject); else v = Py_BuildValue("(is)", i, s); if (v != NULL) { *************** *** 330,346 **** PyObject * PyErr_SetFromErrno(PyObject *exc) { ! return PyErr_SetFromErrnoWithFilename(exc, NULL); } #ifdef MS_WINDOWS /* Windows specific error code handling */ ! PyObject *PyErr_SetExcFromWindowsErrWithFilename( PyObject *exc, int ierr, ! const char *filename) { int len; char *s; --- 330,368 ---- PyObject * + PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) + { + PyObject *name = filename ? PyString_FromString(filename) : NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + Py_DECREF(name); + return result; + } + + #ifdef Py_WIN_WIDE_FILENAMES + PyObject * + PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, Py_UNICODE *filename) + { + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + Py_XDECREF(name); + return result; + } + #endif /* Py_WIN_WIDE_FILENAMES */ + + PyObject * PyErr_SetFromErrno(PyObject *exc) { ! return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); } #ifdef MS_WINDOWS /* Windows specific error code handling */ ! PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( PyObject *exc, int ierr, ! PyObject *filenameObject) { int len; char *s; *************** *** 362,369 **** /* remove trailing cr/lf and dots */ while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) s[--len] = '\0'; ! if (filename != NULL) ! v = Py_BuildValue("(iss)", err, s, filename); else v = Py_BuildValue("(is)", err, s); if (v != NULL) { --- 384,391 ---- /* remove trailing cr/lf and dots */ while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.')) s[--len] = '\0'; ! if (filenameObject != NULL) ! v = Py_BuildValue("(isO)", err, s, filenameObject); else v = Py_BuildValue("(is)", err, s); if (v != NULL) { *************** *** 374,379 **** --- 396,431 ---- return NULL; } + PyObject *PyErr_SetExcFromWindowsErrWithFilename( + PyObject *exc, + int ierr, + const char *filename) + { + PyObject *name = filename ? PyString_FromString(filename) : NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, + name); + Py_XDECREF(name); + return ret; + } + + #ifdef Py_WIN_WIDE_FILENAMES + PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename( + PyObject *exc, + int ierr, + const Py_UNICODE *filename) + { + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, + name); + Py_XDECREF(name); + return ret; + } + #endif /* Py_WIN_WIDE_FILENAMES */ + PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) { return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); *************** *** 388,396 **** int ierr, const char *filename) { ! return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError, ! ierr, filename); } #endif /* MS_WINDOWS */ void --- 440,468 ---- int ierr, const char *filename) { ! PyObject *name = filename ? PyString_FromString(filename) : NULL; ! PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( ! PyExc_WindowsError, ! ierr, name); ! Py_XDECREF(result); ! return result; ! } ! ! #ifdef Py_WIN_WIDE_FILENAMES ! PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename( ! int ierr, ! const Py_UNICODE *filename) ! { ! PyObject *name = filename ? ! PyUnicode_FromUnicode(filename, wcslen(filename)) : ! NULL; ! PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( ! PyExc_WindowsError, ! ierr, name); ! Py_XDECREF(result); ! return result; } + #endif /* Py_WIN_WIDE_FILENAMES */ #endif /* MS_WINDOWS */ void