summaryrefslogtreecommitdiffstats
path: root/Objects/fileobject.c
diff options
context:
space:
mode:
authorMark Hammond <mhammond@skippinet.com.au>2002-10-03 05:10:39 (GMT)
committerMark Hammond <mhammond@skippinet.com.au>2002-10-03 05:10:39 (GMT)
commitc2e85bd4e20dc3b5bc446a705a46397c799f56c0 (patch)
tree8db1cdb9fedfe47739b9ace6da4df65389da3567 /Objects/fileobject.c
parenteb287a26621001fb5d945b7b6246ccac77378cc7 (diff)
downloadcpython-c2e85bd4e20dc3b5bc446a705a46397c799f56c0.zip
cpython-c2e85bd4e20dc3b5bc446a705a46397c799f56c0.tar.gz
cpython-c2e85bd4e20dc3b5bc446a705a46397c799f56c0.tar.bz2
Patch 594001: PEP 277 - Unicode file name support for Windows NT.
Diffstat (limited to 'Objects/fileobject.c')
-rw-r--r--Objects/fileobject.c96
1 files changed, 83 insertions, 13 deletions
diff --git a/Objects/fileobject.c b/Objects/fileobject.c
index 8dc21b7..ebf0d40 100644
--- a/Objects/fileobject.c
+++ b/Objects/fileobject.c
@@ -15,6 +15,12 @@
#include <windows.h>
#endif
+#ifdef _MSC_VER
+/* Need GetVersion to see if on NT so safe to use _wfopen */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif /* _MSC_VER */
+
#ifdef macintosh
#ifdef USE_GUSI
#define HAVE_FTRUNCATE
@@ -102,7 +108,7 @@ dircheck(PyFileObject* f)
static PyObject *
fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
- int (*close)(FILE *))
+ int (*close)(FILE *), PyObject *wname)
{
assert(f != NULL);
assert(PyFile_Check(f));
@@ -110,7 +116,10 @@ fill_file_fields(PyFileObject *f, FILE *fp, char *name, char *mode,
Py_DECREF(f->f_name);
Py_DECREF(f->f_mode);
- f->f_name = PyString_FromString(name);
+ 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,7 +144,12 @@ open_the_file(PyFileObject *f, char *name, char *mode)
{
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,7 +170,6 @@ open_the_file(PyFileObject *f, char *name, char *mode)
else
#endif
{
- Py_BEGIN_ALLOW_THREADS
#ifdef WITH_UNIVERSAL_NEWLINES
if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
mode = "rb";
@@ -168,8 +181,26 @@ open_the_file(PyFileObject *f, char *name, char *mode)
if (strcmp(mode, "U") == 0 || strcmp(mode, "rU") == 0)
mode = "r";
#endif
- f->f_fp = fopen(name, mode);
- Py_END_ALLOW_THREADS
+#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,7 +232,11 @@ open_the_file(PyFileObject *f, char *name, char *mode)
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,7 +250,7 @@ PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type,
NULL, NULL);
if (f != NULL) {
- if (fill_file_fields(f, fp, name, mode, close) == NULL) {
+ if (fill_file_fields(f, fp, name, mode, close, NULL) == NULL) {
Py_DECREF(f);
f = NULL;
}
@@ -293,11 +328,24 @@ file_dealloc(PyFileObject *f)
static PyObject *
file_repr(PyFileObject *f)
{
- return PyString_FromFormat("<%s file '%s', mode '%s' at %p>",
+ 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,6 +1814,7 @@ file_init(PyObject *self, PyObject *args, PyObject *kwds)
char *name = NULL;
char *mode = "r";
int bufsize = -1;
+ int wideargument = 0;
assert(PyFile_Check(self));
if (foself->f_fp != NULL) {
@@ -1776,12 +1825,33 @@ file_init(PyObject *self, PyObject *args, PyObject *kwds)
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;
+#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);