annotate Python/fileutils.c @ 65162:39014f0abc32

Create fileutils.c/.h * _Py_fopen() and _Py_stat() come from Python/import.c * (_Py)_wrealpath() comes from Python/sysmodule.c * _Py_char2wchar(), _Py_wchar2char() and _Py_wfopen() come from Modules/main.c * (_Py)_wstat(), (_Py)_wgetcwd(), _Py_wreadlink() come from Modules/getpath.c
author Victor Stinner <victor.stinner@haypocalc.com>
date Thu, 07 Oct 2010 21:45:39 +0000
parents
children 7879a8ec7f79
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
65162
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
1 #include "Python.h"
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
2
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
3 #ifdef HAVE_STAT
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
4
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
5 /* Decode a byte string from the locale encoding with the
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
6 surrogateescape error handler (undecodable bytes are decoded as characters
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
7 in range U+DC80..U+DCFF). If a byte sequence can be decoded as a surrogate
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
8 character, escape the bytes using the surrogateescape error handler instead
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
9 of decoding them.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
10
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
11 Use _Py_wchar2char() to encode the character string back to a byte string.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
12
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
13 Return a pointer to a newly allocated (wide) character string (use
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
14 PyMem_Free() to free the memory), or NULL on error (conversion error or
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
15 memory error). */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
16 wchar_t*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
17 _Py_char2wchar(char* arg)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
18 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
19 wchar_t *res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
20 #ifdef HAVE_BROKEN_MBSTOWCS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
21 /* Some platforms have a broken implementation of
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
22 * mbstowcs which does not count the characters that
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
23 * would result from conversion. Use an upper bound.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
24 */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
25 size_t argsize = strlen(arg);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
26 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
27 size_t argsize = mbstowcs(NULL, arg, 0);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
28 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
29 size_t count;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
30 unsigned char *in;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
31 wchar_t *out;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
32 #ifdef HAVE_MBRTOWC
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
33 mbstate_t mbs;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
34 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
35 if (argsize != (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
36 res = (wchar_t *)PyMem_Malloc((argsize+1)*sizeof(wchar_t));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
37 if (!res)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
38 goto oom;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
39 count = mbstowcs(res, arg, argsize+1);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
40 if (count != (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
41 wchar_t *tmp;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
42 /* Only use the result if it contains no
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
43 surrogate characters. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
44 for (tmp = res; *tmp != 0 &&
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
45 (*tmp < 0xd800 || *tmp > 0xdfff); tmp++)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
46 ;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
47 if (*tmp == 0)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
48 return res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
49 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
50 PyMem_Free(res);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
51 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
52 /* Conversion failed. Fall back to escaping with surrogateescape. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
53 #ifdef HAVE_MBRTOWC
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
54 /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
55
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
56 /* Overallocate; as multi-byte characters are in the argument, the
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
57 actual output could use less memory. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
58 argsize = strlen(arg) + 1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
59 res = (wchar_t*)PyMem_Malloc(argsize*sizeof(wchar_t));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
60 if (!res) goto oom;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
61 in = (unsigned char*)arg;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
62 out = res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
63 memset(&mbs, 0, sizeof mbs);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
64 while (argsize) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
65 size_t converted = mbrtowc(out, (char*)in, argsize, &mbs);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
66 if (converted == 0)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
67 /* Reached end of string; null char stored. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
68 break;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
69 if (converted == (size_t)-2) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
70 /* Incomplete character. This should never happen,
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
71 since we provide everything that we have -
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
72 unless there is a bug in the C library, or I
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
73 misunderstood how mbrtowc works. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
74 fprintf(stderr, "unexpected mbrtowc result -2\n");
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
75 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
76 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
77 if (converted == (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
78 /* Conversion error. Escape as UTF-8b, and start over
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
79 in the initial shift state. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
80 *out++ = 0xdc00 + *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
81 argsize--;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
82 memset(&mbs, 0, sizeof mbs);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
83 continue;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
84 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
85 if (*out >= 0xd800 && *out <= 0xdfff) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
86 /* Surrogate character. Escape the original
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
87 byte sequence with surrogateescape. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
88 argsize -= converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
89 while (converted--)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
90 *out++ = 0xdc00 + *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
91 continue;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
92 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
93 /* successfully converted some bytes */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
94 in += converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
95 argsize -= converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
96 out++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
97 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
98 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
99 /* Cannot use C locale for escaping; manually escape as if charset
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
100 is ASCII (i.e. escape all bytes > 128. This will still roundtrip
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
101 correctly in the locale's charset, which must be an ASCII superset. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
102 res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
103 if (!res) goto oom;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
104 in = (unsigned char*)arg;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
105 out = res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
106 while(*in)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
107 if(*in < 128)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
108 *out++ = *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
109 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
110 *out++ = 0xdc00 + *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
111 *out = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
112 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
113 return res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
114 oom:
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
115 fprintf(stderr, "out of memory\n");
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
116 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
117 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
118
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
119 /* Encode a (wide) character string to the locale encoding with the
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
120 surrogateescape error handler (characters in range U+DC80..U+DCFF are
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
121 converted to bytes 0x80..0xFF).
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
122
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
123 This function is the reverse of _Py_char2wchar().
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
124
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
125 Return a pointer to a newly allocated byte string (use PyMem_Free() to free
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
126 the memory), or NULL on error (conversion error or memory error). */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
127 char*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
128 _Py_wchar2char(const wchar_t *text)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
129 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
130 const size_t len = wcslen(text);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
131 char *result = NULL, *bytes = NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
132 size_t i, size, converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
133 wchar_t c, buf[2];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
134
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
135 /* The function works in two steps:
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
136 1. compute the length of the output buffer in bytes (size)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
137 2. outputs the bytes */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
138 size = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
139 buf[1] = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
140 while (1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
141 for (i=0; i < len; i++) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
142 c = text[i];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
143 if (c >= 0xdc80 && c <= 0xdcff) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
144 /* UTF-8b surrogate */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
145 if (bytes != NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
146 *bytes++ = c - 0xdc00;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
147 size--;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
148 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
149 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
150 size++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
151 continue;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
152 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
153 else {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
154 buf[0] = c;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
155 if (bytes != NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
156 converted = wcstombs(bytes, buf, size);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
157 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
158 converted = wcstombs(NULL, buf, 0);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
159 if (converted == (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
160 if (result != NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
161 PyMem_Free(result);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
162 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
163 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
164 if (bytes != NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
165 bytes += converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
166 size -= converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
167 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
168 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
169 size += converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
170 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
171 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
172 if (result != NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
173 *bytes = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
174 break;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
175 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
176
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
177 size += 1; /* nul byte at the end */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
178 result = PyMem_Malloc(size);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
179 if (result == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
180 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
181 bytes = result;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
182 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
183 return result;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
184 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
185
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
186 #if defined(MS_WINDOWS) || defined(HAVE_STAT)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
187 int
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
188 _Py_wstat(const wchar_t* path, struct stat *buf)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
189 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
190 /* In principle, this should use HAVE__WSTAT, and _wstat
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
191 should be detected by autoconf. However, no current
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
192 POSIX system provides that function, so testing for
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
193 it is pointless.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
194 Not sure whether the MS_WINDOWS guards are necessary:
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
195 perhaps for cygwin/mingw builds?
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
196 */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
197 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
198 return _wstat(path, buf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
199 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
200 int err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
201 char *fname;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
202 fname = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
203 if (fname == NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
204 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
205 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
206 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
207 err = stat(fname, buf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
208 PyMem_Free(fname);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
209 return err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
210 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
211 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
212 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
213
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
214 /* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
215 attribute on Windows. Return 0 on success, -1 on stat error or (if
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
216 PyErr_Occurred()) unicode error. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
217
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
218 int
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
219 _Py_stat(PyObject *unicode, struct stat *statbuf)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
220 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
221 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
222 wchar_t *path;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
223 int err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
224 struct _stat wstatbuf;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
225
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
226 path = PyUnicode_AsWideCharString(unicode, NULL);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
227 if (path == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
228 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
229 err = _wstat(path, &wstatbuf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
230 PyMem_Free(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
231 if (!err)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
232 statbuf->st_mode = wstatbuf.st_mode;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
233 return err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
234 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
235 int ret;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
236 PyObject *bytes = PyUnicode_EncodeFSDefault(unicode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
237 if (bytes == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
238 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
239 ret = stat(PyBytes_AS_STRING(bytes), statbuf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
240 Py_DECREF(bytes);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
241 return ret;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
242 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
243 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
244
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
245 FILE *
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
246 _Py_wfopen(const wchar_t *path, const wchar_t *mode)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
247 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
248 #ifndef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
249 FILE *f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
250 char *cpath;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
251 char cmode[10];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
252 size_t r;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
253 r = wcstombs(cmode, mode, 10);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
254 if (r == (size_t)-1 || r >= 10) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
255 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
256 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
257 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
258 cpath = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
259 if (cpath == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
260 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
261 f = fopen(cpath, cmode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
262 PyMem_Free(cpath);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
263 return f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
264 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
265 return _wfopen(path, mode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
266 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
267 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
268
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
269 /* Call _wfopen() on Windows, or fopen() otherwise. Return the new file
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
270 object on success, or NULL if the file cannot be open or (if
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
271 PyErr_Occurred()) on unicode error */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
272
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
273 FILE*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
274 _Py_fopen(PyObject *unicode, const char *mode)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
275 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
276 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
277 wchar_t *path;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
278 wchar_t wmode[10];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
279 int usize;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
280 FILE *f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
281
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
282 usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
283 if (usize == 0)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
284 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
285
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
286 path = PyUnicode_AsWideCharString(unicode, NULL);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
287 if (path == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
288 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
289 f = _wfopen(path, wmode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
290 PyMem_Free(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
291 return f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
292 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
293 FILE *f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
294 PyObject *bytes = PyUnicode_EncodeFSDefault(unicode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
295 if (bytes == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
296 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
297 f = fopen(PyBytes_AS_STRING(bytes), mode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
298 Py_DECREF(bytes);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
299 return f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
300 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
301 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
302
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
303 #ifdef HAVE_READLINK
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
304 int
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
305 _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
306 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
307 char *cpath;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
308 char cbuf[PATH_MAX];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
309 int res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
310 size_t r1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
311
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
312 cpath = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
313 if (cpath == NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
314 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
315 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
316 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
317 res = (int)readlink(cpath, cbuf, PATH_MAX);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
318 PyMem_Free(cpath);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
319 if (res == -1)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
320 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
321 if (res == PATH_MAX) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
322 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
323 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
324 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
325 cbuf[res] = '\0'; /* buf will be null terminated */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
326 r1 = mbstowcs(buf, cbuf, bufsiz);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
327 if (r1 == -1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
328 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
329 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
330 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
331 return (int)r1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
332 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
333 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
334
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
335 #ifdef HAVE_REALPATH
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
336 wchar_t*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
337 _Py_wrealpath(const wchar_t *path, wchar_t *resolved_path)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
338 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
339 char *cpath;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
340 char cresolved_path[PATH_MAX];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
341 char *res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
342 size_t r;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
343 cpath = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
344 if (cpath == NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
345 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
346 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
347 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
348 res = realpath(cpath, cresolved_path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
349 PyMem_Free(cpath);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
350 if (res == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
351 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
352 r = mbstowcs(resolved_path, cresolved_path, PATH_MAX);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
353 if (r == (size_t)-1 || r >= PATH_MAX) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
354 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
355 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
356 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
357 return resolved_path;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
358 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
359 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
360
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
361 wchar_t*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
362 _Py_wgetcwd(wchar_t *buf, size_t size)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
363 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
364 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
365 return _wgetcwd(buf, size);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
366 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
367 char fname[PATH_MAX];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
368 if (getcwd(fname, PATH_MAX) == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
369 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
370 if (mbstowcs(buf, fname, size) >= size) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
371 errno = ERANGE;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
372 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
373 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
374 return buf;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
375 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
376 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
377
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
378 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
379
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
380 #include "Python.h"
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
381
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
382 #ifdef HAVE_STAT
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
383
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
384 /* Decode a byte string from the locale encoding with the
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
385 surrogateescape error handler (undecodable bytes are decoded as characters
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
386 in range U+DC80..U+DCFF). If a byte sequence can be decoded as a surrogate
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
387 character, escape the bytes using the surrogateescape error handler instead
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
388 of decoding them.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
389
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
390 Use _Py_wchar2char() to encode the character string back to a byte string.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
391
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
392 Return a pointer to a newly allocated (wide) character string (use
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
393 PyMem_Free() to free the memory), or NULL on error (conversion error or
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
394 memory error). */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
395 wchar_t*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
396 _Py_char2wchar(char* arg)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
397 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
398 wchar_t *res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
399 #ifdef HAVE_BROKEN_MBSTOWCS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
400 /* Some platforms have a broken implementation of
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
401 * mbstowcs which does not count the characters that
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
402 * would result from conversion. Use an upper bound.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
403 */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
404 size_t argsize = strlen(arg);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
405 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
406 size_t argsize = mbstowcs(NULL, arg, 0);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
407 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
408 size_t count;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
409 unsigned char *in;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
410 wchar_t *out;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
411 #ifdef HAVE_MBRTOWC
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
412 mbstate_t mbs;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
413 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
414 if (argsize != (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
415 res = (wchar_t *)PyMem_Malloc((argsize+1)*sizeof(wchar_t));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
416 if (!res)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
417 goto oom;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
418 count = mbstowcs(res, arg, argsize+1);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
419 if (count != (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
420 wchar_t *tmp;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
421 /* Only use the result if it contains no
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
422 surrogate characters. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
423 for (tmp = res; *tmp != 0 &&
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
424 (*tmp < 0xd800 || *tmp > 0xdfff); tmp++)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
425 ;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
426 if (*tmp == 0)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
427 return res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
428 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
429 PyMem_Free(res);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
430 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
431 /* Conversion failed. Fall back to escaping with surrogateescape. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
432 #ifdef HAVE_MBRTOWC
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
433 /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
434
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
435 /* Overallocate; as multi-byte characters are in the argument, the
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
436 actual output could use less memory. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
437 argsize = strlen(arg) + 1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
438 res = (wchar_t*)PyMem_Malloc(argsize*sizeof(wchar_t));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
439 if (!res) goto oom;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
440 in = (unsigned char*)arg;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
441 out = res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
442 memset(&mbs, 0, sizeof mbs);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
443 while (argsize) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
444 size_t converted = mbrtowc(out, (char*)in, argsize, &mbs);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
445 if (converted == 0)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
446 /* Reached end of string; null char stored. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
447 break;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
448 if (converted == (size_t)-2) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
449 /* Incomplete character. This should never happen,
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
450 since we provide everything that we have -
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
451 unless there is a bug in the C library, or I
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
452 misunderstood how mbrtowc works. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
453 fprintf(stderr, "unexpected mbrtowc result -2\n");
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
454 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
455 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
456 if (converted == (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
457 /* Conversion error. Escape as UTF-8b, and start over
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
458 in the initial shift state. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
459 *out++ = 0xdc00 + *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
460 argsize--;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
461 memset(&mbs, 0, sizeof mbs);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
462 continue;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
463 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
464 if (*out >= 0xd800 && *out <= 0xdfff) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
465 /* Surrogate character. Escape the original
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
466 byte sequence with surrogateescape. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
467 argsize -= converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
468 while (converted--)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
469 *out++ = 0xdc00 + *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
470 continue;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
471 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
472 /* successfully converted some bytes */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
473 in += converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
474 argsize -= converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
475 out++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
476 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
477 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
478 /* Cannot use C locale for escaping; manually escape as if charset
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
479 is ASCII (i.e. escape all bytes > 128. This will still roundtrip
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
480 correctly in the locale's charset, which must be an ASCII superset. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
481 res = PyMem_Malloc((strlen(arg)+1)*sizeof(wchar_t));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
482 if (!res) goto oom;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
483 in = (unsigned char*)arg;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
484 out = res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
485 while(*in)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
486 if(*in < 128)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
487 *out++ = *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
488 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
489 *out++ = 0xdc00 + *in++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
490 *out = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
491 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
492 return res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
493 oom:
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
494 fprintf(stderr, "out of memory\n");
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
495 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
496 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
497
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
498 /* Encode a (wide) character string to the locale encoding with the
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
499 surrogateescape error handler (characters in range U+DC80..U+DCFF are
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
500 converted to bytes 0x80..0xFF).
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
501
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
502 This function is the reverse of _Py_char2wchar().
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
503
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
504 Return a pointer to a newly allocated byte string (use PyMem_Free() to free
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
505 the memory), or NULL on error (conversion error or memory error). */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
506 char*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
507 _Py_wchar2char(const wchar_t *text)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
508 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
509 const size_t len = wcslen(text);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
510 char *result = NULL, *bytes = NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
511 size_t i, size, converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
512 wchar_t c, buf[2];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
513
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
514 /* The function works in two steps:
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
515 1. compute the length of the output buffer in bytes (size)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
516 2. outputs the bytes */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
517 size = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
518 buf[1] = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
519 while (1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
520 for (i=0; i < len; i++) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
521 c = text[i];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
522 if (c >= 0xdc80 && c <= 0xdcff) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
523 /* UTF-8b surrogate */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
524 if (bytes != NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
525 *bytes++ = c - 0xdc00;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
526 size--;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
527 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
528 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
529 size++;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
530 continue;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
531 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
532 else {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
533 buf[0] = c;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
534 if (bytes != NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
535 converted = wcstombs(bytes, buf, size);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
536 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
537 converted = wcstombs(NULL, buf, 0);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
538 if (converted == (size_t)-1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
539 if (result != NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
540 PyMem_Free(result);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
541 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
542 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
543 if (bytes != NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
544 bytes += converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
545 size -= converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
546 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
547 else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
548 size += converted;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
549 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
550 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
551 if (result != NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
552 *bytes = 0;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
553 break;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
554 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
555
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
556 size += 1; /* nul byte at the end */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
557 result = PyMem_Malloc(size);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
558 if (result == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
559 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
560 bytes = result;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
561 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
562 return result;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
563 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
564
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
565 #if defined(MS_WINDOWS) || defined(HAVE_STAT)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
566 int
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
567 _Py_wstat(const wchar_t* path, struct stat *buf)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
568 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
569 /* In principle, this should use HAVE__WSTAT, and _wstat
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
570 should be detected by autoconf. However, no current
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
571 POSIX system provides that function, so testing for
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
572 it is pointless.
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
573 Not sure whether the MS_WINDOWS guards are necessary:
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
574 perhaps for cygwin/mingw builds?
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
575 */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
576 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
577 return _wstat(path, buf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
578 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
579 int err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
580 char *fname;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
581 fname = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
582 if (fname == NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
583 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
584 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
585 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
586 err = stat(fname, buf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
587 PyMem_Free(fname);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
588 return err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
589 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
590 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
591 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
592
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
593 /* Call _wstat() on Windows, or stat() otherwise. Only fill st_mode
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
594 attribute on Windows. Return 0 on success, -1 on stat error or (if
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
595 PyErr_Occurred()) unicode error. */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
596
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
597 int
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
598 _Py_stat(PyObject *unicode, struct stat *statbuf)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
599 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
600 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
601 wchar_t *path;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
602 int err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
603 struct _stat wstatbuf;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
604
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
605 path = PyUnicode_AsWideCharString(unicode, NULL);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
606 if (path == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
607 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
608 err = _wstat(path, &wstatbuf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
609 PyMem_Free(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
610 if (!err)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
611 statbuf->st_mode = wstatbuf.st_mode;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
612 return err;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
613 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
614 int ret;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
615 PyObject *bytes = PyUnicode_EncodeFSDefault(unicode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
616 if (bytes == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
617 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
618 ret = stat(PyBytes_AS_STRING(bytes), statbuf);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
619 Py_DECREF(bytes);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
620 return ret;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
621 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
622 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
623
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
624 FILE *
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
625 _Py_wfopen(const wchar_t *path, const wchar_t *mode)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
626 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
627 #ifndef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
628 FILE *f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
629 char *cpath;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
630 char cmode[10];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
631 size_t r;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
632 r = wcstombs(cmode, mode, 10);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
633 if (r == (size_t)-1 || r >= 10) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
634 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
635 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
636 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
637 cpath = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
638 if (cpath == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
639 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
640 f = fopen(cpath, cmode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
641 PyMem_Free(cpath);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
642 return f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
643 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
644 return _wfopen(path, mode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
645 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
646 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
647
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
648 /* Call _wfopen() on Windows, or fopen() otherwise. Return the new file
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
649 object on success, or NULL if the file cannot be open or (if
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
650 PyErr_Occurred()) on unicode error */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
651
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
652 FILE*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
653 _Py_fopen(PyObject *unicode, const char *mode)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
654 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
655 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
656 wchar_t *path;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
657 wchar_t wmode[10];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
658 int usize;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
659 FILE *f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
660
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
661 usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode));
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
662 if (usize == 0)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
663 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
664
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
665 path = PyUnicode_AsWideCharString(unicode, NULL);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
666 if (path == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
667 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
668 f = _wfopen(path, wmode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
669 PyMem_Free(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
670 return f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
671 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
672 FILE *f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
673 PyObject *bytes = PyUnicode_EncodeFSDefault(unicode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
674 if (bytes == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
675 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
676 f = fopen(PyBytes_AS_STRING(bytes), mode);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
677 Py_DECREF(bytes);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
678 return f;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
679 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
680 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
681
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
682 #ifdef HAVE_READLINK
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
683 int
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
684 _Py_wreadlink(const wchar_t *path, wchar_t *buf, size_t bufsiz)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
685 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
686 char *cpath;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
687 char cbuf[PATH_MAX];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
688 int res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
689 size_t r1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
690
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
691 cpath = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
692 if (cpath == NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
693 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
694 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
695 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
696 res = (int)readlink(cpath, cbuf, PATH_MAX);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
697 PyMem_Free(cpath);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
698 if (res == -1)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
699 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
700 if (res == PATH_MAX) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
701 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
702 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
703 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
704 cbuf[res] = '\0'; /* buf will be null terminated */
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
705 r1 = mbstowcs(buf, cbuf, bufsiz);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
706 if (r1 == -1) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
707 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
708 return -1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
709 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
710 return (int)r1;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
711 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
712 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
713
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
714 #ifdef HAVE_REALPATH
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
715 wchar_t*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
716 _Py_wrealpath(const wchar_t *path, wchar_t *resolved_path)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
717 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
718 char *cpath;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
719 char cresolved_path[PATH_MAX];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
720 char *res;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
721 size_t r;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
722 cpath = _Py_wchar2char(path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
723 if (cpath == NULL) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
724 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
725 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
726 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
727 res = realpath(cpath, cresolved_path);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
728 PyMem_Free(cpath);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
729 if (res == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
730 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
731 r = mbstowcs(resolved_path, cresolved_path, PATH_MAX);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
732 if (r == (size_t)-1 || r >= PATH_MAX) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
733 errno = EINVAL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
734 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
735 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
736 return resolved_path;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
737 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
738 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
739
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
740 wchar_t*
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
741 _Py_wgetcwd(wchar_t *buf, size_t size)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
742 {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
743 #ifdef MS_WINDOWS
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
744 return _wgetcwd(buf, size);
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
745 #else
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
746 char fname[PATH_MAX];
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
747 if (getcwd(fname, PATH_MAX) == NULL)
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
748 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
749 if (mbstowcs(buf, fname, size) >= size) {
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
750 errno = ERANGE;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
751 return NULL;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
752 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
753 return buf;
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
754 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
755 }
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
756
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
757 #endif
39014f0abc32 Create fileutils.c/.h
Victor Stinner <victor.stinner@haypocalc.com>
parents:
diff changeset
758