Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3)

Delta Between Two Patch Sets: Modules/posixmodule.c

Issue 3871: cross and native build of python for mingw32 with distutils
Left Patch Set: Created 9 years, 5 months ago
Right Patch Set: Created 7 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Modules/_multiprocessing/multiprocessing.c ('k') | Modules/python.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 1
2 /* POSIX module implementation */ 2 /* POSIX module implementation */
3 3
4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the 4 /* This file is also used for Windows NT/MS-Win and OS/2. In that case the
5 module actually calls itself 'nt' or 'os2', not 'posix', and a few 5 module actually calls itself 'nt' or 'os2', not 'posix', and a few
6 functions are either unimplemented or implemented differently. The source 6 functions are either unimplemented or implemented differently. The source
7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
8 of the compiler used. Different compilers define their own feature 8 of the compiler used. Different compilers define their own feature
9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler 9 test macro, e.g. '__BORLANDC__' or '_MSC_VER'. For OS/2, the compiler
10 independent macro PYOS_OS2 should be defined. On OS/2 the default 10 independent macro PYOS_OS2 should be defined. On OS/2 the default
11 compiler is assumed to be IBM's VisualAge C++ (VACPP). PYCC_GCC is used 11 compiler is assumed to be IBM's VisualAge C++ (VACPP). PYCC_GCC is used
12 as the compiler specific macro for the EMX port of gcc to OS/2. */ 12 as the compiler specific macro for the EMX port of gcc to OS/2. */
13 13
14 /* See also ../Dos/dosmodule.c */
15
16 #ifdef __APPLE__ 14 #ifdef __APPLE__
17 /* 15 /*
18 * Step 1 of support for weak-linking a number of symbols existing on 16 * Step 1 of support for weak-linking a number of symbols existing on
19 * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block 17 * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
20 * at the end of this file for more information. 18 * at the end of this file for more information.
21 */ 19 */
22 # pragma weak lchown 20 # pragma weak lchown
23 # pragma weak statvfs 21 # pragma weak statvfs
24 # pragma weak fstatvfs 22 # pragma weak fstatvfs
25 23
26 #endif /* __APPLE__ */ 24 #endif /* __APPLE__ */
27 25
28 #define PY_SSIZE_T_CLEAN 26 #define PY_SSIZE_T_CLEAN
29 27
30 #include "Python.h" 28 #include "Python.h"
31 #include "structseq.h"
32 29
33 #if defined(__VMS) 30 #if defined(__VMS)
31 # error "PEP 11: VMS is now unsupported, code will be removed in Python 3.4"
34 # include <unixio.h> 32 # include <unixio.h>
35 #endif /* defined(__VMS) */ 33 #endif /* defined(__VMS) */
36 34
37 #ifdef __cplusplus 35 #ifdef __cplusplus
38 extern "C" { 36 extern "C" {
39 #endif 37 #endif
40 38
41 PyDoc_STRVAR(posix__doc__, 39 PyDoc_STRVAR(posix__doc__,
42 "This module provides access to operating system functionality that is\n\ 40 "This module provides access to operating system functionality that is\n\
43 standardized by the C Standard and the POSIX standard (a thinly\n\ 41 standardized by the C Standard and the POSIX standard (a thinly\n\
44 disguised Unix interface). Refer to the library manual and\n\ 42 disguised Unix interface). Refer to the library manual and\n\
45 corresponding Unix manual entries for more information on calls."); 43 corresponding Unix manual entries for more information on calls.");
46 44
47 45
48 #if defined(PYOS_OS2) 46 #if defined(PYOS_OS2)
47 #error "PEP 11: OS/2 is now unsupported, code will be removed in Python 3.4"
49 #define INCL_DOS 48 #define INCL_DOS
50 #define INCL_DOSERRORS 49 #define INCL_DOSERRORS
51 #define INCL_DOSPROCESS 50 #define INCL_DOSPROCESS
52 #define INCL_NOPMAPI 51 #define INCL_NOPMAPI
53 #include <os2.h> 52 #include <os2.h>
54 #if defined(PYCC_GCC) 53 #if defined(PYCC_GCC)
55 #include <ctype.h> 54 #include <ctype.h>
56 #include <io.h> 55 #include <io.h>
57 #include <stdio.h> 56 #include <stdio.h>
58 #include <process.h> 57 #include <process.h>
59 #endif 58 #endif
60 #include "osdefs.h" 59 #include "osdefs.h"
61 #endif 60 #endif
62 61
62 #ifdef HAVE_SYS_UIO_H
63 #include <sys/uio.h>
64 #endif
65
63 #ifdef HAVE_SYS_TYPES_H 66 #ifdef HAVE_SYS_TYPES_H
64 #include <sys/types.h> 67 #include <sys/types.h>
65 #endif /* HAVE_SYS_TYPES_H */ 68 #endif /* HAVE_SYS_TYPES_H */
66 69
67 #ifdef HAVE_SYS_STAT_H 70 #ifdef HAVE_SYS_STAT_H
68 #include <sys/stat.h> 71 #include <sys/stat.h>
69 #endif /* HAVE_SYS_STAT_H */ 72 #endif /* HAVE_SYS_STAT_H */
70 73
71 #ifdef HAVE_SYS_WAIT_H 74 #ifdef HAVE_SYS_WAIT_H
72 #include <sys/wait.h> /* For WNOHANG */ 75 #include <sys/wait.h> /* For WNOHANG */
(...skipping 15 matching lines...) Expand all
88 #include <sysexits.h> 91 #include <sysexits.h>
89 #endif /* HAVE_SYSEXITS_H */ 92 #endif /* HAVE_SYSEXITS_H */
90 93
91 #ifdef HAVE_SYS_LOADAVG_H 94 #ifdef HAVE_SYS_LOADAVG_H
92 #include <sys/loadavg.h> 95 #include <sys/loadavg.h>
93 #endif 96 #endif
94 97
95 #ifdef HAVE_LANGINFO_H 98 #ifdef HAVE_LANGINFO_H
96 #include <langinfo.h> 99 #include <langinfo.h>
97 #endif 100 #endif
101
102 #ifdef HAVE_SYS_SENDFILE_H
103 #include <sys/sendfile.h>
104 #endif
105
106 #ifdef HAVE_SCHED_H
107 #include <sched.h>
108 #endif
109
110 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
111 #undef HAVE_SCHED_SETAFFINITY
112 #endif
113
114 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__)
115 #define USE_XATTRS
116 #endif
117
118 #ifdef USE_XATTRS
119 #include <sys/xattr.h>
120 #endif
121
122 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
123 #ifdef HAVE_SYS_SOCKET_H
124 #include <sys/socket.h>
125 #endif
126 #endif
127
128 #ifdef HAVE_DLFCN_H
129 #include <dlfcn.h>
130 #endif
131
132 #if defined(MS_WINDOWS)
133 # define TERMSIZE_USE_CONIO
134 #elif defined(HAVE_SYS_IOCTL_H)
135 # include <sys/ioctl.h>
136 # if defined(HAVE_TERMIOS_H)
137 # include <termios.h>
138 # endif
139 # if defined(TIOCGWINSZ)
140 # define TERMSIZE_USE_IOCTL
141 # endif
142 #endif /* MS_WINDOWS */
98 143
99 /* Various compilers have only certain posix functions */ 144 /* Various compilers have only certain posix functions */
100 /* XXX Gosh I wish these were all moved into pyconfig.h */ 145 /* XXX Gosh I wish these were all moved into pyconfig.h */
101 #if defined(PYCC_VACPP) && defined(PYOS_OS2) 146 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
102 #include <process.h> 147 #include <process.h>
103 #else 148 #else
104 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ 149 #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
105 #define HAVE_GETCWD 1 150 #define HAVE_GETCWD 1
106 #define HAVE_OPENDIR 1 151 #define HAVE_OPENDIR 1
107 #define HAVE_SYSTEM 1 152 #define HAVE_SYSTEM 1
108 #if defined(__OS2__) 153 #if defined(__OS2__)
109 #define HAVE_EXECV 1 154 #define HAVE_EXECV 1
110 #define HAVE_WAIT 1 155 #define HAVE_WAIT 1
111 #endif 156 #endif
112 #include <process.h> 157 #include <process.h>
113 #else 158 #else
114 #ifdef __BORLANDC__ /* Borland compiler */ 159 #ifdef __BORLANDC__ /* Borland compiler */
115 #define HAVE_EXECV 1 160 #define HAVE_EXECV 1
116 #define HAVE_GETCWD 1 161 #define HAVE_GETCWD 1
117 #define HAVE_OPENDIR 1 162 #define HAVE_OPENDIR 1
118 #define HAVE_PIPE 1 163 #define HAVE_PIPE 1
119 #define HAVE_SYSTEM 1 164 #define HAVE_SYSTEM 1
120 #define HAVE_WAIT 1 165 #define HAVE_WAIT 1
121 #else 166 #else
122 #if defined(_MSC_VER) || defined(__MINGW32__) /* Microsoft/MinGW compile r */ 167 #ifdef _MSC_VER /* Microsoft compiler */
123 #define HAVE_GETCWD 1 168 #define HAVE_GETCWD 1
169 #define HAVE_GETPPID 1
170 #define HAVE_GETLOGIN 1
124 #define HAVE_SPAWNV 1 171 #define HAVE_SPAWNV 1
125 #define HAVE_EXECV 1 172 #define HAVE_EXECV 1
126 #define HAVE_PIPE 1 173 #define HAVE_PIPE 1
127 #define HAVE_SYSTEM 1 174 #define HAVE_SYSTEM 1
128 #define HAVE_CWAIT 1 175 #define HAVE_CWAIT 1
129 #define HAVE_FSYNC 1 176 #define HAVE_FSYNC 1
130 #define fsync _commit 177 #define fsync _commit
178 #elif defined(__MINGW32__) /* GCC (mingw special) compiler */
179 /*#define HAVE_GETCWD 1 - detected by configure*/
180 #define HAVE_SPAWNV 1
181 #define HAVE_EXECV 1
182 #define HAVE_PIPE 1
183 #define HAVE_POPEN 1
184 #define HAVE_SYSTEM 1
185 #define HAVE_CWAIT 1
186 #define HAVE_FSYNC 1
187 #undef HAVE_FTRUNCATE /* mingw implement it as _chsize. undef to be compatible */
188 #undef HAVE_TRUNCATE /* mingw-w64 implement it. undef to be compatible */
189 #define fsync _commit
190 #include <windows.h>
191 #include <winioctl.h>
192 #ifndef _MAX_ENV
193 #define _MAX_ENV 32767
194 #endif
131 #else 195 #else
132 #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS) || defined(MS_WINDO WS) 196 #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
133 /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */ 197 /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
134 #else /* all other compilers */ 198 #else /* all other compilers */
135 /* Unix functions that the configure script doesn't check for */ 199 /* Unix functions that the configure script doesn't check for */
136 #define HAVE_EXECV 1 200 #define HAVE_EXECV 1
137 #define HAVE_FORK 1 201 #define HAVE_FORK 1
138 #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ 202 #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
139 #define HAVE_FORK1 1 203 #define HAVE_FORK1 1
140 #endif 204 #endif
141 #define HAVE_GETCWD 1 205 #define HAVE_GETCWD 1
142 #define HAVE_GETEGID 1 206 #define HAVE_GETEGID 1
143 #define HAVE_GETEUID 1 207 #define HAVE_GETEUID 1
144 #define HAVE_GETGID 1 208 #define HAVE_GETGID 1
145 #define HAVE_GETPPID 1 209 #define HAVE_GETPPID 1
146 #define HAVE_GETUID 1 210 #define HAVE_GETUID 1
147 #define HAVE_KILL 1 211 #define HAVE_KILL 1
148 #define HAVE_OPENDIR 1 212 #define HAVE_OPENDIR 1
149 #define HAVE_PIPE 1 213 #define HAVE_PIPE 1
150 #define HAVE_SYSTEM 1 214 #define HAVE_SYSTEM 1
151 #define HAVE_WAIT 1 215 #define HAVE_WAIT 1
152 #define HAVE_TTYNAME 1 216 #define HAVE_TTYNAME 1
153 #endif /* PYOS_OS2 && PYCC_GCC && __VMS */ 217 #endif /* PYOS_OS2 && PYCC_GCC && __VMS */
154 #endif /* _MSC_VER || __MINGW32__ */ 218 #endif /* _MSC_VER */
155 #endif /* __BORLANDC__ */ 219 #endif /* __BORLANDC__ */
156 #endif /* ! __WATCOMC__ || __QNX__ */ 220 #endif /* ! __WATCOMC__ || __QNX__ */
157 #endif /* ! __IBMC__ */ 221 #endif /* ! __IBMC__ */
222
223
224
158 225
159 #ifndef _MSC_VER 226 #ifndef _MSC_VER
160 227
161 #if defined(__sgi)&&_COMPILER_VERSION>=700 228 #if defined(__sgi)&&_COMPILER_VERSION>=700
162 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode 229 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
163 (default) */ 230 (default) */
164 extern char *ctermid_r(char *); 231 extern char *ctermid_r(char *);
165 #endif 232 #endif
166 233
167 #ifndef HAVE_UNISTD_H 234 #ifndef HAVE_UNISTD_H
168 #if defined(PYCC_VACPP) 235 #if defined(PYCC_VACPP)
169 extern int mkdir(char *); 236 extern int mkdir(char *);
170 #else 237 #else
171 #if ( defined(__WATCOMC__) || defined(_MSC_VER) || defined(__MINGW32__)) && !def ined(__QNX__) 238 #if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
172 extern int mkdir(const char *); 239 extern int mkdir(const char *);
173 #else 240 #else
174 extern int mkdir(const char *, mode_t); 241 extern int mkdir(const char *, mode_t);
175 #endif 242 #endif
176 #endif 243 #endif
177 #if defined(__IBMC__) || defined(__IBMCPP__) 244 #if defined(__IBMC__) || defined(__IBMCPP__)
178 extern int chdir(char *); 245 extern int chdir(char *);
179 extern int rmdir(char *); 246 extern int rmdir(char *);
180 #else 247 #else
181 extern int chdir(const char *); 248 extern int chdir(const char *);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 #include <sys/ndir.h> 312 #include <sys/ndir.h>
246 #endif 313 #endif
247 #ifdef HAVE_SYS_DIR_H 314 #ifdef HAVE_SYS_DIR_H
248 #include <sys/dir.h> 315 #include <sys/dir.h>
249 #endif 316 #endif
250 #ifdef HAVE_NDIR_H 317 #ifdef HAVE_NDIR_H
251 #include <ndir.h> 318 #include <ndir.h>
252 #endif 319 #endif
253 #endif 320 #endif
254 321
255 #ifdef MS_WINDOWS 322 #if defined(_MSC_VER) || defined(__MINGW32__)
256 #ifdef HAVE_DIRECT_H 323 #ifdef HAVE_DIRECT_H
257 #include <direct.h> 324 #include <direct.h>
258 #endif 325 #endif
259 #ifdef HAVE_IO_H 326 #ifdef HAVE_IO_H
260 #include <io.h> 327 #include <io.h>
261 #endif 328 #endif
262 #ifdef HAVE_PROCESS_H 329 #ifdef HAVE_PROCESS_H
263 #include <process.h> 330 #include <process.h>
264 #endif 331 #endif
265 #ifndef VOLUME_NAME_DOS 332 #ifndef VOLUME_NAME_DOS
266 #define VOLUME_NAME_DOS»0x0 333 #define VOLUME_NAME_DOS 0x0
267 #endif 334 #endif
268 #ifndef VOLUME_NAME_NT 335 #ifndef VOLUME_NAME_NT
269 #define VOLUME_NAME_NT» 0x2 336 #define VOLUME_NAME_NT 0x2
270 #endif 337 #endif
271 #ifndef IO_REPARSE_TAG_SYMLINK 338 #ifndef IO_REPARSE_TAG_SYMLINK
272 #define IO_REPARSE_TAG_SYMLINK» (0xA000000CL) 339 #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
273 #endif 340 #endif
274 #include "osdefs.h" 341 #include "osdefs.h"
275 #include <malloc.h> 342 #include <malloc.h>
276 #include <windows.h> 343 #include <windows.h>
277 #include <shellapi.h> /* for ShellExecute() */ 344 #include <shellapi.h> /* for ShellExecute() */
278 #ifdef __MINGW32__ 345 #include <lmcons.h> /* for UNLEN */
279 #include <winioctl.h> /* for FSCTL_GET_REPARSE_POINT */ 346 #ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */
280 #include <winldap.h> /* for HCRYPTPROV */ 347 #define HAVE_SYMLINK
281 #endif 348 static int win32_can_symlink = 0;
282 #endif /* MS_WINDOWS */ 349 #endif
350 #endif /* _MSC_VER */
283 351
284 #if defined(PYCC_VACPP) && defined(PYOS_OS2) 352 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
285 #include <io.h> 353 #include <io.h>
286 #endif /* OS2 */ 354 #endif /* OS2 */
287 355
288 #ifndef MAXPATHLEN 356 #ifndef MAXPATHLEN
289 #if defined(PATH_MAX) && PATH_MAX > 1024 357 #if defined(PATH_MAX) && PATH_MAX > 1024
290 #define MAXPATHLEN PATH_MAX 358 #define MAXPATHLEN PATH_MAX
291 #else 359 #else
292 #define MAXPATHLEN 1024 360 #define MAXPATHLEN 1024
(...skipping 24 matching lines...) Expand all
317 #endif /* UNION_WAIT */ 385 #endif /* UNION_WAIT */
318 386
319 /* Don't use the "_r" form if we don't need it (also, won't have a 387 /* Don't use the "_r" form if we don't need it (also, won't have a
320 prototype for it, at least on Solaris -- maybe others as well?). */ 388 prototype for it, at least on Solaris -- maybe others as well?). */
321 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD) 389 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
322 #define USE_CTERMID_R 390 #define USE_CTERMID_R
323 #endif 391 #endif
324 392
325 /* choose the appropriate stat and fstat functions and return structs */ 393 /* choose the appropriate stat and fstat functions and return structs */
326 #undef STAT 394 #undef STAT
395 #undef FSTAT
396 #undef STRUCT_STAT
327 #if defined(MS_WIN64) || defined(MS_WINDOWS) 397 #if defined(MS_WIN64) || defined(MS_WINDOWS)
328 # define STAT win32_stat 398 # define STAT win32_stat
399 # define LSTAT win32_lstat
329 # define FSTAT win32_fstat 400 # define FSTAT win32_fstat
330 # define STRUCT_STAT struct win32_stat 401 # define STRUCT_STAT struct win32_stat
331 #else 402 #else
332 # define STAT stat 403 # define STAT stat
404 # define LSTAT lstat
333 # define FSTAT fstat 405 # define FSTAT fstat
334 # define STRUCT_STAT struct stat 406 # define STRUCT_STAT struct stat
335 #endif 407 #endif
336 408
337 #if defined(MAJOR_IN_MKDEV) 409 #if defined(MAJOR_IN_MKDEV)
338 #include <sys/mkdev.h> 410 #include <sys/mkdev.h>
339 #else 411 #else
340 #if defined(MAJOR_IN_SYSMACROS) 412 #if defined(MAJOR_IN_SYSMACROS)
341 #include <sys/sysmacros.h> 413 #include <sys/sysmacros.h>
342 #endif 414 #endif
343 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) 415 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
344 #include <sys/mkdev.h> 416 #include <sys/mkdev.h>
345 #endif 417 #endif
346 #endif 418 #endif
347 419
420
421 #ifdef MS_WINDOWS
422 static int
423 win32_warn_bytes_api()
424 {
425 return PyErr_WarnEx(PyExc_DeprecationWarning,
426 "The Windows bytes API has been deprecated, "
427 "use Unicode filenames instead",
428 1);
429 }
430 #endif
431
432
433 #ifdef AT_FDCWD
434 /*
435 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
436 * without the int cast, the value gets interpreted as uint (4291925331),
437 * which doesn't play nicely with all the initializer lines in this file that
438 * look like this:
439 * int dir_fd = DEFAULT_DIR_FD;
440 */
441 #define DEFAULT_DIR_FD (int)AT_FDCWD
442 #else
443 #define DEFAULT_DIR_FD (-100)
444 #endif
445
446 static int
447 _fd_converter(PyObject *o, int *p, int default_value) {
448 long long_value;
449 if (o == Py_None) {
450 *p = default_value;
451 return 1;
452 }
453 if (PyFloat_Check(o)) {
454 PyErr_SetString(PyExc_TypeError,
455 "integer argument expected, got float" );
456 return 0;
457 }
458 long_value = PyLong_AsLong(o);
459 if (long_value == -1 && PyErr_Occurred())
460 return 0;
461 if (long_value > INT_MAX) {
462 PyErr_SetString(PyExc_OverflowError,
463 "signed integer is greater than maximum");
464 return 0;
465 }
466 if (long_value < INT_MIN) {
467 PyErr_SetString(PyExc_OverflowError,
468 "signed integer is less than minimum");
469 return 0;
470 }
471 *p = (int)long_value;
472 return 1;
473 }
474
475 static int
476 dir_fd_converter(PyObject *o, void *p) {
477 return _fd_converter(o, (int *)p, DEFAULT_DIR_FD);
478 }
479
480
481
482 /*
483 * A PyArg_ParseTuple "converter" function
484 * that handles filesystem paths in the manner
485 * preferred by the os module.
486 *
487 * path_converter accepts (Unicode) strings and their
488 * subclasses, and bytes and their subclasses. What
489 * it does with the argument depends on the platform:
490 *
491 * * On Windows, if we get a (Unicode) string we
492 * extract the wchar_t * and return it; if we get
493 * bytes we extract the char * and return that.
494 *
495 * * On all other platforms, strings are encoded
496 * to bytes using PyUnicode_FSConverter, then we
497 * extract the char * from the bytes object and
498 * return that.
499 *
500 * path_converter also optionally accepts signed
501 * integers (representing open file descriptors) instead
502 * of path strings.
503 *
504 * Input fields:
505 * path.nullable
506 * If nonzero, the path is permitted to be None.
507 * path.allow_fd
508 * If nonzero, the path is permitted to be a file handle
509 * (a signed int) instead of a string.
510 * path.function_name
511 * If non-NULL, path_converter will use that as the name
512 * of the function in error messages.
513 * (If path.argument_name is NULL it omits the function name.)
514 * path.argument_name
515 * If non-NULL, path_converter will use that as the name
516 * of the parameter in error messages.
517 * (If path.argument_name is NULL it uses "path".)
518 *
519 * Output fields:
520 * path.wide
521 * Points to the path if it was expressed as Unicode
522 * and was not encoded. (Only used on Windows.)
523 * path.narrow
524 * Points to the path if it was expressed as bytes,
525 * or it was Unicode and was encoded to bytes.
526 * path.fd
527 * Contains a file descriptor if path.accept_fd was true
528 * and the caller provided a signed integer instead of any
529 * sort of string.
530 *
531 * WARNING: if your "path" parameter is optional, and is
532 * unspecified, path_converter will never get called.
533 * So if you set allow_fd, you *MUST* initialize path.fd = -1
534 * yourself!
535 * path.length
536 * The length of the path in characters, if specified as
537 * a string.
538 * path.object
539 * The original object passed in.
540 * path.cleanup
541 * For internal use only. May point to a temporary object.
542 * (Pay no attention to the man behind the curtain.)
543 *
544 * At most one of path.wide or path.narrow will be non-NULL.
545 * If path was None and path.nullable was set,
546 * or if path was an integer and path.allow_fd was set,
547 * both path.wide and path.narrow will be NULL
548 * and path.length will be 0.
549 *
550 * path_converter takes care to not write to the path_t
551 * unless it's successful. However it must reset the
552 * "cleanup" field each time it's called.
553 *
554 * Use as follows:
555 * path_t path;
556 * memset(&path, 0, sizeof(path));
557 * PyArg_ParseTuple(args, "O&", path_converter, &path);
558 * // ... use values from path ...
559 * path_cleanup(&path);
560 *
561 * (Note that if PyArg_Parse fails you don't need to call
562 * path_cleanup(). However it is safe to do so.)
563 */
564 typedef struct {
565 char *function_name;
566 char *argument_name;
567 int nullable;
568 int allow_fd;
569 wchar_t *wide;
570 char *narrow;
571 int fd;
572 Py_ssize_t length;
573 PyObject *object;
574 PyObject *cleanup;
575 } path_t;
576
577 static void
578 path_cleanup(path_t *path) {
579 if (path->cleanup) {
580 Py_DECREF(path->cleanup);
581 path->cleanup = NULL;
582 }
583 }
584
585 static int
586 path_converter(PyObject *o, void *p) {
587 path_t *path = (path_t *)p;
588 PyObject *unicode, *bytes;
589 Py_ssize_t length;
590 char *narrow;
591
592 #define FORMAT_EXCEPTION(exc, fmt) \
593 PyErr_Format(exc, "%s%s" fmt, \
594 path->function_name ? path->function_name : "", \
595 path->function_name ? ": " : "", \
596 path->argument_name ? path->argument_name : "path")
597
598 /* Py_CLEANUP_SUPPORTED support */
599 if (o == NULL) {
600 path_cleanup(path);
601 return 1;
602 }
603
604 /* ensure it's always safe to call path_cleanup() */
605 path->cleanup = NULL;
606
607 if (o == Py_None) {
608 if (!path->nullable) {
609 FORMAT_EXCEPTION(PyExc_TypeError,
610 "can't specify None for %s argument");
611 return 0;
612 }
613 path->wide = NULL;
614 path->narrow = NULL;
615 path->length = 0;
616 path->object = o;
617 path->fd = -1;
618 return 1;
619 }
620
621 unicode = PyUnicode_FromObject(o);
622 if (unicode) {
623 #ifdef MS_WINDOWS
624 wchar_t *wide;
625 length = PyUnicode_GET_SIZE(unicode);
626 if (length > 32767) {
627 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
628 Py_DECREF(unicode);
629 return 0;
630 }
631
632 wide = PyUnicode_AsUnicode(unicode);
633 if (!wide) {
634 Py_DECREF(unicode);
635 return 0;
636 }
637
638 path->wide = wide;
639 path->narrow = NULL;
640 path->length = length;
641 path->object = o;
642 path->fd = -1;
643 path->cleanup = unicode;
644 return Py_CLEANUP_SUPPORTED;
645 #else
646 int converted = PyUnicode_FSConverter(unicode, &bytes);
647 Py_DECREF(unicode);
648 if (!converted)
649 bytes = NULL;
650 #endif
651 }
652 else {
653 PyErr_Clear();
654 bytes = PyBytes_FromObject(o);
655 if (!bytes) {
656 PyErr_Clear();
657 if (path->allow_fd) {
658 int fd;
659 /*
660 * note: _fd_converter always permits None.
661 * but we've already done our None check.
662 * so o cannot be None at this point.
663 */
664 int result = _fd_converter(o, &fd, -1);
665 if (result) {
666 path->wide = NULL;
667 path->narrow = NULL;
668 path->length = 0;
669 path->object = o;
670 path->fd = fd;
671 return result;
672 }
673 }
674 }
675 }
676
677 if (!bytes) {
678 if (!PyErr_Occurred())
679 FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter");
680 return 0;
681 }
682
683 #ifdef MS_WINDOWS
684 if (win32_warn_bytes_api()) {
685 Py_DECREF(bytes);
686 return 0;
687 }
688 #endif
689
690 length = PyBytes_GET_SIZE(bytes);
691 #ifdef MS_WINDOWS
692 if (length > MAX_PATH) {
693 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
694 Py_DECREF(bytes);
695 return 0;
696 }
697 #endif
698
699 narrow = PyBytes_AS_STRING(bytes);
700 if (length != strlen(narrow)) {
701 FORMAT_EXCEPTION(PyExc_ValueError, "embedded NUL character in %s");
702 Py_DECREF(bytes);
703 return 0;
704 }
705
706 path->wide = NULL;
707 path->narrow = narrow;
708 path->length = length;
709 path->object = o;
710 path->fd = -1;
711 path->cleanup = bytes;
712 return Py_CLEANUP_SUPPORTED;
713 }
714
715 static void
716 argument_unavailable_error(char *function_name, char *argument_name) {
717 PyErr_Format(PyExc_NotImplementedError,
718 "%s%s%s unavailable on this platform",
719 (function_name != NULL) ? function_name : "",
720 (function_name != NULL) ? ": ": "",
721 argument_name);
722 }
723
724 static int
725 dir_fd_unavailable(PyObject *o, void *p) {
726 int *dir_fd = (int *)p;
727 int return_value = _fd_converter(o, dir_fd, DEFAULT_DIR_FD);
728 if (!return_value)
729 return 0;
730 if (*dir_fd == DEFAULT_DIR_FD)
731 return 1;
732 argument_unavailable_error(NULL, "dir_fd");
733 return 0;
734 }
735
736 static int
737 fd_specified(char *function_name, int fd) {
738 if (fd == -1)
739 return 0;
740
741 argument_unavailable_error(function_name, "fd");
742 return 1;
743 }
744
745 static int
746 follow_symlinks_specified(char *function_name, int follow_symlinks) {
747 if (follow_symlinks)
748 return 0;
749
750 argument_unavailable_error(function_name, "follow_symlinks");
751 return 1;
752 }
753
754 static int
755 path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) {
756 if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) {
757 PyErr_Format(PyExc_ValueError,
758 "%s: can't specify dir_fd without matching path",
759 function_name);
760 return 1;
761 }
762 return 0;
763 }
764
765 static int
766 dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) {
767 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
768 PyErr_Format(PyExc_ValueError,
769 "%s: can't specify both dir_fd and fd",
770 function_name);
771 return 1;
772 }
773 return 0;
774 }
775
776 static int
777 fd_and_follow_symlinks_invalid(char *function_name, int fd,
778 int follow_symlinks) {
779 if ((fd > 0) && (!follow_symlinks)) {
780 PyErr_Format(PyExc_ValueError,
781 "%s: cannot use fd and follow_symlinks together",
782 function_name);
783 return 1;
784 }
785 return 0;
786 }
787
788 static int
789 dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd,
790 int follow_symlinks) {
791 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
792 PyErr_Format(PyExc_ValueError,
793 "%s: cannot use dir_fd and follow_symlinks together",
794 function_name);
795 return 1;
796 }
797 return 0;
798 }
799
800 /* A helper used by a number of POSIX-only functions */
801 #ifndef MS_WINDOWS
802 static int
803 _parse_off_t(PyObject* arg, void* addr)
804 {
805 #if !defined(HAVE_LARGEFILE_SUPPORT)
806 *((off_t*)addr) = PyLong_AsLong(arg);
807 #else
808 *((off_t*)addr) = PyLong_AsLongLong(arg);
809 #endif
810 if (PyErr_Occurred())
811 return 0;
812 return 1;
813 }
814 #endif
815
348 #if defined _MSC_VER && _MSC_VER >= 1400 816 #if defined _MSC_VER && _MSC_VER >= 1400
349 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is 817 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
350 * valid and throw an assertion if it isn't. 818 * valid and raise an assertion if it isn't.
351 * Normally, an invalid fd is likely to be a C program error and therefore 819 * Normally, an invalid fd is likely to be a C program error and therefore
352 * an assertion can be useful, but it does contradict the POSIX standard 820 * an assertion can be useful, but it does contradict the POSIX standard
353 * which for write(2) states: 821 * which for write(2) states:
354 * "Otherwise, -1 shall be returned and errno set to indicate the error." 822 * "Otherwise, -1 shall be returned and errno set to indicate the error."
355 * "[EBADF] The fildes argument is not a valid file descriptor open for 823 * "[EBADF] The fildes argument is not a valid file descriptor open for
356 * writing." 824 * writing."
357 * Furthermore, python allows the user to enter any old integer 825 * Furthermore, python allows the user to enter any old integer
358 * as a fd and should merely raise a python exception on error. 826 * as a fd and should merely raise a python exception on error.
359 * The Microsoft CRT doesn't provide an official way to check for the 827 * The Microsoft CRT doesn't provide an official way to check for the
360 * validity of a file descriptor, but we can emulate its internal behaviour 828 * validity of a file descriptor, but we can emulate its internal behaviour
(...skipping 21 matching lines...) Expand all
382 #define FOPEN 0x01 850 #define FOPEN 0x01
383 #define _NO_CONSOLE_FILENO (intptr_t)-2 851 #define _NO_CONSOLE_FILENO (intptr_t)-2
384 852
385 /* This function emulates what the windows CRT does to validate file handles */ 853 /* This function emulates what the windows CRT does to validate file handles */
386 int 854 int
387 _PyVerify_fd(int fd) 855 _PyVerify_fd(int fd)
388 { 856 {
389 const int i1 = fd >> IOINFO_L2E; 857 const int i1 = fd >> IOINFO_L2E;
390 const int i2 = fd & ((1 << IOINFO_L2E) - 1); 858 const int i2 = fd & ((1 << IOINFO_L2E) - 1);
391 859
392 static int sizeof_ioinfo = 0; 860 static size_t sizeof_ioinfo = 0;
393 861
394 /* Determine the actual size of the ioinfo structure, 862 /* Determine the actual size of the ioinfo structure,
395 * as used by the CRT loaded in memory 863 * as used by the CRT loaded in memory
396 */ 864 */
397 if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) { 865 if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
398 sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS; 866 sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
399 } 867 }
400 if (sizeof_ioinfo == 0) { 868 if (sizeof_ioinfo == 0) {
401 /* This should not happen... */ 869 /* This should not happen... */
402 goto fail; 870 goto fail;
(...skipping 28 matching lines...) Expand all
431 if ((unsigned)fd2 < _NHANDLE_) 899 if ((unsigned)fd2 < _NHANDLE_)
432 return 1; 900 return 1;
433 else 901 else
434 return 0; 902 return 0;
435 } 903 }
436 #else 904 #else
437 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */ 905 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
438 #define _PyVerify_fd_dup2(A, B) (1) 906 #define _PyVerify_fd_dup2(A, B) (1)
439 #endif 907 #endif
440 908
909 #ifdef MS_WINDOWS
910 /* The following structure was copied from
911 http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
912 include doesn't seem to be present in the Windows SDK (at least as included
913 with Visual Studio Express). */
914 #ifndef HAVE_REPARSE_DATA_BUFFER
915 /*
916 * REPARSE_DATA_BUFFER is defined in <winnt.h> on mingw.org w32api
917 * instead as is documented in <ntifs.h>. The mingw-w64 API define
918 * it in <ddk/ntifs.h> but we can not include as header like
919 * <ntddk.h> is required instead <ddk/ntddk.h>, i.e. to use mingw-w64
920 * headers user must specify explicitly path to ddk :(.
921 * So lest check at configure time and use MSC hack if not found.
922 */
923 typedef struct _REPARSE_DATA_BUFFER {
924 ULONG ReparseTag;
925 USHORT ReparseDataLength;
926 USHORT Reserved;
927 union {
928 struct {
929 USHORT SubstituteNameOffset;
930 USHORT SubstituteNameLength;
931 USHORT PrintNameOffset;
932 USHORT PrintNameLength;
933 ULONG Flags;
934 WCHAR PathBuffer[1];
935 } SymbolicLinkReparseBuffer;
936
937 struct {
938 USHORT SubstituteNameOffset;
939 USHORT SubstituteNameLength;
940 USHORT PrintNameOffset;
941 USHORT PrintNameLength;
942 WCHAR PathBuffer[1];
943 } MountPointReparseBuffer;
944
945 struct {
946 UCHAR DataBuffer[1];
947 } GenericReparseBuffer;
948 };
949 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
950
951 #define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER,\
952 GenericReparseBuffer)
953 #ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE
954 #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
955 #endif
956 #endif /*ndef HAVE_REPARSE_DATA_BUFFER*/
957
958 static int
959 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
960 {
961 char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
962 REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
963 DWORD n_bytes_returned;
964
965 if (0 == DeviceIoControl(
966 reparse_point_handle,
967 FSCTL_GET_REPARSE_POINT,
968 NULL, 0, /* in buffer */
969 target_buffer, sizeof(target_buffer),
970 &n_bytes_returned,
971 NULL)) /* we're not using OVERLAPPED_IO */
972 return FALSE;
973
974 if (reparse_tag)
975 *reparse_tag = rdb->ReparseTag;
976
977 return TRUE;
978 }
979
980 #endif /* MS_WINDOWS */
981
441 /* Return a dictionary corresponding to the POSIX environment table */ 982 /* Return a dictionary corresponding to the POSIX environment table */
442 #ifdef WITH_NEXT_FRAMEWORK 983 #ifdef WITH_NEXT_FRAMEWORK
443 /* On Darwin/MacOSX a shared library or framework has no access to 984 /* On Darwin/MacOSX a shared library or framework has no access to
444 ** environ directly, we must obtain it with _NSGetEnviron(). 985 ** environ directly, we must obtain it with _NSGetEnviron().
445 */ 986 */
446 #include <crt_externs.h> 987 #include <crt_externs.h>
447 static char **environ; 988 static char **environ;
448 #elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) ) 989 #elif !defined(_MSC_VER) && !defined(__MINGW32__) && ( !defined(__WATCOMC__) || defined(__QNX__) )
449 extern char **environ; 990 extern char **environ;
450 #endif /* !_MSC_VER */ 991 #endif /* !_MSC_VER */
451 992
452 static PyObject * 993 static PyObject *
453 convertenviron(void) 994 convertenviron(void)
454 { 995 {
455 PyObject *d; 996 PyObject *d;
456 #ifdef MS_WINDOWS 997 #ifdef MS_WINDOWS
457 wchar_t **e; 998 wchar_t **e;
458 #else 999 #else
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 posix_error(void) 1094 posix_error(void)
554 { 1095 {
555 return PyErr_SetFromErrno(PyExc_OSError); 1096 return PyErr_SetFromErrno(PyExc_OSError);
556 } 1097 }
557 static PyObject * 1098 static PyObject *
558 posix_error_with_filename(char* name) 1099 posix_error_with_filename(char* name)
559 { 1100 {
560 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); 1101 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
561 } 1102 }
562 1103
563 #ifdef MS_WINDOWS
564 static PyObject *
565 posix_error_with_unicode_filename(Py_UNICODE* name)
566 {
567 return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);
568 }
569 #endif /* MS_WINDOWS */
570
571 1104
572 static PyObject * 1105 static PyObject *
573 posix_error_with_allocated_filename(PyObject* name) 1106 posix_error_with_allocated_filename(PyObject* name)
574 { 1107 {
575 PyObject *name_str, *rc; 1108 PyObject *name_str, *rc;
576 name_str = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AsString(name), 1109 name_str = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AsString(name),
577 PyBytes_GET_SIZE(name)); 1110 PyBytes_GET_SIZE(name));
578 Py_DECREF(name); 1111 Py_DECREF(name);
579 rc = PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, 1112 rc = PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
580 name_str); 1113 name_str);
(...skipping 11 matching lines...) Expand all
592 Windows error object, which is non-trivial. 1125 Windows error object, which is non-trivial.
593 */ 1126 */
594 errno = GetLastError(); 1127 errno = GetLastError();
595 if (filename) 1128 if (filename)
596 return PyErr_SetFromWindowsErrWithFilename(errno, filename); 1129 return PyErr_SetFromWindowsErrWithFilename(errno, filename);
597 else 1130 else
598 return PyErr_SetFromWindowsErr(errno); 1131 return PyErr_SetFromWindowsErr(errno);
599 } 1132 }
600 1133
601 static PyObject * 1134 static PyObject *
602 win32_error_unicode(char* function, Py_UNICODE* filename) 1135 win32_error_unicode(char* function, wchar_t* filename)
603 { 1136 {
604 /* XXX - see win32_error for comments on 'function' */ 1137 /* XXX - see win32_error for comments on 'function' */
605 errno = GetLastError(); 1138 errno = GetLastError();
606 if (filename) 1139 if (filename)
607 return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename); 1140 return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
608 else 1141 else
609 return PyErr_SetFromWindowsErr(errno); 1142 return PyErr_SetFromWindowsErr(errno);
610 } 1143 }
611 1144
612 static int 1145 static PyObject *
613 convert_to_unicode(PyObject **param) 1146 win32_error_object(char* function, PyObject* filename)
614 { 1147 {
615 if (PyUnicode_CheckExact(*param)) 1148 /* XXX - see win32_error for comments on 'function' */
616 Py_INCREF(*param); 1149 errno = GetLastError();
617 else if (PyUnicode_Check(*param)) 1150 if (filename)
618 /* For a Unicode subtype that's not a Unicode object, 1151 return PyErr_SetExcFromWindowsErrWithFilenameObject(
619 return a true Unicode object with the same data. */ 1152 PyExc_WindowsError,
620 *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*param), 1153 errno,
621 PyUnicode_GET_SIZE(*param)); 1154 filename);
622 else 1155 else
623 *param = PyUnicode_FromEncodedObject(*param, 1156 return PyErr_SetFromWindowsErr(errno);
624 Py_FileSystemDefaultEncoding,
625 "strict");
626 return (*param) != NULL;
627 } 1157 }
628 1158
629 #endif /* MS_WINDOWS */ 1159 #endif /* MS_WINDOWS */
1160
1161 /*
1162 * Some functions return Win32 errors, others only ever use posix_error
1163 * (this is for backwards compatibility with exceptions)
1164 */
1165 static PyObject *
1166 path_posix_error(char *function_name, path_t *path)
1167 {
1168 if (path->narrow)
1169 return posix_error_with_filename(path->narrow);
1170 return posix_error();
1171 }
1172
1173 static PyObject *
1174 path_error(char *function_name, path_t *path)
1175 {
1176 #ifdef MS_WINDOWS
1177 if (path->narrow)
1178 return win32_error(function_name, path->narrow);
1179 if (path->wide)
1180 return win32_error_unicode(function_name, path->wide);
1181 return win32_error(function_name, NULL);
1182 #else
1183 return path_posix_error(function_name, path);
1184 #endif
1185 }
630 1186
631 #if defined(PYOS_OS2) 1187 #if defined(PYOS_OS2)
632 /********************************************************************** 1188 /**********************************************************************
633 * Helper Function to Trim and Format OS/2 Messages 1189 * Helper Function to Trim and Format OS/2 Messages
634 **********************************************************************/ 1190 **********************************************************************/
635 static void 1191 static void
636 os2_formatmsg(char *msgbuf, int msglen, char *reason) 1192 os2_formatmsg(char *msgbuf, int msglen, char *reason)
637 { 1193 {
638 msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */ 1194 msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
639 1195
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 Py_BEGIN_ALLOW_THREADS 1295 Py_BEGIN_ALLOW_THREADS
740 res = (*func)(path1); 1296 res = (*func)(path1);
741 Py_END_ALLOW_THREADS 1297 Py_END_ALLOW_THREADS
742 if (res < 0) 1298 if (res < 0)
743 return posix_error_with_allocated_filename(opath1); 1299 return posix_error_with_allocated_filename(opath1);
744 Py_DECREF(opath1); 1300 Py_DECREF(opath1);
745 Py_INCREF(Py_None); 1301 Py_INCREF(Py_None);
746 return Py_None; 1302 return Py_None;
747 } 1303 }
748 1304
749 static PyObject *
750 posix_2str(PyObject *args,
751 char *format,
752 int (*func)(const char *, const char *))
753 {
754 PyObject *opath1 = NULL, *opath2 = NULL;
755 char *path1, *path2;
756 int res;
757 if (!PyArg_ParseTuple(args, format,
758 PyUnicode_FSConverter, &opath1,
759 PyUnicode_FSConverter, &opath2)) {
760 return NULL;
761 }
762 path1 = PyBytes_AsString(opath1);
763 path2 = PyBytes_AsString(opath2);
764 Py_BEGIN_ALLOW_THREADS
765 res = (*func)(path1, path2);
766 Py_END_ALLOW_THREADS
767 Py_DECREF(opath1);
768 Py_DECREF(opath2);
769 if (res != 0)
770 /* XXX how to report both path1 and path2??? */
771 return posix_error();
772 Py_INCREF(Py_None);
773 return Py_None;
774 }
775 1305
776 #ifdef MS_WINDOWS 1306 #ifdef MS_WINDOWS
777 static PyObject* 1307 static PyObject*
778 win32_1str(PyObject* args, char* func, 1308 win32_1str(PyObject* args, char* func,
779 char* format, BOOL (__stdcall *funcA)(LPCSTR), 1309 char* format, BOOL (__stdcall *funcA)(LPCSTR),
780 char* wformat, BOOL (__stdcall *funcW)(LPWSTR)) 1310 char* wformat, BOOL (__stdcall *funcW)(LPCWSTR))
781 { 1311 {
782 PyObject *uni; 1312 PyObject *uni;
783 char *ansi; 1313 const char *ansi;
784 BOOL result; 1314 BOOL result;
785 1315
786 if (!PyArg_ParseTuple(args, wformat, &uni)) 1316 if (PyArg_ParseTuple(args, wformat, &uni))
787 PyErr_Clear(); 1317 {
788 else { 1318 wchar_t *wstr = PyUnicode_AsUnicode(uni);
1319 if (wstr == NULL)
1320 return NULL;
789 Py_BEGIN_ALLOW_THREADS 1321 Py_BEGIN_ALLOW_THREADS
790 result = funcW(PyUnicode_AsUnicode(uni)); 1322 result = funcW(wstr);
791 Py_END_ALLOW_THREADS 1323 Py_END_ALLOW_THREADS
792 if (!result) 1324 if (!result)
793 return win32_error_unicode(func, PyUnicode_AsUnicode(uni)); 1325 return win32_error_object(func, uni);
794 Py_INCREF(Py_None); 1326 Py_INCREF(Py_None);
795 return Py_None; 1327 return Py_None;
796 } 1328 }
1329 PyErr_Clear();
1330
797 if (!PyArg_ParseTuple(args, format, &ansi)) 1331 if (!PyArg_ParseTuple(args, format, &ansi))
1332 return NULL;
1333 if (win32_warn_bytes_api())
798 return NULL; 1334 return NULL;
799 Py_BEGIN_ALLOW_THREADS 1335 Py_BEGIN_ALLOW_THREADS
800 result = funcA(ansi); 1336 result = funcA(ansi);
801 Py_END_ALLOW_THREADS 1337 Py_END_ALLOW_THREADS
802 if (!result) 1338 if (!result)
803 return win32_error(func, ansi); 1339 return win32_error(func, ansi);
804 Py_INCREF(Py_None); 1340 Py_INCREF(Py_None);
805 return Py_None; 1341 return Py_None;
806 1342
807 } 1343 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 1419
884 struct win32_stat{ 1420 struct win32_stat{
885 int st_dev; 1421 int st_dev;
886 __int64 st_ino; 1422 __int64 st_ino;
887 unsigned short st_mode; 1423 unsigned short st_mode;
888 int st_nlink; 1424 int st_nlink;
889 int st_uid; 1425 int st_uid;
890 int st_gid; 1426 int st_gid;
891 int st_rdev; 1427 int st_rdev;
892 __int64 st_size; 1428 __int64 st_size;
893 int st_atime; 1429 time_t st_atime;
894 int st_atime_nsec; 1430 int st_atime_nsec;
895 int st_mtime; 1431 time_t st_mtime;
896 int st_mtime_nsec; 1432 int st_mtime_nsec;
897 int st_ctime; 1433 time_t st_ctime;
898 int st_ctime_nsec; 1434 int st_ctime_nsec;
899 }; 1435 };
900 1436
901 static __int64 secs_between_epochs = 11644473600LL; /* Seconds between 1.1.1601 and 1.1.1970 */ 1437 static __int64 secs_between_epochs = Py_LL(11644473600); /* Seconds between 1.1. 1601 and 1.1.1970 */
902 1438
903 static void 1439 static void
904 FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, int *time_out, int* nsec_out) 1440 FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
905 { 1441 {
906 /* XXX endianness. Shouldn't matter, as all Windows implementations are litt le-endian */ 1442 /* XXX endianness. Shouldn't matter, as all Windows implementations are litt le-endian */
907 /* Cannot simply cast and dereference in_ptr, 1443 /* Cannot simply cast and dereference in_ptr,
908 since it might not be aligned properly */ 1444 since it might not be aligned properly */
909 __int64 in; 1445 __int64 in;
910 memcpy(&in, in_ptr, sizeof(in)); 1446 memcpy(&in, in_ptr, sizeof(in));
911 *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */ 1447 *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
912 /* XXX Win32 supports time stamps past 2038; we currently don't */ 1448 *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
913 *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, int);
914 } 1449 }
915 1450
916 static void 1451 static void
917 time_t_to_FILE_TIME(int time_in, int nsec_in, FILETIME *out_ptr) 1452 time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
918 { 1453 {
919 /* XXX endianness */ 1454 /* XXX endianness */
920 __int64 out; 1455 __int64 out;
921 out = time_in + secs_between_epochs; 1456 out = time_in + secs_between_epochs;
922 out = out * 10000000 + nsec_in / 100; 1457 out = out * 10000000 + nsec_in / 100;
923 memcpy(out_ptr, &out, sizeof(out)); 1458 memcpy(out_ptr, &out, sizeof(out));
924 } 1459 }
925 1460
926 /* Below, we *know* that ugo+r is 0444 */ 1461 /* Below, we *know* that ugo+r is 0444 */
927 #if _S_IREAD != 0400 1462 #if _S_IREAD != 0400
928 #error Unsupported C library 1463 #error Unsupported C library
929 #endif 1464 #endif
930 static int 1465 static int
931 attributes_to_mode(DWORD attr) 1466 attributes_to_mode(DWORD attr)
932 { 1467 {
933 int m = 0; 1468 int m = 0;
934 if (attr & FILE_ATTRIBUTE_DIRECTORY) 1469 if (attr & FILE_ATTRIBUTE_DIRECTORY)
935 m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */ 1470 m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
936 else 1471 else
937 m |= _S_IFREG; 1472 m |= _S_IFREG;
938 if (attr & FILE_ATTRIBUTE_READONLY) 1473 if (attr & FILE_ATTRIBUTE_READONLY)
939 m |= 0444; 1474 m |= 0444;
940 else 1475 else
941 m |= 0666; 1476 m |= 0666;
942 return m; 1477 return m;
943 } 1478 }
944 1479
945 static int 1480 static int
946 attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *resul t) 1481 attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, stru ct win32_stat *result)
947 { 1482 {
948 memset(result, 0, sizeof(*result)); 1483 memset(result, 0, sizeof(*result));
949 result->st_mode = attributes_to_mode(info->dwFileAttributes); 1484 result->st_mode = attributes_to_mode(info->dwFileAttributes);
950 result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow; 1485 result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
951 FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result-> st_ctime_nsec); 1486 FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result-> st_ctime_nsec);
952 FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result- >st_mtime_nsec); 1487 FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result- >st_mtime_nsec);
953 FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result ->st_atime_nsec); 1488 FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result ->st_atime_nsec);
1489 result->st_nlink = info->nNumberOfLinks;
1490 result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow ;
1491 if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
1492 /* first clear the S_IFMT bits */
1493 result->st_mode ^= (result->st_mode & 0170000);
1494 /* now set the bits that make this a symlink */
1495 result->st_mode |= 0120000;
1496 }
954 1497
955 return 0; 1498 return 0;
956 } 1499 }
957 1500
958 static BOOL 1501 static BOOL
959 attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) 1502 attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *rep arse_tag)
960 { 1503 {
961 HANDLE hFindFile; 1504 HANDLE hFindFile;
962 WIN32_FIND_DATAA FileData; 1505 WIN32_FIND_DATAA FileData;
963 hFindFile = FindFirstFileA(pszFile, &FileData); 1506 hFindFile = FindFirstFileA(pszFile, &FileData);
964 if (hFindFile == INVALID_HANDLE_VALUE) 1507 if (hFindFile == INVALID_HANDLE_VALUE)
965 return FALSE; 1508 return FALSE;
966 FindClose(hFindFile); 1509 FindClose(hFindFile);
967 pfad->dwFileAttributes = FileData.dwFileAttributes; 1510 memset(info, 0, sizeof(*info));
968 pfad->ftCreationTime = FileData.ftCreationTime; 1511 *reparse_tag = 0;
969 pfad->ftLastAccessTime = FileData.ftLastAccessTime; 1512 info->dwFileAttributes = FileData.dwFileAttributes;
970 pfad->ftLastWriteTime = FileData.ftLastWriteTime; 1513 info->ftCreationTime = FileData.ftCreationTime;
971 pfad->nFileSizeHigh = FileData.nFileSizeHigh; 1514 info->ftLastAccessTime = FileData.ftLastAccessTime;
972 pfad->nFileSizeLow = FileData.nFileSizeLow; 1515 info->ftLastWriteTime = FileData.ftLastWriteTime;
1516 info->nFileSizeHigh = FileData.nFileSizeHigh;
1517 info->nFileSizeLow = FileData.nFileSizeLow;
1518 /* info->nNumberOfLinks = 1; */
1519 if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1520 *reparse_tag = FileData.dwReserved0;
973 return TRUE; 1521 return TRUE;
974 } 1522 }
975 1523
976 static BOOL 1524 static BOOL
977 attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) 1525 attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG * reparse_tag)
978 { 1526 {
979 HANDLE hFindFile; 1527 HANDLE hFindFile;
980 WIN32_FIND_DATAW FileData; 1528 WIN32_FIND_DATAW FileData;
981 hFindFile = FindFirstFileW(pszFile, &FileData); 1529 hFindFile = FindFirstFileW(pszFile, &FileData);
982 if (hFindFile == INVALID_HANDLE_VALUE) 1530 if (hFindFile == INVALID_HANDLE_VALUE)
983 return FALSE; 1531 return FALSE;
984 FindClose(hFindFile); 1532 FindClose(hFindFile);
985 pfad->dwFileAttributes = FileData.dwFileAttributes; 1533 memset(info, 0, sizeof(*info));
986 pfad->ftCreationTime = FileData.ftCreationTime; 1534 *reparse_tag = 0;
987 pfad->ftLastAccessTime = FileData.ftLastAccessTime; 1535 info->dwFileAttributes = FileData.dwFileAttributes;
988 pfad->ftLastWriteTime = FileData.ftLastWriteTime; 1536 info->ftCreationTime = FileData.ftCreationTime;
989 pfad->nFileSizeHigh = FileData.nFileSizeHigh; 1537 info->ftLastAccessTime = FileData.ftLastAccessTime;
990 pfad->nFileSizeLow = FileData.nFileSizeLow; 1538 info->ftLastWriteTime = FileData.ftLastWriteTime;
1539 info->nFileSizeHigh = FileData.nFileSizeHigh;
1540 info->nFileSizeLow = FileData.nFileSizeLow;
1541 /* info->nNumberOfLinks = 1; */
1542 if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1543 *reparse_tag = FileData.dwReserved0;
991 return TRUE; 1544 return TRUE;
992 }
993
994 /* About the following functions: win32_lstat, win32_lstat_w, win32_stat,
995 win32_stat_w
996
997 In Posix, stat automatically traverses symlinks and returns the stat
998 structure for the target. In Windows, the equivalent GetFileAttributes by
999 default does not traverse symlinks and instead returns attributes for
1000 the symlink.
1001
1002 Therefore, win32_lstat will get the attributes traditionally, and
1003 win32_stat will first explicitly resolve the symlink target and then will
1004 call win32_lstat on that result.
1005
1006 The _w represent Unicode equivalents of the aformentioned ANSI functions. */
1007
1008 static int
1009 win32_lstat(const char* path, struct win32_stat *result)
1010 {
1011 WIN32_FILE_ATTRIBUTE_DATA info;
1012 int code;
1013 char *dot;
1014 WIN32_FIND_DATAA find_data;
1015 HANDLE find_data_handle;
1016 if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
1017 if (GetLastError() != ERROR_SHARING_VIOLATION) {
1018 /* Protocol violation: we explicitly clear errno, instead of
1019 setting it to a POSIX error. Callers should use GetLastError. */
1020 errno = 0;
1021 return -1;
1022 } else {
1023 /* Could not get attributes on open file. Fall back to
1024 reading the directory. */
1025 if (!attributes_from_dir(path, &info)) {
1026 /* Very strange. This should not fail now */
1027 errno = 0;
1028 return -1;
1029 }
1030 }
1031 }
1032
1033 code = attribute_data_to_stat(&info, result);
1034 if (code != 0)
1035 return code;
1036
1037 /* Get WIN32_FIND_DATA structure for the path to determine if
1038 it is a symlink */
1039 if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1040 find_data_handle = FindFirstFileA(path, &find_data);
1041 if(find_data_handle != INVALID_HANDLE_VALUE) {
1042 if(find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
1043 /* first clear the S_IFMT bits */
1044 result->st_mode ^= (result->st_mode & 0170000);
1045 /* now set the bits that make this a symlink */
1046 result->st_mode |= 0120000;
1047 }
1048 FindClose(find_data_handle);
1049 }
1050 }
1051
1052 /* Set S_IFEXEC if it is an .exe, .bat, ... */
1053 dot = strrchr(path, '.');
1054 if (dot) {
1055 if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
1056 stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
1057 result->st_mode |= 0111;
1058 }
1059 return code;
1060 }
1061
1062 static int
1063 win32_lstat_w(const wchar_t* path, struct win32_stat *result)
1064 {
1065 int code;
1066 const wchar_t *dot;
1067 WIN32_FILE_ATTRIBUTE_DATA info;
1068 WIN32_FIND_DATAW find_data;
1069 HANDLE find_data_handle;
1070 if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
1071 if (GetLastError() != ERROR_SHARING_VIOLATION) {
1072 /* Protocol violation: we explicitly clear errno, instead of
1073 setting it to a POSIX error. Callers should use GetLastError. */
1074 errno = 0;
1075 return -1;
1076 } else {
1077 /* Could not get attributes on open file. Fall back to reading
1078 the directory. */
1079 if (!attributes_from_dir_w(path, &info)) {
1080 /* Very strange. This should not fail now */
1081 errno = 0;
1082 return -1;
1083 }
1084 }
1085 }
1086 code = attribute_data_to_stat(&info, result);
1087 if (code < 0)
1088 return code;
1089
1090 /* Get WIN32_FIND_DATA structure for the path to determine if
1091 it is a symlink */
1092 if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1093 find_data_handle = FindFirstFileW(path, &find_data);
1094 if(find_data_handle != INVALID_HANDLE_VALUE) {
1095 if(find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
1096 /* first clear the S_IFMT bits */
1097 result->st_mode ^= (result->st_mode & 0170000);
1098 /* now set the bits that make this a symlink */
1099 result->st_mode |= 0120000;
1100 }
1101 FindClose(find_data_handle);
1102 }
1103 }
1104
1105 /* Set IFEXEC if it is an .exe, .bat, ... */
1106 dot = wcsrchr(path, '.');
1107 if (dot) {
1108 if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
1109 _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
1110 result->st_mode |= 0111;
1111 }
1112 return code;
1113 } 1545 }
1114 1546
1115 /* Grab GetFinalPathNameByHandle dynamically from kernel32 */ 1547 /* Grab GetFinalPathNameByHandle dynamically from kernel32 */
1116 static int has_GetFinalPathNameByHandle = 0; 1548 static int has_GetFinalPathNameByHandle = 0;
1117 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
1118 DWORD);
1119 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, 1549 static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
1120 DWORD); 1550 DWORD);
1121 static int 1551 static int
1122 check_GetFinalPathNameByHandle() 1552 check_GetFinalPathNameByHandle()
1123 { 1553 {
1124 HINSTANCE hKernel32; 1554 HINSTANCE hKernel32;
1555 DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
1556 DWORD);
1557
1125 /* only recheck */ 1558 /* only recheck */
1126 if (!has_GetFinalPathNameByHandle) 1559 if (!has_GetFinalPathNameByHandle)
1127 { 1560 {
1128 hKernel32 = GetModuleHandle("KERNEL32"); 1561 hKernel32 = GetModuleHandleW(L"KERNEL32");
1129 *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32, 1562 *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
1130 "GetFinalPathNameByHandleA"); 1563 "GetFinalPathNameByHandleA");
1131 *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32, 1564 *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
1132 "GetFinalPathNameByHandleW"); 1565 "GetFinalPathNameByHandleW");
1133 has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA && 1566 has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
1134 Py_GetFinalPathNameByHandleW; 1567 Py_GetFinalPathNameByHandleW;
1135 } 1568 }
1136 return has_GetFinalPathNameByHandle; 1569 return has_GetFinalPathNameByHandle;
1137 } 1570 }
1138 1571
1572 static BOOL
1573 get_target_path(HANDLE hdl, wchar_t **target_path)
1574 {
1575 int buf_size, result_length;
1576 wchar_t *buf;
1577
1578 /* We have a good handle to the target, use it to determine
1579 the target path name (then we'll call lstat on it). */
1580 buf_size = Py_GetFinalPathNameByHandleW(hdl, 0, 0,
1581 VOLUME_NAME_DOS);
1582 if(!buf_size)
1583 return FALSE;
1584
1585 buf = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
1586 if (!buf) {
1587 SetLastError(ERROR_OUTOFMEMORY);
1588 return FALSE;
1589 }
1590
1591 result_length = Py_GetFinalPathNameByHandleW(hdl,
1592 buf, buf_size, VOLUME_NAME_DOS);
1593
1594 if(!result_length) {
1595 free(buf);
1596 return FALSE;
1597 }
1598
1599 if(!CloseHandle(hdl)) {
1600 free(buf);
1601 return FALSE;
1602 }
1603
1604 buf[result_length] = 0;
1605
1606 *target_path = buf;
1607 return TRUE;
1608 }
1609
1139 static int 1610 static int
1140 win32_stat(const char* path, struct win32_stat *result) 1611 win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
1141 { 1612 BOOL traverse);
1142 /* Traverse the symlink to the target using 1613 static int
1143 GetFinalPathNameByHandle() 1614 win32_xstat_impl(const char *path, struct win32_stat *result,
1144 */ 1615 BOOL traverse)
1616 {
1145 int code; 1617 int code;
1146 HANDLE hFile; 1618 HANDLE hFile, hFile2;
1147 int buf_size; 1619 BY_HANDLE_FILE_INFORMATION info;
1148 char *target_path; 1620 ULONG reparse_tag = 0;
1149 int result_length; 1621 wchar_t *target_path;
1150 WIN32_FILE_ATTRIBUTE_DATA info; 1622 const char *dot;
1151 1623
1152 if(!check_GetFinalPathNameByHandle()) { 1624 if(!check_GetFinalPathNameByHandle()) {
1153 /* if the OS doesn't have GetFinalPathNameByHandle, it doesn't 1625 /* If the OS doesn't have GetFinalPathNameByHandle, don't
1154 have symlinks, so just fall back to the traditional behavior 1626 traverse reparse point. */
1155 found in lstat. */ 1627 traverse = FALSE;
1156 return win32_lstat(path, result);
1157 } 1628 }
1158 1629
1159 hFile = CreateFileA( 1630 hFile = CreateFileA(
1160 path, 1631 path,
1161 0, /* desired access */ 1632 FILE_READ_ATTRIBUTES, /* desired access */
1162 0, /* share mode */ 1633 0, /* share mode */
1163 NULL, /* security attributes */ 1634 NULL, /* security attributes */
1164 OPEN_EXISTING, 1635 OPEN_EXISTING,
1165 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 1636 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1166 FILE_FLAG_BACKUP_SEMANTICS, 1637 /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
1638 Because of this, calls like GetFinalPathNameByHandle will return
1639 the symlink path agin and not the actual final path. */
1640 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
1641 FILE_FLAG_OPEN_REPARSE_POINT,
1167 NULL); 1642 NULL);
1168 1643
1169 if(hFile == INVALID_HANDLE_VALUE) { 1644 if (hFile == INVALID_HANDLE_VALUE) {
1170 /* Either the target doesn't exist, or we don't have access to 1645 /* Either the target doesn't exist, or we don't have access to
1171 get a handle to it. If the former, we need to return an error. 1646 get a handle to it. If the former, we need to return an error.
1172 If the latter, we can use attributes_from_dir. */ 1647 If the latter, we can use attributes_from_dir. */
1173 if (GetLastError() != ERROR_SHARING_VIOLATION) { 1648 if (GetLastError() != ERROR_SHARING_VIOLATION)
1174 /* Protocol violation: we explicitly clear errno, instead of
1175 setting it to a POSIX error. Callers should use GetLastError. */
1176 errno = 0;
1177 return -1; 1649 return -1;
1178 } else { 1650 /* Could not get attributes on open file. Fall back to
1179 /* Could not get attributes on open file. Fall back to 1651 reading the directory. */
1180 reading the directory. */ 1652 if (!attributes_from_dir(path, &info, &reparse_tag))
1181 if (!attributes_from_dir(path, &info)) { 1653 /* Very strange. This should not fail now */
1182 /* Very strange. This should not fail now */ 1654 return -1;
1183 errno = 0; 1655 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1656 if (traverse) {
1657 /* Should traverse, but could not open reparse point handle */
1658 SetLastError(ERROR_SHARING_VIOLATION);
1184 return -1; 1659 return -1;
1185 } 1660 }
1186 } 1661 }
1187 code = attribute_data_to_stat(&info, result); 1662 } else {
1188 } 1663 if (!GetFileInformationByHandle(hFile, &info)) {
1189 1664 CloseHandle(hFile);
1190 buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS); 1665 return -1;
1191 if(!buf_size) return -1; 1666 }
1192 target_path = (char *)malloc((buf_size+1)*sizeof(char)); 1667 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1193 result_length = Py_GetFinalPathNameByHandleA(hFile, target_path, 1668 if (!win32_get_reparse_tag(hFile, &reparse_tag))
1194 buf_size, VOLUME_NAME_DOS); 1669 return -1;
1195 1670
1196 if(!result_length) 1671 /* Close the outer open file handle now that we're about to
1197 return -1; 1672 reopen it with different flags. */
1198 1673 if (!CloseHandle(hFile))
1199 if(!CloseHandle(hFile)) 1674 return -1;
1200 return -1; 1675
1201 1676 if (traverse) {
1202 target_path[result_length] = 0; 1677 /* In order to call GetFinalPathNameByHandle we need to open
1203 code = win32_lstat(target_path, result); 1678 the file without the reparse handling flag set. */
1204 free(target_path); 1679 hFile2 = CreateFileA(
1205 1680 path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
1206 return code; 1681 NULL, OPEN_EXISTING,
1207 } 1682 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
1208 1683 NULL);
1209 static int 1684 if (hFile2 == INVALID_HANDLE_VALUE)
1210 win32_stat_w(const wchar_t* path, struct win32_stat *result) 1685 return -1;
1211 { 1686
1212 /* Traverse the symlink to the target using GetFinalPathNameByHandle() */ 1687 if (!get_target_path(hFile2, &target_path))
1688 return -1;
1689
1690 code = win32_xstat_impl_w(target_path, result, FALSE);
1691 free(target_path);
1692 return code;
1693 }
1694 } else
1695 CloseHandle(hFile);
1696 }
1697 attribute_data_to_stat(&info, reparse_tag, result);
1698
1699 /* Set S_IEXEC if it is an .exe, .bat, ... */
1700 dot = strrchr(path, '.');
1701 if (dot) {
1702 if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
1703 stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
1704 result->st_mode |= 0111;
1705 }
1706 return 0;
1707 }
1708
1709 static int
1710 win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
1711 BOOL traverse)
1712 {
1213 int code; 1713 int code;
1214 HANDLE hFile; 1714 HANDLE hFile, hFile2;
1215 int buf_size; 1715 BY_HANDLE_FILE_INFORMATION info;
1716 ULONG reparse_tag = 0;
1216 wchar_t *target_path; 1717 wchar_t *target_path;
1217 int result_length; 1718 const wchar_t *dot;
1218 WIN32_FILE_ATTRIBUTE_DATA info; 1719
1219
1220 if(!check_GetFinalPathNameByHandle()) { 1720 if(!check_GetFinalPathNameByHandle()) {
1221 /* If the OS doesn't have GetFinalPathNameByHandle, it doesn't have 1721 /* If the OS doesn't have GetFinalPathNameByHandle, don't
1222 symlinks, so just fall back to the traditional behavior found 1722 traverse reparse point. */
1223 in lstat. */ 1723 traverse = FALSE;
1224 return win32_lstat_w(path, result);
1225 } 1724 }
1226 1725
1227 hFile = CreateFileW( 1726 hFile = CreateFileW(
1228 path, 1727 path,
1229 0, /* desired access */ 1728 FILE_READ_ATTRIBUTES, /* desired access */
1230 0, /* share mode */ 1729 0, /* share mode */
1231 NULL, /* security attributes */ 1730 NULL, /* security attributes */
1232 OPEN_EXISTING, 1731 OPEN_EXISTING,
1233 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 1732 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1234 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 1733 /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
1734 Because of this, calls like GetFinalPathNameByHandle will return
1735 the symlink path agin and not the actual final path. */
1736 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
1737 FILE_FLAG_OPEN_REPARSE_POINT,
1235 NULL); 1738 NULL);
1236 1739
1237 if(hFile == INVALID_HANDLE_VALUE) { 1740 if (hFile == INVALID_HANDLE_VALUE) {
1238 /* Either the target doesn't exist, or we don't have access to 1741 /* Either the target doesn't exist, or we don't have access to
1239 get a handle to it. If the former, we need to return an error. 1742 get a handle to it. If the former, we need to return an error.
1240 If the latter, we can use attributes_from_dir. */ 1743 If the latter, we can use attributes_from_dir. */
1241 if (GetLastError() != ERROR_SHARING_VIOLATION) { 1744 if (GetLastError() != ERROR_SHARING_VIOLATION)
1242 /* Protocol violation: we explicitly clear errno, instead of
1243 setting it to a POSIX error. Callers should use GetLastError. */
1244 errno = 0;
1245 return -1; 1745 return -1;
1246 } else { 1746 /* Could not get attributes on open file. Fall back to
1247 /* Could not get attributes on open file. Fall back to 1747 reading the directory. */
1248 reading the directory. */ 1748 if (!attributes_from_dir_w(path, &info, &reparse_tag))
1249 if (!attributes_from_dir_w(path, &info)) { 1749 /* Very strange. This should not fail now */
1250 /* Very strange. This should not fail now */ 1750 return -1;
1251 errno = 0; 1751 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1752 if (traverse) {
1753 /* Should traverse, but could not open reparse point handle */
1754 SetLastError(ERROR_SHARING_VIOLATION);
1252 return -1; 1755 return -1;
1253 } 1756 }
1254 } 1757 }
1255 code = attribute_data_to_stat(&info, result); 1758 } else {
1256 } 1759 if (!GetFileInformationByHandle(hFile, &info)) {
1257 else { 1760 CloseHandle(hFile);
1258 /* We have a good handle to the target, use it to determine the target
1259 path name (then we'll call lstat on it). */
1260 buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_DOS);
1261 if(!buf_size)
1262 return -1; 1761 return -1;
1263 1762 }
1264 target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t)); 1763 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1265 result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, 1764 if (!win32_get_reparse_tag(hFile, &reparse_tag))
1266 buf_size, VOLUME_NAME_DOS); 1765 return -1;
1267 1766
1268 if(!result_length) 1767 /* Close the outer open file handle now that we're about to
1269 return -1; 1768 reopen it with different flags. */
1270 1769 if (!CloseHandle(hFile))
1271 if(!CloseHandle(hFile)) 1770 return -1;
1272 return -1; 1771
1273 1772 if (traverse) {
1274 target_path[result_length] = 0; 1773 /* In order to call GetFinalPathNameByHandle we need to open
1275 code = win32_lstat_w(target_path, result); 1774 the file without the reparse handling flag set. */
1276 free(target_path); 1775 hFile2 = CreateFileW(
1277 } 1776 path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
1278 1777 NULL, OPEN_EXISTING,
1778 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
1779 NULL);
1780 if (hFile2 == INVALID_HANDLE_VALUE)
1781 return -1;
1782
1783 if (!get_target_path(hFile2, &target_path))
1784 return -1;
1785
1786 code = win32_xstat_impl_w(target_path, result, FALSE);
1787 free(target_path);
1788 return code;
1789 }
1790 } else
1791 CloseHandle(hFile);
1792 }
1793 attribute_data_to_stat(&info, reparse_tag, result);
1794
1795 /* Set S_IEXEC if it is an .exe, .bat, ... */
1796 dot = wcsrchr(path, '.');
1797 if (dot) {
1798 if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
1799 _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
1800 result->st_mode |= 0111;
1801 }
1802 return 0;
1803 }
1804
1805 static int
1806 win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
1807 {
1808 /* Protocol violation: we explicitly clear errno, instead of
1809 setting it to a POSIX error. Callers should use GetLastError. */
1810 int code = win32_xstat_impl(path, result, traverse);
1811 errno = 0;
1279 return code; 1812 return code;
1813 }
1814
1815 static int
1816 win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
1817 {
1818 /* Protocol violation: we explicitly clear errno, instead of
1819 setting it to a POSIX error. Callers should use GetLastError. */
1820 int code = win32_xstat_impl_w(path, result, traverse);
1821 errno = 0;
1822 return code;
1823 }
1824 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1825
1826 In Posix, stat automatically traverses symlinks and returns the stat
1827 structure for the target. In Windows, the equivalent GetFileAttributes by
1828 default does not traverse symlinks and instead returns attributes for
1829 the symlink.
1830
1831 Therefore, win32_lstat will get the attributes traditionally, and
1832 win32_stat will first explicitly resolve the symlink target and then will
1833 call win32_lstat on that result.
1834
1835 The _w represent Unicode equivalents of the aforementioned ANSI functions. */
1836
1837 static int
1838 win32_lstat(const char* path, struct win32_stat *result)
1839 {
1840 return win32_xstat(path, result, FALSE);
1841 }
1842
1843 static int
1844 win32_lstat_w(const wchar_t* path, struct win32_stat *result)
1845 {
1846 return win32_xstat_w(path, result, FALSE);
1847 }
1848
1849 static int
1850 win32_stat(const char* path, struct win32_stat *result)
1851 {
1852 return win32_xstat(path, result, TRUE);
1853 }
1854
1855 static int
1856 win32_stat_w(const wchar_t* path, struct win32_stat *result)
1857 {
1858 return win32_xstat_w(path, result, TRUE);
1280 } 1859 }
1281 1860
1282 static int 1861 static int
1283 win32_fstat(int file_number, struct win32_stat *result) 1862 win32_fstat(int file_number, struct win32_stat *result)
1284 { 1863 {
1285 BY_HANDLE_FILE_INFORMATION info; 1864 BY_HANDLE_FILE_INFORMATION info;
1286 HANDLE h; 1865 HANDLE h;
1287 int type; 1866 int type;
1288 1867
1289 h = (HANDLE)_get_osfhandle(file_number); 1868 if (!_PyVerify_fd(file_number))
1869 h = INVALID_HANDLE_VALUE;
1870 else
1871 h = (HANDLE)_get_osfhandle(file_number);
1290 1872
1291 /* Protocol violation: we explicitly clear errno, instead of 1873 /* Protocol violation: we explicitly clear errno, instead of
1292 setting it to a POSIX error. Callers should use GetLastError. */ 1874 setting it to a POSIX error. Callers should use GetLastError. */
1293 errno = 0; 1875 errno = 0;
1294 1876
1295 if (h == INVALID_HANDLE_VALUE) { 1877 if (h == INVALID_HANDLE_VALUE) {
1296 /* This is really a C library error (invalid file handle). 1878 /* This is really a C library error (invalid file handle).
1297 We set the Win32 error to the closes one matching. */ 1879 We set the Win32 error to the closes one matching. */
1298 SetLastError(ERROR_INVALID_HANDLE); 1880 SetLastError(ERROR_INVALID_HANDLE);
1299 return -1; 1881 return -1;
1300 } 1882 }
1301 memset(result, 0, sizeof(*result)); 1883 memset(result, 0, sizeof(*result));
1302 1884
1303 type = GetFileType(h); 1885 type = GetFileType(h);
1304 if (type == FILE_TYPE_UNKNOWN) { 1886 if (type == FILE_TYPE_UNKNOWN) {
1305 DWORD error = GetLastError(); 1887 DWORD error = GetLastError();
1306 if (error != 0) { 1888 if (error != 0) {
1307 return -1; 1889 return -1;
1308 } 1890 }
1309 /* else: valid but unknown file */ 1891 /* else: valid but unknown file */
1310 } 1892 }
1311 1893
1312 if (type != FILE_TYPE_DISK) { 1894 if (type != FILE_TYPE_DISK) {
1313 if (type == FILE_TYPE_CHAR) 1895 if (type == FILE_TYPE_CHAR)
1314 result->st_mode = _S_IFCHR; 1896 result->st_mode = _S_IFCHR;
1315 else if (type == FILE_TYPE_PIPE) 1897 else if (type == FILE_TYPE_PIPE)
1316 result->st_mode = _S_IFIFO; 1898 result->st_mode = _S_IFIFO;
1317 return 0; 1899 return 0;
1318 } 1900 }
1319 1901
1320 if (!GetFileInformationByHandle(h, &info)) { 1902 if (!GetFileInformationByHandle(h, &info)) {
1321 return -1; 1903 return -1;
1322 } 1904 }
1323 1905
1324 /* similar to stat() */ 1906 attribute_data_to_stat(&info, 0, result);
1325 result->st_mode = attributes_to_mode(info.dwFileAttributes);
1326 result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
1327 FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime,
1328 &result->st_ctime_nsec);
1329 FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime,
1330 &result->st_mtime_nsec);
1331 FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime,
1332 &result->st_atime_nsec);
1333 /* specific to fstat() */ 1907 /* specific to fstat() */
1334 result->st_nlink = info.nNumberOfLinks;
1335 result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow; 1908 result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1336 return 0; 1909 return 0;
1337 } 1910 }
1338 1911
1339 #endif /* MS_WINDOWS */ 1912 #endif /* MS_WINDOWS */
1340 1913
1341 PyDoc_STRVAR(stat_result__doc__, 1914 PyDoc_STRVAR(stat_result__doc__,
1342 "stat_result: Result from stat or lstat.\n\n\ 1915 "stat_result: Result from stat, fstat, or lstat.\n\n\
1343 This object may be accessed either as a tuple of\n\ 1916 This object may be accessed either as a tuple of\n\
1344 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ 1917 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1345 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ 1918 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1346 \n\ 1919 \n\
1347 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ 1920 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1348 or st_flags, they are available as attributes only.\n\ 1921 or st_flags, they are available as attributes only.\n\
1349 \n\ 1922 \n\
1350 See os.stat for more information."); 1923 See os.stat for more information.");
1351 1924
1352 static PyStructSequence_Field stat_result_fields[] = { 1925 static PyStructSequence_Field stat_result_fields[] = {
1353 {"st_mode", "protection bits"}, 1926 {"st_mode", "protection bits"},
1354 {"st_ino", "inode"}, 1927 {"st_ino", "inode"},
1355 {"st_dev", "device"}, 1928 {"st_dev", "device"},
1356 {"st_nlink", "number of hard links"}, 1929 {"st_nlink", "number of hard links"},
1357 {"st_uid", "user ID of owner"}, 1930 {"st_uid", "user ID of owner"},
1358 {"st_gid", "group ID of owner"}, 1931 {"st_gid", "group ID of owner"},
1359 {"st_size", "total size, in bytes"}, 1932 {"st_size", "total size, in bytes"},
1360 /* The NULL is replaced with PyStructSequence_UnnamedField later. */ 1933 /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1361 {NULL, "integer time of last access"}, 1934 {NULL, "integer time of last access"},
1362 {NULL, "integer time of last modification"}, 1935 {NULL, "integer time of last modification"},
1363 {NULL, "integer time of last change"}, 1936 {NULL, "integer time of last change"},
1364 {"st_atime", "time of last access"}, 1937 {"st_atime", "time of last access"},
1365 {"st_mtime", "time of last modification"}, 1938 {"st_mtime", "time of last modification"},
1366 {"st_ctime", "time of last change"}, 1939 {"st_ctime", "time of last change"},
1940 {"st_atime_ns", "time of last access in nanoseconds"},
1941 {"st_mtime_ns", "time of last modification in nanoseconds"},
1942 {"st_ctime_ns", "time of last change in nanoseconds"},
1367 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1943 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1368 {"st_blksize", "blocksize for filesystem I/O"}, 1944 {"st_blksize", "blocksize for filesystem I/O"},
1369 #endif 1945 #endif
1370 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS 1946 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1371 {"st_blocks", "number of blocks allocated"}, 1947 {"st_blocks", "number of blocks allocated"},
1372 #endif 1948 #endif
1373 #ifdef HAVE_STRUCT_STAT_ST_RDEV 1949 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1374 {"st_rdev", "device type (if inode device)"}, 1950 {"st_rdev", "device type (if inode device)"},
1375 #endif 1951 #endif
1376 #ifdef HAVE_STRUCT_STAT_ST_FLAGS 1952 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1377 {"st_flags", "user defined flags for file"}, 1953 {"st_flags", "user defined flags for file"},
1378 #endif 1954 #endif
1379 #ifdef HAVE_STRUCT_STAT_ST_GEN 1955 #ifdef HAVE_STRUCT_STAT_ST_GEN
1380 {"st_gen", "generation number"}, 1956 {"st_gen", "generation number"},
1381 #endif 1957 #endif
1382 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME 1958 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1383 {"st_birthtime", "time of creation"}, 1959 {"st_birthtime", "time of creation"},
1384 #endif 1960 #endif
1385 {0} 1961 {0}
1386 }; 1962 };
1387 1963
1388 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1964 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1389 #define ST_BLKSIZE_IDX 13 1965 #define ST_BLKSIZE_IDX 16
1390 #else 1966 #else
1391 #define ST_BLKSIZE_IDX 12 1967 #define ST_BLKSIZE_IDX 15
1392 #endif 1968 #endif
1393 1969
1394 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS 1970 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1395 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) 1971 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1396 #else 1972 #else
1397 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX 1973 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1398 #endif 1974 #endif
1399 1975
1400 #ifdef HAVE_STRUCT_STAT_ST_RDEV 1976 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1401 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1) 1977 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1450 {0} 2026 {0}
1451 }; 2027 };
1452 2028
1453 static PyStructSequence_Desc statvfs_result_desc = { 2029 static PyStructSequence_Desc statvfs_result_desc = {
1454 "statvfs_result", /* name */ 2030 "statvfs_result", /* name */
1455 statvfs_result__doc__, /* doc */ 2031 statvfs_result__doc__, /* doc */
1456 statvfs_result_fields, 2032 statvfs_result_fields,
1457 10 2033 10
1458 }; 2034 };
1459 2035
2036 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2037 PyDoc_STRVAR(waitid_result__doc__,
2038 "waitid_result: Result from waitid.\n\n\
2039 This object may be accessed either as a tuple of\n\
2040 (si_pid, si_uid, si_signo, si_status, si_code),\n\
2041 or via the attributes si_pid, si_uid, and so on.\n\
2042 \n\
2043 See os.waitid for more information.");
2044
2045 static PyStructSequence_Field waitid_result_fields[] = {
2046 {"si_pid", },
2047 {"si_uid", },
2048 {"si_signo", },
2049 {"si_status", },
2050 {"si_code", },
2051 {0}
2052 };
2053
2054 static PyStructSequence_Desc waitid_result_desc = {
2055 "waitid_result", /* name */
2056 waitid_result__doc__, /* doc */
2057 waitid_result_fields,
2058 5
2059 };
2060 static PyTypeObject WaitidResultType;
2061 #endif
2062
1460 static int initialized; 2063 static int initialized;
1461 static PyTypeObject StatResultType; 2064 static PyTypeObject StatResultType;
1462 static PyTypeObject StatVFSResultType; 2065 static PyTypeObject StatVFSResultType;
2066 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
2067 static PyTypeObject SchedParamType;
2068 #endif
1463 static newfunc structseq_new; 2069 static newfunc structseq_new;
1464 2070
1465 static PyObject * 2071 static PyObject *
1466 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 2072 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1467 { 2073 {
1468 PyStructSequence *result; 2074 PyStructSequence *result;
1469 int i; 2075 int i;
1470 2076
1471 result = (PyStructSequence*)structseq_new(type, args, kwds); 2077 result = (PyStructSequence*)structseq_new(type, args, kwds);
1472 if (!result) 2078 if (!result)
(...skipping 22 matching lines...) Expand all
1495 If newval is True, future calls to stat() return floats, if it is False,\n\ 2101 If newval is True, future calls to stat() return floats, if it is False,\n\
1496 future calls return ints. \n\ 2102 future calls return ints. \n\
1497 If newval is omitted, return the current setting.\n"); 2103 If newval is omitted, return the current setting.\n");
1498 2104
1499 static PyObject* 2105 static PyObject*
1500 stat_float_times(PyObject* self, PyObject *args) 2106 stat_float_times(PyObject* self, PyObject *args)
1501 { 2107 {
1502 int newval = -1; 2108 int newval = -1;
1503 if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval)) 2109 if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
1504 return NULL; 2110 return NULL;
2111 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2112 "stat_float_times() is deprecated",
2113 1))
2114 return NULL;
1505 if (newval == -1) 2115 if (newval == -1)
1506 /* Return old value */ 2116 /* Return old value */
1507 return PyBool_FromLong(_stat_float_times); 2117 return PyBool_FromLong(_stat_float_times);
1508 _stat_float_times = newval; 2118 _stat_float_times = newval;
1509 Py_INCREF(Py_None); 2119 Py_INCREF(Py_None);
1510 return Py_None; 2120 return Py_None;
1511 } 2121 }
1512 2122
2123 static PyObject *billion = NULL;
2124
1513 static void 2125 static void
1514 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) 2126 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
1515 { 2127 {
1516 PyObject *fval,*ival; 2128 PyObject *s = _PyLong_FromTime_t(sec);
1517 #if SIZEOF_TIME_T > SIZEOF_LONG 2129 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
1518 ival = PyLong_FromLongLong((PY_LONG_LONG)sec); 2130 PyObject *s_in_ns = NULL;
1519 #else 2131 PyObject *ns_total = NULL;
1520 ival = PyLong_FromLong((long)sec); 2132 PyObject *float_s = NULL;
1521 #endif 2133
1522 if (!ival) 2134 if (!(s && ns_fractional))
1523 return; 2135 goto exit;
2136
2137 s_in_ns = PyNumber_Multiply(s, billion);
2138 if (!s_in_ns)
2139 goto exit;
2140
2141 ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2142 if (!ns_total)
2143 goto exit;
2144
1524 if (_stat_float_times) { 2145 if (_stat_float_times) {
1525 fval = PyFloat_FromDouble(sec + 1e-9*nsec); 2146 float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
1526 } else { 2147 if (!float_s)
1527 fval = ival; 2148 goto exit;
1528 Py_INCREF(fval); 2149 }
1529 } 2150 else {
1530 PyStructSequence_SET_ITEM(v, index, ival); 2151 float_s = s;
1531 PyStructSequence_SET_ITEM(v, index+3, fval); 2152 Py_INCREF(float_s);
2153 }
2154
2155 PyStructSequence_SET_ITEM(v, index, s);
2156 PyStructSequence_SET_ITEM(v, index+3, float_s);
2157 PyStructSequence_SET_ITEM(v, index+6, ns_total);
2158 s = NULL;
2159 float_s = NULL;
2160 ns_total = NULL;
2161 exit:
2162 Py_XDECREF(s);
2163 Py_XDECREF(ns_fractional);
2164 Py_XDECREF(s_in_ns);
2165 Py_XDECREF(ns_total);
2166 Py_XDECREF(float_s);
1532 } 2167 }
1533 2168
1534 /* pack a system stat C structure into the Python stat tuple 2169 /* pack a system stat C structure into the Python stat tuple
1535 (used by posix_stat() and posix_fstat()) */ 2170 (used by posix_stat() and posix_fstat()) */
1536 static PyObject* 2171 static PyObject*
1537 _pystat_fromstructstat(STRUCT_STAT *st) 2172 _pystat_fromstructstat(STRUCT_STAT *st)
1538 { 2173 {
1539 unsigned long ansec, mnsec, cnsec; 2174 unsigned long ansec, mnsec, cnsec;
1540 PyObject *v = PyStructSequence_New(&StatResultType); 2175 PyObject *v = PyStructSequence_New(&StatResultType);
1541 if (v == NULL) 2176 if (v == NULL)
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1624 #endif 2259 #endif
1625 2260
1626 if (PyErr_Occurred()) { 2261 if (PyErr_Occurred()) {
1627 Py_DECREF(v); 2262 Py_DECREF(v);
1628 return NULL; 2263 return NULL;
1629 } 2264 }
1630 2265
1631 return v; 2266 return v;
1632 } 2267 }
1633 2268
2269 /* POSIX methods */
2270
2271
2272 static PyObject *
2273 posix_do_stat(char *function_name, path_t *path,
2274 int dir_fd, int follow_symlinks)
2275 {
2276 STRUCT_STAT st;
2277 int result;
2278
2279 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2280 if (follow_symlinks_specified(function_name, follow_symlinks))
2281 return NULL;
2282 #endif
2283
2284 if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2285 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2286 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2287 return NULL;
2288
2289 Py_BEGIN_ALLOW_THREADS
2290 if (path->fd != -1)
2291 result = FSTAT(path->fd, &st);
2292 else
1634 #ifdef MS_WINDOWS 2293 #ifdef MS_WINDOWS
1635 2294 if (path->wide) {
1636 /* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\, 2295 if (follow_symlinks)
1637 where / can be used in place of \ and the trailing slash is optional. 2296 result = win32_stat_w(path->wide, &st);
1638 Both SERVER and SHARE must have at least one character. 2297 else
1639 */ 2298 result = win32_lstat_w(path->wide, &st);
1640 2299 }
1641 #define ISSLASHA(c) ((c) == '\\' || (c) == '/') 2300 else
1642 #define ISSLASHW(c) ((c) == L'\\' || (c) == L'/') 2301 #endif
1643 #ifndef ARRAYSIZE 2302 #if defined(HAVE_LSTAT) || defined(MS_WINDOWS)
1644 #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) 2303 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
1645 #endif 2304 result = LSTAT(path->narrow, &st);
1646 2305 else
1647 static BOOL 2306 #endif
1648 IsUNCRootA(char *path, int pathlen) 2307 #ifdef HAVE_FSTATAT
1649 { 2308 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
1650 #define ISSLASH ISSLASHA 2309 result = fstatat(dir_fd, path->narrow, &st,
1651 2310 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
1652 int i, share; 2311 else
1653 2312 #endif
1654 if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1])) 2313 result = STAT(path->narrow, &st);
1655 /* minimum UNCRoot is \\x\y */ 2314 Py_END_ALLOW_THREADS
1656 return FALSE; 2315
1657 for (i = 2; i < pathlen ; i++) 2316 if (result != 0)
1658 if (ISSLASH(path[i])) break; 2317 return path_error("stat", path);
1659 if (i == 2 || i == pathlen) 2318
1660 /* do not allow \\\SHARE or \\SERVER */ 2319 return _pystat_fromstructstat(&st);
1661 return FALSE; 2320 }
1662 share = i+1; 2321
1663 for (i = share; i < pathlen; i++) 2322 PyDoc_STRVAR(posix_stat__doc__,
1664 if (ISSLASH(path[i])) break; 2323 "stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result\n\n\
1665 return (i != share && (i == pathlen || i == pathlen-1)); 2324 Perform a stat system call on the given path.\n\
1666 2325 \n\
1667 #undef ISSLASH 2326 path may be specified as either a string or as an open file descriptor.\n\
1668 } 2327 \n\
1669 2328 If dir_fd is not None, it should be a file descriptor open to a directory,\n\
1670 static BOOL 2329 and path should be relative; path will then be relative to that directory.\n\
1671 IsUNCRootW(Py_UNICODE *path, int pathlen) 2330 dir_fd may not be supported on your platform; if it is unavailable, using\n\
1672 { 2331 it will raise a NotImplementedError.\n\
1673 #define ISSLASH ISSLASHW 2332 If follow_symlinks is False, and the last element of the path is a symbolic\n\
1674 2333 link, stat will examine the symbolic link itself instead of the file the\n\
1675 int i, share; 2334 link points to.\n\
1676 2335 It is an error to use dir_fd or follow_symlinks when specifying path as\n\
1677 if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1])) 2336 an open file descriptor.");
1678 /* minimum UNCRoot is \\x\y */ 2337
1679 return FALSE; 2338 static PyObject *
1680 for (i = 2; i < pathlen ; i++) 2339 posix_stat(PyObject *self, PyObject *args, PyObject *kwargs)
1681 if (ISSLASH(path[i])) break; 2340 {
1682 if (i == 2 || i == pathlen) 2341 static char *keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
1683 /* do not allow \\\SHARE or \\SERVER */ 2342 path_t path;
1684 return FALSE; 2343 int dir_fd = DEFAULT_DIR_FD;
1685 share = i+1; 2344 int follow_symlinks = 1;
1686 for (i = share; i < pathlen; i++) 2345 PyObject *return_value;
1687 if (ISSLASH(path[i])) break; 2346
1688 return (i != share && (i == pathlen || i == pathlen-1)); 2347 memset(&path, 0, sizeof(path));
1689 2348 path.allow_fd = 1;
1690 #undef ISSLASH 2349 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", keywords,
1691 } 2350 path_converter, &path,
1692 #endif /* MS_WINDOWS */ 2351 #ifdef HAVE_FSTATAT
1693 2352 dir_fd_converter, &dir_fd,
1694 static PyObject *
1695 posix_do_stat(PyObject *self, PyObject *args,
1696 char *format,
1697 #ifdef __VMS
1698 int (*statfunc)(const char *, STRUCT_STAT *, ...),
1699 #else 2353 #else
1700 int (*statfunc)(const char *, STRUCT_STAT *), 2354 dir_fd_unavailable, &dir_fd,
1701 #endif 2355 #endif
1702 char *wformat, 2356 &follow_symlinks))
1703 int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *)) 2357 return NULL;
1704 { 2358 return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
1705 STRUCT_STAT st; 2359 path_cleanup(&path);
1706 PyObject *opath; 2360 return return_value;
1707 char *path; 2361 }
1708 int res; 2362
1709 PyObject *result; 2363 PyDoc_STRVAR(posix_lstat__doc__,
1710 2364 "lstat(path, *, dir_fd=None) -> stat result\n\n\
1711 #ifdef MS_WINDOWS 2365 Like stat(), but do not follow symbolic links.\n\
1712 PyUnicodeObject *po; 2366 Equivalent to stat(path, follow_symlinks=False).");
1713 if (PyArg_ParseTuple(args, wformat, &po)) { 2367
1714 Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po); 2368 static PyObject *
1715 2369 posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs)
1716 Py_BEGIN_ALLOW_THREADS 2370 {
1717 /* PyUnicode_AS_UNICODE result OK without 2371 static char *keywords[] = {"path", "dir_fd", NULL};
1718 thread lock as it is a simple dereference. */ 2372 path_t path;
1719 res = wstatfunc(wpath, &st); 2373 int dir_fd = DEFAULT_DIR_FD;
1720 Py_END_ALLOW_THREADS 2374 int follow_symlinks = 0;
1721 2375 PyObject *return_value;
1722 if (res != 0) 2376
1723 return win32_error_unicode("stat", wpath); 2377 memset(&path, 0, sizeof(path));
1724 return _pystat_fromstructstat(&st); 2378 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", keywords,
1725 } 2379 path_converter, &path,
1726 /* Drop the argument parsing error as narrow strings 2380 #ifdef HAVE_FSTATAT
1727 are also valid. */ 2381 dir_fd_converter, &dir_fd
1728 PyErr_Clear();
1729 #endif
1730
1731 if (!PyArg_ParseTuple(args, format,
1732 PyUnicode_FSConverter, &opath))
1733 return NULL;
1734 path = PyBytes_AsString(opath);
1735 Py_BEGIN_ALLOW_THREADS
1736 res = (*statfunc)(path, &st);
1737 Py_END_ALLOW_THREADS
1738
1739 if (res != 0) {
1740 #ifdef MS_WINDOWS
1741 result = win32_error("stat", path);
1742 #else 2382 #else
1743 result = posix_error_with_filename(path); 2383 dir_fd_unavailable, &dir_fd
1744 #endif 2384 #endif
1745 } 2385 ))
1746 else 2386 return NULL;
1747 result = _pystat_fromstructstat(&st); 2387 return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
1748 2388 path_cleanup(&path);
1749 Py_DECREF(opath); 2389 return return_value;
1750 return result; 2390 }
1751 }
1752
1753 /* POSIX methods */
1754 2391
1755 PyDoc_STRVAR(posix_access__doc__, 2392 PyDoc_STRVAR(posix_access__doc__,
1756 "access(path, mode) -> True if granted, False otherwise\n\n\ 2393 "access(path, mode, *, dir_fd=None, effective_ids=False,\
1757 Use the real uid/gid to test for access to a path. Note that most\n\ 2394 follow_symlinks=True)\n\n\
1758 operations will use the effective uid/gid, therefore this routine can\n\ 2395 Use the real uid/gid to test for access to a path. Returns True if granted,\n\
1759 be used in a suid/sgid environment to test if the invoking user has the\n\ 2396 False otherwise.\n\
1760 specified access to the path. The mode argument can be F_OK to test\n\ 2397 \n\
1761 existence, or the inclusive-OR of R_OK, W_OK, and X_OK."); 2398 If dir_fd is not None, it should be a file descriptor open to a directory,\n\
1762 2399 and path should be relative; path will then be relative to that directory.\n\
1763 static PyObject * 2400 If effective_ids is True, access will use the effective uid/gid instead of\n\
1764 posix_access(PyObject *self, PyObject *args) 2401 the real uid/gid.\n\
1765 { 2402 If follow_symlinks is False, and the last element of the path is a symbolic\n\
1766 PyObject *opath; 2403 link, access will examine the symbolic link itself instead of the file the\n\
1767 char *path; 2404 link points to.\n\
2405 dir_fd, effective_ids, and follow_symlinks may not be implemented\n\
2406 on your platform. If they are unavailable, using them will raise a\n\
2407 NotImplementedError.\n\
2408 \n\
2409 Note that most operations will use the effective uid/gid, therefore this\n\
2410 routine can be used in a suid/sgid environment to test if the invoking user\n\
2411 has the specified access to the path.\n\
2412 The mode argument can be F_OK to test existence, or the inclusive-OR\n\
2413 of R_OK, W_OK, and X_OK.");
2414
2415 static PyObject *
2416 posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
2417 {
2418 static char *keywords[] = {"path", "mode", "dir_fd", "effective_ids",
2419 "follow_symlinks", NULL};
2420 path_t path;
1768 int mode; 2421 int mode;
2422 int dir_fd = DEFAULT_DIR_FD;
2423 int effective_ids = 0;
2424 int follow_symlinks = 1;
2425 PyObject *return_value = NULL;
1769 2426
1770 #ifdef MS_WINDOWS 2427 #ifdef MS_WINDOWS
1771 DWORD attr; 2428 DWORD attr;
1772 PyUnicodeObject *po; 2429 #else
1773 if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) { 2430 int result;
1774 Py_BEGIN_ALLOW_THREADS 2431 #endif
1775 /* PyUnicode_AS_UNICODE OK without thread lock as 2432
1776 it is a simple dereference. */ 2433 memset(&path, 0, sizeof(path));
1777 attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po)); 2434 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&pp:access", keywords,
1778 Py_END_ALLOW_THREADS 2435 path_converter, &path, &mode,
1779 goto finish; 2436 #ifdef HAVE_FACCESSAT
1780 } 2437 dir_fd_converter, &dir_fd,
1781 /* Drop the argument parsing error as narrow strings 2438 #else
1782 are also valid. */ 2439 dir_fd_unavailable, &dir_fd,
1783 PyErr_Clear(); 2440 #endif
1784 if (!PyArg_ParseTuple(args, "O&i:access", 2441 &effective_ids, &follow_symlinks))
1785 PyUnicode_FSConverter, &opath, &mode)) 2442 return NULL;
1786 return NULL; 2443
1787 path = PyBytes_AsString(opath); 2444 #ifndef HAVE_FACCESSAT
2445 if (follow_symlinks_specified("access", follow_symlinks))
2446 goto exit;
2447
2448 if (effective_ids) {
2449 argument_unavailable_error("access", "effective_ids");
2450 goto exit;
2451 }
2452 #endif
2453
2454 #ifdef MS_WINDOWS
1788 Py_BEGIN_ALLOW_THREADS 2455 Py_BEGIN_ALLOW_THREADS
1789 attr = GetFileAttributesA(path); 2456 if (path.wide != NULL)
2457 attr = GetFileAttributesW(path.wide);
2458 else
2459 attr = GetFileAttributesA(path.narrow);
1790 Py_END_ALLOW_THREADS 2460 Py_END_ALLOW_THREADS
1791 Py_DECREF(opath); 2461
1792 finish: 2462 /*
1793 if (attr == 0xFFFFFFFF) 2463 * Access is possible if
1794 /* File does not exist, or cannot read attributes */ 2464 * * we didn't get a -1, and
1795 return PyBool_FromLong(0); 2465 * * write access wasn't requested,
1796 /* Access is possible if either write access wasn't requested, or 2466 * * or the file isn't read-only,
1797 the file isn't read-only, or if it's a directory, as there are 2467 * * or it's a directory.
1798 no read-only directories on Windows. */ 2468 * (Directories cannot be read-only on Windows.)
1799 return PyBool_FromLong(!(mode & 2) 2469 */
1800 || !(attr & FILE_ATTRIBUTE_READONLY) 2470 return_value = PyBool_FromLong(
1801 || (attr & FILE_ATTRIBUTE_DIRECTORY)); 2471 (attr != 0xFFFFFFFF) &&
2472 (!(mode & 2) ||
2473 !(attr & FILE_ATTRIBUTE_READONLY) ||
2474 (attr & FILE_ATTRIBUTE_DIRECTORY)));
1802 #else 2475 #else
1803 int res; 2476
1804 if (!PyArg_ParseTuple(args, "O&i:access",
1805 PyUnicode_FSConverter, &opath, &mode))
1806 return NULL;
1807 path = PyBytes_AsString(opath);
1808 Py_BEGIN_ALLOW_THREADS 2477 Py_BEGIN_ALLOW_THREADS
1809 res = access(path, mode); 2478 #ifdef HAVE_FACCESSAT
2479 if ((dir_fd != DEFAULT_DIR_FD) ||
2480 effective_ids ||
2481 !follow_symlinks) {
2482 int flags = 0;
2483 if (!follow_symlinks)
2484 flags |= AT_SYMLINK_NOFOLLOW;
2485 if (effective_ids)
2486 flags |= AT_EACCESS;
2487 result = faccessat(dir_fd, path.narrow, mode, flags);
2488 }
2489 else
2490 #endif
2491 result = access(path.narrow, mode);
1810 Py_END_ALLOW_THREADS 2492 Py_END_ALLOW_THREADS
1811 Py_DECREF(opath); 2493 return_value = PyBool_FromLong(!result);
1812 return PyBool_FromLong(res == 0); 2494 #endif
1813 #endif 2495
2496 #ifndef HAVE_FACCESSAT
2497 exit:
2498 #endif
2499 path_cleanup(&path);
2500 return return_value;
1814 } 2501 }
1815 2502
1816 #ifndef F_OK 2503 #ifndef F_OK
1817 #define F_OK 0 2504 #define F_OK 0
1818 #endif 2505 #endif
1819 #ifndef R_OK 2506 #ifndef R_OK
1820 #define R_OK 4 2507 #define R_OK 4
1821 #endif 2508 #endif
1822 #ifndef W_OK 2509 #ifndef W_OK
1823 #define W_OK 2 2510 #define W_OK 2
(...skipping 22 matching lines...) Expand all
1846 ret = ttyname(); 2533 ret = ttyname();
1847 } 2534 }
1848 else { 2535 else {
1849 ret = NULL; 2536 ret = NULL;
1850 } 2537 }
1851 #else 2538 #else
1852 ret = ttyname(id); 2539 ret = ttyname(id);
1853 #endif 2540 #endif
1854 if (ret == NULL) 2541 if (ret == NULL)
1855 return posix_error(); 2542 return posix_error();
1856 return PyUnicode_FromString(ret); 2543 return PyUnicode_DecodeFSDefault(ret);
1857 } 2544 }
1858 #endif 2545 #endif
1859 2546
1860 #ifdef HAVE_CTERMID 2547 #ifdef HAVE_CTERMID
1861 PyDoc_STRVAR(posix_ctermid__doc__, 2548 PyDoc_STRVAR(posix_ctermid__doc__,
1862 "ctermid() -> string\n\n\ 2549 "ctermid() -> string\n\n\
1863 Return the name of the controlling terminal for this process."); 2550 Return the name of the controlling terminal for this process.");
1864 2551
1865 static PyObject * 2552 static PyObject *
1866 posix_ctermid(PyObject *self, PyObject *noargs) 2553 posix_ctermid(PyObject *self, PyObject *noargs)
1867 { 2554 {
1868 char *ret; 2555 char *ret;
1869 char buffer[L_ctermid]; 2556 char buffer[L_ctermid];
1870 2557
1871 #ifdef USE_CTERMID_R 2558 #ifdef USE_CTERMID_R
1872 ret = ctermid_r(buffer); 2559 ret = ctermid_r(buffer);
1873 #else 2560 #else
1874 ret = ctermid(buffer); 2561 ret = ctermid(buffer);
1875 #endif 2562 #endif
1876 if (ret == NULL) 2563 if (ret == NULL)
1877 return posix_error(); 2564 return posix_error();
1878 return PyUnicode_FromString(buffer); 2565 return PyUnicode_DecodeFSDefault(buffer);
1879 } 2566 }
1880 #endif 2567 #endif
1881 2568
1882 PyDoc_STRVAR(posix_chdir__doc__, 2569 PyDoc_STRVAR(posix_chdir__doc__,
1883 "chdir(path)\n\n\ 2570 "chdir(path)\n\n\
1884 Change the current working directory to the specified path."); 2571 Change the current working directory to the specified path.\n\
1885 2572 \n\
1886 static PyObject * 2573 path may always be specified as a string.\n\
1887 posix_chdir(PyObject *self, PyObject *args) 2574 On some platforms, path may also be specified as an open file descriptor.\n\
1888 { 2575 If this functionality is unavailable, using it raises an exception.");
2576
2577 static PyObject *
2578 posix_chdir(PyObject *self, PyObject *args, PyObject *kwargs)
2579 {
2580 path_t path;
2581 int result;
2582 PyObject *return_value = NULL;
2583 static char *keywords[] = {"path", NULL};
2584
2585 memset(&path, 0, sizeof(path));
2586 #ifdef HAVE_FCHDIR
2587 path.allow_fd = 1;
2588 #endif
2589 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", keywords,
2590 path_converter, &path
2591 ))
2592 return NULL;
2593
2594 Py_BEGIN_ALLOW_THREADS
1889 #ifdef MS_WINDOWS 2595 #ifdef MS_WINDOWS
1890 return win32_1str(args, "chdir", "y:chdir", win32_chdir, "U:chdir", win32_wc hdir); 2596 if (path.wide)
2597 result = win32_wchdir(path.wide);
2598 else
2599 result = win32_chdir(path.narrow);
2600 result = !result; /* on unix, success = 0, on windows, success = !0 */
1891 #elif defined(PYOS_OS2) && defined(PYCC_GCC) 2601 #elif defined(PYOS_OS2) && defined(PYCC_GCC)
1892 return posix_1str(args, "O&:chdir", _chdir2); 2602 result = _chdir2(path.narrow);
1893 #elif defined(__VMS)
1894 return posix_1str(args, "O&:chdir", (int (*)(const char *))chdir);
1895 #else 2603 #else
1896 return posix_1str(args, "O&:chdir", chdir); 2604 #ifdef HAVE_FCHDIR
1897 #endif 2605 if (path.fd != -1)
2606 result = fchdir(path.fd);
2607 else
2608 #endif
2609 result = chdir(path.narrow);
2610 #endif
2611 Py_END_ALLOW_THREADS
2612
2613 if (result) {
2614 return_value = path_error("chdir", &path);
2615 goto exit;
2616 }
2617
2618 return_value = Py_None;
2619 Py_INCREF(Py_None);
2620
2621 exit:
2622 path_cleanup(&path);
2623 return return_value;
1898 } 2624 }
1899 2625
1900 #ifdef HAVE_FCHDIR 2626 #ifdef HAVE_FCHDIR
1901 PyDoc_STRVAR(posix_fchdir__doc__, 2627 PyDoc_STRVAR(posix_fchdir__doc__,
1902 "fchdir(fildes)\n\n\ 2628 "fchdir(fd)\n\n\
1903 Change to the directory of the given file descriptor. fildes must be\n\ 2629 Change to the directory of the given file descriptor. fd must be\n\
1904 opened on a directory, not a file."); 2630 opened on a directory, not a file. Equivalent to os.chdir(fd).");
1905 2631
1906 static PyObject * 2632 static PyObject *
1907 posix_fchdir(PyObject *self, PyObject *fdobj) 2633 posix_fchdir(PyObject *self, PyObject *fdobj)
1908 { 2634 {
1909 return posix_fildes(fdobj, fchdir); 2635 return posix_fildes(fdobj, fchdir);
1910 } 2636 }
1911 #endif /* HAVE_FCHDIR */ 2637 #endif /* HAVE_FCHDIR */
1912 2638
1913 2639
1914 PyDoc_STRVAR(posix_chmod__doc__, 2640 PyDoc_STRVAR(posix_chmod__doc__,
1915 "chmod(path, mode)\n\n\ 2641 "chmod(path, mode, *, dir_fd=None, follow_symlinks=True)\n\n\
1916 Change the access permissions of a file."); 2642 Change the access permissions of a file.\n\
1917 2643 \n\
1918 static PyObject * 2644 path may always be specified as a string.\n\
1919 posix_chmod(PyObject *self, PyObject *args) 2645 On some platforms, path may also be specified as an open file descriptor.\n\
1920 { 2646 If this functionality is unavailable, using it raises an exception.\n\
1921 PyObject *opath = NULL; 2647 If dir_fd is not None, it should be a file descriptor open to a directory,\n\
1922 char *path = NULL; 2648 and path should be relative; path will then be relative to that directory.\n\
1923 int i; 2649 If follow_symlinks is False, and the last element of the path is a symbolic\n\
1924 int res; 2650 link, chmod will modify the symbolic link itself instead of the file the\n\
2651 link points to.\n\
2652 It is an error to use dir_fd or follow_symlinks when specifying path as\n\
2653 an open file descriptor.\n\
2654 dir_fd and follow_symlinks may not be implemented on your platform.\n\
2655 If they are unavailable, using them will raise a NotImplementedError.");
2656
2657 static PyObject *
2658 posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
2659 {
2660 path_t path;
2661 int mode;
2662 int dir_fd = DEFAULT_DIR_FD;
2663 int follow_symlinks = 1;
2664 int result;
2665 PyObject *return_value = NULL;
2666 static char *keywords[] = {"path", "mode", "dir_fd",
2667 "follow_symlinks", NULL};
2668
1925 #ifdef MS_WINDOWS 2669 #ifdef MS_WINDOWS
1926 DWORD attr; 2670 DWORD attr;
1927 PyUnicodeObject *po; 2671 #endif
1928 if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) { 2672
1929 Py_BEGIN_ALLOW_THREADS 2673 #ifdef HAVE_FCHMODAT
1930 attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po)); 2674 int fchmodat_nofollow_unsupported = 0;
1931 if (attr != 0xFFFFFFFF) { 2675 #endif
1932 if (i & _S_IWRITE) 2676
1933 attr &= ~FILE_ATTRIBUTE_READONLY; 2677 memset(&path, 0, sizeof(path));
1934 else 2678 #ifdef HAVE_FCHMOD
1935 attr |= FILE_ATTRIBUTE_READONLY; 2679 path.allow_fd = 1;
1936 res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr); 2680 #endif
1937 } 2681 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", keywords,
1938 else 2682 path_converter, &path,
1939 res = 0; 2683 &mode,
1940 Py_END_ALLOW_THREADS 2684 #ifdef HAVE_FCHMODAT
1941 if (!res) 2685 dir_fd_converter, &dir_fd,
1942 return win32_error_unicode("chmod", 2686 #else
1943 PyUnicode_AS_UNICODE(po)); 2687 dir_fd_unavailable, &dir_fd,
1944 Py_INCREF(Py_None); 2688 #endif
1945 return Py_None; 2689 &follow_symlinks))
1946 } 2690 return NULL;
1947 /* Drop the argument parsing error as narrow strings 2691
1948 are also valid. */ 2692 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
1949 PyErr_Clear(); 2693 if (follow_symlinks_specified("chmod", follow_symlinks))
1950 2694 goto exit;
1951 if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter, 2695 #endif
1952 &opath, &i)) 2696
1953 return NULL; 2697 #ifdef MS_WINDOWS
1954 path = PyBytes_AsString(opath);
1955 Py_BEGIN_ALLOW_THREADS 2698 Py_BEGIN_ALLOW_THREADS
1956 attr = GetFileAttributesA(path); 2699 if (path.wide)
1957 if (attr != 0xFFFFFFFF) { 2700 attr = GetFileAttributesW(path.wide);
1958 if (i & _S_IWRITE) 2701 else
2702 attr = GetFileAttributesA(path.narrow);
2703 if (attr == 0xFFFFFFFF)
2704 result = 0;
2705 else {
2706 if (mode & _S_IWRITE)
1959 attr &= ~FILE_ATTRIBUTE_READONLY; 2707 attr &= ~FILE_ATTRIBUTE_READONLY;
1960 else 2708 else
1961 attr |= FILE_ATTRIBUTE_READONLY; 2709 attr |= FILE_ATTRIBUTE_READONLY;
1962 res = SetFileAttributesA(path, attr); 2710 if (path.wide)
1963 } 2711 result = SetFileAttributesW(path.wide, attr);
2712 else
2713 result = SetFileAttributesA(path.narrow, attr);
2714 }
2715 Py_END_ALLOW_THREADS
2716
2717 if (!result) {
2718 return_value = win32_error_object("chmod", path.object);
2719 goto exit;
2720 }
2721 #else /* MS_WINDOWS */
2722 Py_BEGIN_ALLOW_THREADS
2723 #ifdef HAVE_FCHMOD
2724 if (path.fd != -1)
2725 result = fchmod(path.fd, mode);
1964 else 2726 else
1965 res = 0; 2727 #endif
2728 #ifdef HAVE_LCHMOD
2729 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2730 result = lchmod(path.narrow, mode);
2731 else
2732 #endif
2733 #ifdef HAVE_FCHMODAT
2734 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2735 /*
2736 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
2737 * The documentation specifically shows how to use it,
2738 * and then says it isn't implemented yet.
2739 * (true on linux with glibc 2.15, and openindiana 3.x)
2740 *
2741 * Once it is supported, os.chmod will automatically
2742 * support dir_fd and follow_symlinks=False. (Hopefully.)
2743 * Until then, we need to be careful what exception we raise.
2744 */
2745 result = fchmodat(dir_fd, path.narrow, mode,
2746 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2747 /*
2748 * But wait! We can't throw the exception without allowing threads,
2749 * and we can't do that in this nested scope. (Macro trickery, sigh.)
2750 */
2751 fchmodat_nofollow_unsupported =
2752 result &&
2753 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
2754 !follow_symlinks;
2755 }
2756 else
2757 #endif
2758 result = chmod(path.narrow, mode);
1966 Py_END_ALLOW_THREADS 2759 Py_END_ALLOW_THREADS
1967 if (!res) { 2760
1968 win32_error("chmod", path); 2761 if (result) {
1969 Py_DECREF(opath); 2762 #ifdef HAVE_FCHMODAT
1970 return NULL; 2763 if (fchmodat_nofollow_unsupported) {
1971 } 2764 if (dir_fd != DEFAULT_DIR_FD)
1972 Py_DECREF(opath); 2765 dir_fd_and_follow_symlinks_invalid("chmod",
2766 dir_fd, follow_symlinks);
2767 else
2768 follow_symlinks_specified("chmod", follow_symlinks);
2769 }
2770 else
2771 #endif
2772 return_value = path_error("chmod", &path);
2773 goto exit;
2774 }
2775 #endif
2776
1973 Py_INCREF(Py_None); 2777 Py_INCREF(Py_None);
1974 return Py_None; 2778 return_value = Py_None;
1975 #else /* MS_WINDOWS */ 2779 exit:
1976 if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter, 2780 path_cleanup(&path);
1977 &opath, &i)) 2781 return return_value;
1978 return NULL; 2782 }
1979 path = PyBytes_AsString(opath); 2783
1980 Py_BEGIN_ALLOW_THREADS
1981 res = chmod(path, i);
1982 Py_END_ALLOW_THREADS
1983 if (res < 0)
1984 return posix_error_with_allocated_filename(opath);
1985 Py_DECREF(opath);
1986 Py_INCREF(Py_None);
1987 return Py_None;
1988 #endif
1989 }
1990 2784
1991 #ifdef HAVE_FCHMOD 2785 #ifdef HAVE_FCHMOD
1992 PyDoc_STRVAR(posix_fchmod__doc__, 2786 PyDoc_STRVAR(posix_fchmod__doc__,
1993 "fchmod(fd, mode)\n\n\ 2787 "fchmod(fd, mode)\n\n\
1994 Change the access permissions of the file given by file\n\ 2788 Change the access permissions of the file given by file\n\
1995 descriptor fd."); 2789 descriptor fd. Equivalent to os.chmod(fd, mode).");
1996 2790
1997 static PyObject * 2791 static PyObject *
1998 posix_fchmod(PyObject *self, PyObject *args) 2792 posix_fchmod(PyObject *self, PyObject *args)
1999 { 2793 {
2000 int fd, mode, res; 2794 int fd, mode, res;
2001 if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode)) 2795 if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
2002 return NULL; 2796 return NULL;
2003 Py_BEGIN_ALLOW_THREADS 2797 Py_BEGIN_ALLOW_THREADS
2004 res = fchmod(fd, mode); 2798 res = fchmod(fd, mode);
2005 Py_END_ALLOW_THREADS 2799 Py_END_ALLOW_THREADS
2006 if (res < 0) 2800 if (res < 0)
2007 return posix_error(); 2801 return posix_error();
2008 Py_RETURN_NONE; 2802 Py_RETURN_NONE;
2009 } 2803 }
2010 #endif /* HAVE_FCHMOD */ 2804 #endif /* HAVE_FCHMOD */
2011 2805
2012 #ifdef HAVE_LCHMOD 2806 #ifdef HAVE_LCHMOD
2013 PyDoc_STRVAR(posix_lchmod__doc__, 2807 PyDoc_STRVAR(posix_lchmod__doc__,
2014 "lchmod(path, mode)\n\n\ 2808 "lchmod(path, mode)\n\n\
2015 Change the access permissions of a file. If path is a symlink, this\n\ 2809 Change the access permissions of a file. If path is a symlink, this\n\
2016 affects the link itself rather than the target."); 2810 affects the link itself rather than the target.\n\
2811 Equivalent to chmod(path, mode, follow_symlinks=False).");
2017 2812
2018 static PyObject * 2813 static PyObject *
2019 posix_lchmod(PyObject *self, PyObject *args) 2814 posix_lchmod(PyObject *self, PyObject *args)
2020 { 2815 {
2021 PyObject *opath; 2816 PyObject *opath;
2022 char *path; 2817 char *path;
2023 int i; 2818 int i;
2024 int res; 2819 int res;
2025 if (!PyArg_ParseTuple(args, "O&i:lchmod", PyUnicode_FSConverter, 2820 if (!PyArg_ParseTuple(args, "O&i:lchmod", PyUnicode_FSConverter,
2026 &opath, &i)) 2821 &opath, &i))
2027 return NULL; 2822 return NULL;
2028 path = PyBytes_AsString(opath); 2823 path = PyBytes_AsString(opath);
2029 Py_BEGIN_ALLOW_THREADS 2824 Py_BEGIN_ALLOW_THREADS
2030 res = lchmod(path, i); 2825 res = lchmod(path, i);
2031 Py_END_ALLOW_THREADS 2826 Py_END_ALLOW_THREADS
2032 if (res < 0) 2827 if (res < 0)
2033 return posix_error_with_allocated_filename(opath); 2828 return posix_error_with_allocated_filename(opath);
2034 Py_DECREF(opath); 2829 Py_DECREF(opath);
2035 Py_RETURN_NONE; 2830 Py_RETURN_NONE;
2036 } 2831 }
2037 #endif /* HAVE_LCHMOD */ 2832 #endif /* HAVE_LCHMOD */
2038 2833
2039 2834
2040 #ifdef HAVE_CHFLAGS 2835 #ifdef HAVE_CHFLAGS
2041 PyDoc_STRVAR(posix_chflags__doc__, 2836 PyDoc_STRVAR(posix_chflags__doc__,
2042 "chflags(path, flags)\n\n\ 2837 "chflags(path, flags, *, follow_symlinks=True)\n\n\
2043 Set file flags."); 2838 Set file flags.\n\
2044 2839 \n\
2045 static PyObject * 2840 If follow_symlinks is False, and the last element of the path is a symbolic\n\
2046 posix_chflags(PyObject *self, PyObject *args) 2841 link, chflags will change flags on the symbolic link itself instead of the\n\
2047 { 2842 file the link points to.\n\
2048 PyObject *opath; 2843 follow_symlinks may not be implemented on your platform. If it is\n\
2049 char *path; 2844 unavailable, using it will raise a NotImplementedError.");
2845
2846 static PyObject *
2847 posix_chflags(PyObject *self, PyObject *args, PyObject *kwargs)
2848 {
2849 path_t path;
2050 unsigned long flags; 2850 unsigned long flags;
2051 int res; 2851 int follow_symlinks = 1;
2052 if (!PyArg_ParseTuple(args, "O&k:chflags", 2852 int result;
2053 PyUnicode_FSConverter, &opath, &flags)) 2853 PyObject *return_value;
2054 return NULL; 2854 static char *keywords[] = {"path", "flags", "follow_symlinks", NULL};
2055 path = PyBytes_AsString(opath); 2855
2856 memset(&path, 0, sizeof(path));
2857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|$i:chflags", keywords,
2858 path_converter, &path,
2859 &flags, &follow_symlinks))
2860 return NULL;
2861
2862 #ifndef HAVE_LCHFLAGS
2863 if (follow_symlinks_specified("chflags", follow_symlinks))
2864 goto exit;
2865 #endif
2866
2056 Py_BEGIN_ALLOW_THREADS 2867 Py_BEGIN_ALLOW_THREADS
2057 res = chflags(path, flags); 2868 #ifdef HAVE_LCHFLAGS
2869 if (!follow_symlinks)
2870 result = lchflags(path.narrow, flags);
2871 else
2872 #endif
2873 result = chflags(path.narrow, flags);
2058 Py_END_ALLOW_THREADS 2874 Py_END_ALLOW_THREADS
2059 if (res < 0) 2875
2060 return posix_error_with_allocated_filename(opath); 2876 if (result) {
2061 Py_DECREF(opath); 2877 return_value = path_posix_error("chflags", &path);
2878 goto exit;
2879 }
2880
2881 return_value = Py_None;
2062 Py_INCREF(Py_None); 2882 Py_INCREF(Py_None);
2063 return Py_None; 2883
2884 exit:
2885 path_cleanup(&path);
2886 return return_value;
2064 } 2887 }
2065 #endif /* HAVE_CHFLAGS */ 2888 #endif /* HAVE_CHFLAGS */
2066 2889
2067 #ifdef HAVE_LCHFLAGS 2890 #ifdef HAVE_LCHFLAGS
2068 PyDoc_STRVAR(posix_lchflags__doc__, 2891 PyDoc_STRVAR(posix_lchflags__doc__,
2069 "lchflags(path, flags)\n\n\ 2892 "lchflags(path, flags)\n\n\
2070 Set file flags.\n\ 2893 Set file flags.\n\
2071 This function will not follow symbolic links."); 2894 This function will not follow symbolic links.\n\
2895 Equivalent to chflags(path, flags, follow_symlinks=False).");
2072 2896
2073 static PyObject * 2897 static PyObject *
2074 posix_lchflags(PyObject *self, PyObject *args) 2898 posix_lchflags(PyObject *self, PyObject *args)
2075 { 2899 {
2076 PyObject *opath; 2900 PyObject *opath;
2077 char *path; 2901 char *path;
2078 unsigned long flags; 2902 unsigned long flags;
2079 int res; 2903 int res;
2080 if (!PyArg_ParseTuple(args, "O&k:lchflags", 2904 if (!PyArg_ParseTuple(args, "O&k:lchflags",
2081 PyUnicode_FSConverter, &opath, &flags)) 2905 PyUnicode_FSConverter, &opath, &flags))
(...skipping 23 matching lines...) Expand all
2105 #endif 2929 #endif
2106 2930
2107 #ifdef HAVE_FSYNC 2931 #ifdef HAVE_FSYNC
2108 PyDoc_STRVAR(posix_fsync__doc__, 2932 PyDoc_STRVAR(posix_fsync__doc__,
2109 "fsync(fildes)\n\n\ 2933 "fsync(fildes)\n\n\
2110 force write of file with filedescriptor to disk."); 2934 force write of file with filedescriptor to disk.");
2111 2935
2112 static PyObject * 2936 static PyObject *
2113 posix_fsync(PyObject *self, PyObject *fdobj) 2937 posix_fsync(PyObject *self, PyObject *fdobj)
2114 { 2938 {
2115 return posix_fildes(fdobj, fsync); 2939 return posix_fildes(fdobj, fsync);
2116 } 2940 }
2117 #endif /* HAVE_FSYNC */ 2941 #endif /* HAVE_FSYNC */
2942
2943 #ifdef HAVE_SYNC
2944 PyDoc_STRVAR(posix_sync__doc__,
2945 "sync()\n\n\
2946 Force write of everything to disk.");
2947
2948 static PyObject *
2949 posix_sync(PyObject *self, PyObject *noargs)
2950 {
2951 Py_BEGIN_ALLOW_THREADS
2952 sync();
2953 Py_END_ALLOW_THREADS
2954 Py_RETURN_NONE;
2955 }
2956 #endif
2118 2957
2119 #ifdef HAVE_FDATASYNC 2958 #ifdef HAVE_FDATASYNC
2120 2959
2121 #ifdef __hpux 2960 #ifdef __hpux
2122 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ 2961 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
2123 #endif 2962 #endif
2124 2963
2125 PyDoc_STRVAR(posix_fdatasync__doc__, 2964 PyDoc_STRVAR(posix_fdatasync__doc__,
2126 "fdatasync(fildes)\n\n\ 2965 "fdatasync(fildes)\n\n\
2127 force write of file with filedescriptor to disk.\n\ 2966 force write of file with filedescriptor to disk.\n\
2128 does not force update of metadata."); 2967 does not force update of metadata.");
2129 2968
2130 static PyObject * 2969 static PyObject *
2131 posix_fdatasync(PyObject *self, PyObject *fdobj) 2970 posix_fdatasync(PyObject *self, PyObject *fdobj)
2132 { 2971 {
2133 return posix_fildes(fdobj, fdatasync); 2972 return posix_fildes(fdobj, fdatasync);
2134 } 2973 }
2135 #endif /* HAVE_FDATASYNC */ 2974 #endif /* HAVE_FDATASYNC */
2136 2975
2137 2976
2138 #ifdef HAVE_CHOWN 2977 #ifdef HAVE_CHOWN
2139 PyDoc_STRVAR(posix_chown__doc__, 2978 PyDoc_STRVAR(posix_chown__doc__,
2140 "chown(path, uid, gid)\n\n\ 2979 "chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n\n\
2141 Change the owner and group id of path to the numeric uid and gid."); 2980 Change the owner and group id of path to the numeric uid and gid.\n\
2142 2981 \n\
2143 static PyObject * 2982 path may always be specified as a string.\n\
2144 posix_chown(PyObject *self, PyObject *args) 2983 On some platforms, path may also be specified as an open file descriptor.\n\
2145 { 2984 If this functionality is unavailable, using it raises an exception.\n\
2146 PyObject *opath; 2985 If dir_fd is not None, it should be a file descriptor open to a directory,\n\
2147 char *path; 2986 and path should be relative; path will then be relative to that directory.\n\
2148 long uid, gid; 2987 If follow_symlinks is False, and the last element of the path is a symbolic\n\
2149 int res; 2988 link, chown will modify the symbolic link itself instead of the file the\n\
2150 if (!PyArg_ParseTuple(args, "O&ll:chown", 2989 link points to.\n\
2151 PyUnicode_FSConverter, &opath, 2990 It is an error to use dir_fd or follow_symlinks when specifying path as\n\
2152 &uid, &gid)) 2991 an open file descriptor.\n\
2153 return NULL; 2992 dir_fd and follow_symlinks may not be implemented on your platform.\n\
2154 path = PyBytes_AsString(opath); 2993 If they are unavailable, using them will raise a NotImplementedError.");
2994
2995 static PyObject *
2996 posix_chown(PyObject *self, PyObject *args, PyObject *kwargs)
2997 {
2998 path_t path;
2999 long uid_l, gid_l;
3000 uid_t uid;
3001 gid_t gid;
3002 int dir_fd = DEFAULT_DIR_FD;
3003 int follow_symlinks = 1;
3004 int result;
3005 PyObject *return_value = NULL;
3006 static char *keywords[] = {"path", "uid", "gid", "dir_fd",
3007 "follow_symlinks", NULL};
3008
3009 memset(&path, 0, sizeof(path));
3010 #ifdef HAVE_FCHOWN
3011 path.allow_fd = 1;
3012 #endif
3013 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&ll|$O&p:chown", keywords,
3014 path_converter, &path,
3015 &uid_l, &gid_l,
3016 #ifdef HAVE_FCHOWNAT
3017 dir_fd_converter, &dir_fd,
3018 #else
3019 dir_fd_unavailable, &dir_fd,
3020 #endif
3021 &follow_symlinks))
3022 return NULL;
3023
3024 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3025 if (follow_symlinks_specified("chown", follow_symlinks))
3026 goto exit;
3027 #endif
3028 if (dir_fd_and_fd_invalid("chown", dir_fd, path.fd) ||
3029 fd_and_follow_symlinks_invalid("chown", path.fd, follow_symlinks))
3030 goto exit;
3031
3032 #ifdef __APPLE__
3033 /*
3034 * This is for Mac OS X 10.3, which doesn't have lchown.
3035 * (But we still have an lchown symbol because of weak-linking.)
3036 * It doesn't have fchownat either. So there's no possibility
3037 * of a graceful failover.
3038 */
3039 if ((!follow_symlinks) && (lchown == NULL)) {
3040 follow_symlinks_specified("chown", follow_symlinks);
3041 goto exit;
3042 }
3043 #endif
3044
2155 Py_BEGIN_ALLOW_THREADS 3045 Py_BEGIN_ALLOW_THREADS
2156 res = chown(path, (uid_t) uid, (gid_t) gid); 3046 uid = (uid_t)uid_l;
3047 gid = (uid_t)gid_l;
3048 #ifdef HAVE_FCHOWN
3049 if (path.fd != -1)
3050 result = fchown(path.fd, uid, gid);
3051 else
3052 #endif
3053 #ifdef HAVE_LCHOWN
3054 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3055 result = lchown(path.narrow, uid, gid);
3056 else
3057 #endif
3058 #ifdef HAVE_FCHOWNAT
3059 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
3060 result = fchownat(dir_fd, path.narrow, uid, gid,
3061 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3062 else
3063 #endif
3064 result = chown(path.narrow, uid, gid);
2157 Py_END_ALLOW_THREADS 3065 Py_END_ALLOW_THREADS
2158 if (res < 0) 3066
2159 return posix_error_with_allocated_filename(opath); 3067 if (result) {
2160 Py_DECREF(opath); 3068 return_value = path_posix_error("chown", &path);
3069 goto exit;
3070 }
3071
3072 return_value = Py_None;
2161 Py_INCREF(Py_None); 3073 Py_INCREF(Py_None);
2162 return Py_None; 3074
3075 exit:
3076 path_cleanup(&path);
3077 return return_value;
2163 } 3078 }
2164 #endif /* HAVE_CHOWN */ 3079 #endif /* HAVE_CHOWN */
2165 3080
2166 #ifdef HAVE_FCHOWN 3081 #ifdef HAVE_FCHOWN
2167 PyDoc_STRVAR(posix_fchown__doc__, 3082 PyDoc_STRVAR(posix_fchown__doc__,
2168 "fchown(fd, uid, gid)\n\n\ 3083 "fchown(fd, uid, gid)\n\n\
2169 Change the owner and group id of the file given by file descriptor\n\ 3084 Change the owner and group id of the file given by file descriptor\n\
2170 fd to the numeric uid and gid."); 3085 fd to the numeric uid and gid. Equivalent to os.chown(fd, uid, gid).");
2171 3086
2172 static PyObject * 3087 static PyObject *
2173 posix_fchown(PyObject *self, PyObject *args) 3088 posix_fchown(PyObject *self, PyObject *args)
2174 { 3089 {
2175 int fd; 3090 int fd;
2176 long uid, gid; 3091 long uid, gid;
2177 int res; 3092 int res;
2178 if (!PyArg_ParseTuple(args, "ill:chown", &fd, &uid, &gid)) 3093 if (!PyArg_ParseTuple(args, "ill:fchown", &fd, &uid, &gid))
2179 return NULL; 3094 return NULL;
2180 Py_BEGIN_ALLOW_THREADS 3095 Py_BEGIN_ALLOW_THREADS
2181 res = fchown(fd, (uid_t) uid, (gid_t) gid); 3096 res = fchown(fd, (uid_t) uid, (gid_t) gid);
2182 Py_END_ALLOW_THREADS 3097 Py_END_ALLOW_THREADS
2183 if (res < 0) 3098 if (res < 0)
2184 return posix_error(); 3099 return posix_error();
2185 Py_RETURN_NONE; 3100 Py_RETURN_NONE;
2186 } 3101 }
2187 #endif /* HAVE_FCHOWN */ 3102 #endif /* HAVE_FCHOWN */
2188 3103
2189 #ifdef HAVE_LCHOWN 3104 #ifdef HAVE_LCHOWN
2190 PyDoc_STRVAR(posix_lchown__doc__, 3105 PyDoc_STRVAR(posix_lchown__doc__,
2191 "lchown(path, uid, gid)\n\n\ 3106 "lchown(path, uid, gid)\n\n\
2192 Change the owner and group id of path to the numeric uid and gid.\n\ 3107 Change the owner and group id of path to the numeric uid and gid.\n\
2193 This function will not follow symbolic links."); 3108 This function will not follow symbolic links.\n\
3109 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).");
2194 3110
2195 static PyObject * 3111 static PyObject *
2196 posix_lchown(PyObject *self, PyObject *args) 3112 posix_lchown(PyObject *self, PyObject *args)
2197 { 3113 {
2198 PyObject *opath; 3114 PyObject *opath;
2199 char *path; 3115 char *path;
2200 long uid, gid; 3116 long uid, gid;
2201 int res; 3117 int res;
2202 if (!PyArg_ParseTuple(args, "O&ll:lchown", 3118 if (!PyArg_ParseTuple(args, "O&ll:lchown",
2203 PyUnicode_FSConverter, &opath, 3119 PyUnicode_FSConverter, &opath,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2245 return NULL; 3161 return NULL;
2246 } 3162 }
2247 if (!len) { 3163 if (!len) {
2248 if (wbuf2 != wbuf) free(wbuf2); 3164 if (wbuf2 != wbuf) free(wbuf2);
2249 return win32_error("getcwdu", NULL); 3165 return win32_error("getcwdu", NULL);
2250 } 3166 }
2251 resobj = PyUnicode_FromWideChar(wbuf2, len); 3167 resobj = PyUnicode_FromWideChar(wbuf2, len);
2252 if (wbuf2 != wbuf) free(wbuf2); 3168 if (wbuf2 != wbuf) free(wbuf2);
2253 return resobj; 3169 return resobj;
2254 } 3170 }
3171
3172 if (win32_warn_bytes_api())
3173 return NULL;
2255 #endif 3174 #endif
2256 3175
2257 Py_BEGIN_ALLOW_THREADS 3176 Py_BEGIN_ALLOW_THREADS
2258 #if defined(PYOS_OS2) && defined(PYCC_GCC) 3177 #if defined(PYOS_OS2) && defined(PYCC_GCC)
2259 res = _getcwd2(buf, sizeof buf); 3178 res = _getcwd2(buf, sizeof buf);
2260 #else 3179 #else
2261 res = getcwd(buf, sizeof buf); 3180 res = getcwd(buf, sizeof buf);
2262 #endif 3181 #endif
2263 Py_END_ALLOW_THREADS 3182 Py_END_ALLOW_THREADS
2264 if (res == NULL) 3183 if (res == NULL)
(...skipping 17 matching lines...) Expand all
2282 "getcwdb() -> path\n\n\ 3201 "getcwdb() -> path\n\n\
2283 Return a bytes string representing the current working directory."); 3202 Return a bytes string representing the current working directory.");
2284 3203
2285 static PyObject * 3204 static PyObject *
2286 posix_getcwd_bytes(PyObject *self) 3205 posix_getcwd_bytes(PyObject *self)
2287 { 3206 {
2288 return posix_getcwd(1); 3207 return posix_getcwd(1);
2289 } 3208 }
2290 #endif 3209 #endif
2291 3210
3211 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3212 #define HAVE_LINK 1
3213 #endif
2292 3214
2293 #ifdef HAVE_LINK 3215 #ifdef HAVE_LINK
2294 PyDoc_STRVAR(posix_link__doc__, 3216 PyDoc_STRVAR(posix_link__doc__,
2295 "link(src, dst)\n\n\ 3217 "link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True)\n\n\
2296 Create a hard link to a file."); 3218 Create a hard link to a file.\n\
2297 3219 \n\
2298 static PyObject * 3220 If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
2299 posix_link(PyObject *self, PyObject *args) 3221 descriptor open to a directory, and the respective path string (src or dst)\n\
2300 { 3222 should be relative; the path will then be relative to that directory.\n\
2301 return posix_2str(args, "O&O&:link", link); 3223 If follow_symlinks is False, and the last element of src is a symbolic\n\
2302 } 3224 link, link will create a link to the symbolic link itself instead of the\n\
2303 #endif /* HAVE_LINK */ 3225 file the link points to.\n\
3226 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n\
3227 platform. If they are unavailable, using them will raise a\n\
3228 NotImplementedError.");
3229
3230 static PyObject *
3231 posix_link(PyObject *self, PyObject *args, PyObject *kwargs)
3232 {
3233 path_t src, dst;
3234 int src_dir_fd = DEFAULT_DIR_FD;
3235 int dst_dir_fd = DEFAULT_DIR_FD;
3236 int follow_symlinks = 1;
3237 PyObject *return_value = NULL;
3238 static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd",
3239 "follow_symlinks", NULL};
3240 #ifdef MS_WINDOWS
3241 BOOL result;
3242 #else
3243 int result;
3244 #endif
3245
3246 memset(&src, 0, sizeof(src));
3247 memset(&dst, 0, sizeof(dst));
3248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|O&O&p:link", keywords,
3249 path_converter, &src,
3250 path_converter, &dst,
3251 dir_fd_converter, &src_dir_fd,
3252 dir_fd_converter, &dst_dir_fd,
3253 &follow_symlinks))
3254 return NULL;
3255
3256 #ifndef HAVE_LINKAT
3257 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3258 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3259 goto exit;
3260 }
3261 #endif
3262
3263 if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
3264 PyErr_SetString(PyExc_NotImplementedError,
3265 "link: src and dst must be the same type");
3266 goto exit;
3267 }
3268
3269 #ifdef MS_WINDOWS
3270 Py_BEGIN_ALLOW_THREADS
3271 if (src.wide)
3272 result = CreateHardLinkW(dst.wide, src.wide, NULL);
3273 else
3274 result = CreateHardLinkA(dst.narrow, src.narrow, NULL);
3275 Py_END_ALLOW_THREADS
3276
3277 if (!result) {
3278 return_value = win32_error_object("link", dst.object);
3279 goto exit;
3280 }
3281 #else
3282 Py_BEGIN_ALLOW_THREADS
3283 #ifdef HAVE_LINKAT
3284 if ((src_dir_fd != DEFAULT_DIR_FD) ||
3285 (dst_dir_fd != DEFAULT_DIR_FD) ||
3286 (!follow_symlinks))
3287 result = linkat(src_dir_fd, src.narrow,
3288 dst_dir_fd, dst.narrow,
3289 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3290 else
3291 #endif
3292 result = link(src.narrow, dst.narrow);
3293 Py_END_ALLOW_THREADS
3294
3295 if (result) {
3296 return_value = path_error("link", &dst);
3297 goto exit;
3298 }
3299 #endif
3300
3301 return_value = Py_None;
3302 Py_INCREF(Py_None);
3303
3304 exit:
3305 path_cleanup(&src);
3306 path_cleanup(&dst);
3307 return return_value;
3308 }
3309 #endif
3310
2304 3311
2305 3312
2306 PyDoc_STRVAR(posix_listdir__doc__, 3313 PyDoc_STRVAR(posix_listdir__doc__,
2307 "listdir([path]) -> list_of_strings\n\n\ 3314 "listdir(path='.') -> list_of_filenames\n\n\
2308 Return a list containing the names of the entries in the directory.\n\ 3315 Return a list containing the names of the files in the directory.\n\
3316 The list is in arbitrary order. It does not include the special\n\
3317 entries '.' and '..' even if they are present in the directory.\n\
2309 \n\ 3318 \n\
2310 path: path of directory to list (default: '.')\n\ 3319 path can be specified as either str or bytes. If path is bytes,\n\
2311 \n\ 3320 the filenames returned will also be bytes; in all other circumstances\n\
2312 The list is in arbitrary order. It does not include the special\n\ 3321 the filenames returned will be str.\n\
2313 entries '.' and '..' even if they are present in the directory."); 3322 On some platforms, path may also be specified as an open file descriptor;\n\
2314 3323 the file descriptor must refer to a directory.\n\
2315 static PyObject * 3324 If this functionality is unavailable, using it raises NotImplementedError.");
2316 posix_listdir(PyObject *self, PyObject *args) 3325
2317 { 3326 static PyObject *
3327 posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
3328 {
3329 path_t path;
3330 PyObject *list = NULL;
3331 static char *keywords[] = {"path", NULL};
3332 int fd = -1;
3333
3334 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3335 PyObject *v;
3336 HANDLE hFindFile = INVALID_HANDLE_VALUE;
3337 BOOL result;
3338 WIN32_FIND_DATA FileData;
3339 char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
3340 char *bufptr = namebuf;
3341 /* only claim to have space for MAX_PATH */
3342 Py_ssize_t len = sizeof(namebuf)-5;
3343 PyObject *po = NULL;
3344 wchar_t *wnamebuf = NULL;
3345 #elif defined(PYOS_OS2)
3346 #ifndef MAX_PATH
3347 #define MAX_PATH CCHMAXPATH
3348 #endif
3349 char *pt;
3350 PyObject *v;
3351 char namebuf[MAX_PATH+5];
3352 HDIR hdir = 1;
3353 ULONG srchcnt = 1;
3354 FILEFINDBUF3 ep;
3355 APIRET rc;
3356 #else
3357 PyObject *v;
3358 DIR *dirp = NULL;
3359 struct dirent *ep;
3360 int return_str; /* if false, return bytes */
3361 #endif
3362
3363 memset(&path, 0, sizeof(path));
3364 path.nullable = 1;
3365 #ifdef HAVE_FDOPENDIR
3366 path.allow_fd = 1;
3367 path.fd = -1;
3368 #endif
3369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", keywords,
3370 path_converter, &path
3371 ))
3372 return NULL;
3373
2318 /* XXX Should redo this putting the (now four) versions of opendir 3374 /* XXX Should redo this putting the (now four) versions of opendir
2319 in separate files instead of having them all here... */ 3375 in separate files instead of having them all here... */
2320 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) 3376 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
2321 3377 if (!path.narrow) {
2322 PyObject *d, *v;
2323 HANDLE hFindFile;
2324 BOOL result;
2325 WIN32_FIND_DATA FileData;
2326 PyObject *opath;
2327 char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
2328 char *bufptr = namebuf;
2329 Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
2330
2331 PyObject *po = NULL;
2332 if (PyArg_ParseTuple(args, "|U:listdir", &po)) {
2333 WIN32_FIND_DATAW wFileData; 3378 WIN32_FIND_DATAW wFileData;
2334 Py_UNICODE *wnamebuf, *po_wchars; 3379 wchar_t *po_wchars;
2335 3380
2336 if (po == NULL) { // Default arg: "." 3381 if (!path.wide) { /* Default arg: "." */
2337 po_wchars = L"."; 3382 po_wchars = L".";
2338 len = 1; 3383 len = 1;
2339 } else { 3384 } else {
2340 po_wchars = PyUnicode_AS_UNICODE(po); 3385 po_wchars = path.wide;
2341 len = PyUnicode_GET_SIZE(po); 3386 len = wcslen(path.wide);
2342 } 3387 }
2343 /* Overallocate for \\*.*\0 */ 3388 /* The +5 is so we can append "\\*.*\0" */
2344 wnamebuf = malloc((len + 5) * sizeof(wchar_t)); 3389 wnamebuf = malloc((len + 5) * sizeof(wchar_t));
2345 if (!wnamebuf) { 3390 if (!wnamebuf) {
2346 PyErr_NoMemory(); 3391 PyErr_NoMemory();
2347 return NULL; 3392 goto exit;
2348 } 3393 }
2349 wcscpy(wnamebuf, po_wchars); 3394 wcscpy(wnamebuf, po_wchars);
2350 if (len > 0) { 3395 if (len > 0) {
2351 Py_UNICODE wch = wnamebuf[len-1]; 3396 wchar_t wch = wnamebuf[len-1];
2352 if (wch != L'/' && wch != L'\\' && wch != L':') 3397 if (wch != L'/' && wch != L'\\' && wch != L':')
2353 wnamebuf[len++] = L'\\'; 3398 wnamebuf[len++] = L'\\';
2354 wcscpy(wnamebuf + len, L"*.*"); 3399 wcscpy(wnamebuf + len, L"*.*");
2355 } 3400 }
2356 if ((d = PyList_New(0)) == NULL) { 3401 if ((list = PyList_New(0)) == NULL) {
2357 free(wnamebuf); 3402 goto exit;
2358 return NULL;
2359 } 3403 }
3404 Py_BEGIN_ALLOW_THREADS
2360 hFindFile = FindFirstFileW(wnamebuf, &wFileData); 3405 hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3406 Py_END_ALLOW_THREADS
2361 if (hFindFile == INVALID_HANDLE_VALUE) { 3407 if (hFindFile == INVALID_HANDLE_VALUE) {
2362 int error = GetLastError(); 3408 int error = GetLastError();
2363 if (error == ERROR_FILE_NOT_FOUND) { 3409 if (error == ERROR_FILE_NOT_FOUND)
2364 free(wnamebuf); 3410 goto exit;
2365 return d; 3411 Py_DECREF(list);
2366 } 3412 list = NULL;
2367 Py_DECREF(d);
2368 win32_error_unicode("FindFirstFileW", wnamebuf); 3413 win32_error_unicode("FindFirstFileW", wnamebuf);
2369 free(wnamebuf); 3414 goto exit;
2370 return NULL;
2371 } 3415 }
2372 do { 3416 do {
2373 /* Skip over . and .. */ 3417 /* Skip over . and .. */
2374 if (wcscmp(wFileData.cFileName, L".") != 0 && 3418 if (wcscmp(wFileData.cFileName, L".") != 0 &&
2375 wcscmp(wFileData.cFileName, L"..") != 0) { 3419 wcscmp(wFileData.cFileName, L"..") != 0) {
2376 v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData. cFileName)); 3420 v = PyUnicode_FromWideChar(wFileData.cFileName,
3421 wcslen(wFileData.cFileName));
2377 if (v == NULL) { 3422 if (v == NULL) {
2378 Py_DECREF(d); 3423 Py_DECREF(list);
2379 d = NULL; 3424 list = NULL;
2380 break; 3425 break;
2381 } 3426 }
2382 if (PyList_Append(d, v) != 0) { 3427 if (PyList_Append(list, v) != 0) {
2383 Py_DECREF(v); 3428 Py_DECREF(v);
2384 Py_DECREF(d); 3429 Py_DECREF(list);
2385 d = NULL; 3430 list = NULL;
2386 break; 3431 break;
2387 } 3432 }
2388 Py_DECREF(v); 3433 Py_DECREF(v);
2389 } 3434 }
2390 Py_BEGIN_ALLOW_THREADS 3435 Py_BEGIN_ALLOW_THREADS
2391 result = FindNextFileW(hFindFile, &wFileData); 3436 result = FindNextFileW(hFindFile, &wFileData);
2392 Py_END_ALLOW_THREADS 3437 Py_END_ALLOW_THREADS
2393 /* FindNextFile sets error to ERROR_NO_MORE_FILES if 3438 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2394 it got to the end of the directory. */ 3439 it got to the end of the directory. */
2395 if (!result && GetLastError() != ERROR_NO_MORE_FILES) { 3440 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2396 Py_DECREF(d); 3441 Py_DECREF(list);
2397 win32_error_unicode("FindNextFileW", wnamebuf); 3442 list = win32_error_unicode("FindNextFileW", wnamebuf);
2398 FindClose(hFindFile); 3443 goto exit;
2399 free(wnamebuf);
2400 return NULL;
2401 } 3444 }
2402 } while (result == TRUE); 3445 } while (result == TRUE);
2403 3446
2404 if (FindClose(hFindFile) == FALSE) { 3447 goto exit;
2405 Py_DECREF(d); 3448 }
2406 win32_error_unicode("FindClose", wnamebuf); 3449 strcpy(namebuf, path.narrow);
2407 free(wnamebuf); 3450 len = path.length;
2408 return NULL;
2409 }
2410 free(wnamebuf);
2411 return d;
2412 }
2413 /* Drop the argument parsing error as narrow strings
2414 are also valid. */
2415 PyErr_Clear();
2416
2417 if (!PyArg_ParseTuple(args, "O&:listdir",
2418 PyUnicode_FSConverter, &opath))
2419 return NULL;
2420 if (PyBytes_GET_SIZE(opath)+1 > MAX_PATH) {
2421 PyErr_SetString(PyExc_ValueError, "path too long");
2422 Py_DECREF(opath);
2423 return NULL;
2424 }
2425 strcpy(namebuf, PyBytes_AsString(opath));
2426 len = PyObject_Size(opath);
2427 if (len > 0) { 3451 if (len > 0) {
2428 char ch = namebuf[len-1]; 3452 char ch = namebuf[len-1];
2429 if (ch != SEP && ch != ALTSEP && ch != ':') 3453 if (ch != SEP && ch != ALTSEP && ch != ':')
2430 namebuf[len++] = '/'; 3454 namebuf[len++] = '/';
2431 strcpy(namebuf + len, "*.*"); 3455 strcpy(namebuf + len, "*.*");
2432 } 3456 }
2433 3457
2434 if ((d = PyList_New(0)) == NULL) 3458 if ((list = PyList_New(0)) == NULL)
2435 return NULL; 3459 return NULL;
2436 3460
3461 Py_BEGIN_ALLOW_THREADS
2437 hFindFile = FindFirstFile(namebuf, &FileData); 3462 hFindFile = FindFirstFile(namebuf, &FileData);
3463 Py_END_ALLOW_THREADS
2438 if (hFindFile == INVALID_HANDLE_VALUE) { 3464 if (hFindFile == INVALID_HANDLE_VALUE) {
2439 int error = GetLastError(); 3465 int error = GetLastError();
2440 if (error == ERROR_FILE_NOT_FOUND) 3466 if (error == ERROR_FILE_NOT_FOUND)
2441 return d; 3467 goto exit;
2442 Py_DECREF(d); 3468 Py_DECREF(list);
2443 return win32_error("FindFirstFile", namebuf); 3469 list = win32_error("FindFirstFile", namebuf);
3470 goto exit;
2444 } 3471 }
2445 do { 3472 do {
2446 /* Skip over . and .. */ 3473 /* Skip over . and .. */
2447 if (strcmp(FileData.cFileName, ".") != 0 && 3474 if (strcmp(FileData.cFileName, ".") != 0 &&
2448 strcmp(FileData.cFileName, "..") != 0) { 3475 strcmp(FileData.cFileName, "..") != 0) {
2449 v = PyBytes_FromString(FileData.cFileName); 3476 v = PyBytes_FromString(FileData.cFileName);
2450 if (v == NULL) { 3477 if (v == NULL) {
2451 Py_DECREF(d); 3478 Py_DECREF(list);
2452 d = NULL; 3479 list = NULL;
2453 break; 3480 break;
2454 } 3481 }
2455 if (PyList_Append(d, v) != 0) { 3482 if (PyList_Append(list, v) != 0) {
2456 Py_DECREF(v); 3483 Py_DECREF(v);
2457 Py_DECREF(d); 3484 Py_DECREF(list);
2458 d = NULL; 3485 list = NULL;
2459 break; 3486 break;
2460 } 3487 }
2461 Py_DECREF(v); 3488 Py_DECREF(v);
2462 } 3489 }
2463 Py_BEGIN_ALLOW_THREADS 3490 Py_BEGIN_ALLOW_THREADS
2464 result = FindNextFile(hFindFile, &FileData); 3491 result = FindNextFile(hFindFile, &FileData);
2465 Py_END_ALLOW_THREADS 3492 Py_END_ALLOW_THREADS
2466 /* FindNextFile sets error to ERROR_NO_MORE_FILES if 3493 /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2467 it got to the end of the directory. */ 3494 it got to the end of the directory. */
2468 if (!result && GetLastError() != ERROR_NO_MORE_FILES) { 3495 if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2469 Py_DECREF(d); 3496 Py_DECREF(list);
2470 win32_error("FindNextFile", namebuf); 3497 list = win32_error("FindNextFile", namebuf);
2471 FindClose(hFindFile); 3498 goto exit;
2472 return NULL;
2473 } 3499 }
2474 } while (result == TRUE); 3500 } while (result == TRUE);
2475 3501
2476 if (FindClose(hFindFile) == FALSE) { 3502 exit:
2477 Py_DECREF(d); 3503 if (hFindFile != INVALID_HANDLE_VALUE) {
2478 return win32_error("FindClose", namebuf); 3504 if (FindClose(hFindFile) == FALSE) {
2479 } 3505 if (list != NULL) {
2480 3506 Py_DECREF(list);
2481 return d; 3507 list = win32_error_object("FindClose", path.object);
3508 }
3509 }
3510 }
3511 if (wnamebuf)
3512 free(wnamebuf);
3513 path_cleanup(&path);
3514
3515 return list;
2482 3516
2483 #elif defined(PYOS_OS2) 3517 #elif defined(PYOS_OS2)
2484 3518 if (path.length >= MAX_PATH) {
2485 #ifndef MAX_PATH
2486 #define MAX_PATH CCHMAXPATH
2487 #endif
2488 PyObject *oname;
2489 char *name, *pt;
2490 Py_ssize_t len;
2491 PyObject *d, *v;
2492 char namebuf[MAX_PATH+5];
2493 HDIR hdir = 1;
2494 ULONG srchcnt = 1;
2495 FILEFINDBUF3 ep;
2496 APIRET rc;
2497
2498 if (!PyArg_ParseTuple(args, "O&:listdir",
2499 PyUnicode_FSConverter, &oname))
2500 return NULL;
2501 name = PyBytes_AsString(oname);
2502 len = PyBytes_GET_SIZE(oname);
2503 if (len >= MAX_PATH) {
2504 Py_DECREF(oname);
2505 PyErr_SetString(PyExc_ValueError, "path too long"); 3519 PyErr_SetString(PyExc_ValueError, "path too long");
2506 return NULL; 3520 goto exit;
2507 } 3521 }
2508 strcpy(namebuf, name); 3522 strcpy(namebuf, path.narrow);
2509 for (pt = namebuf; *pt; pt++) 3523 for (pt = namebuf; *pt; pt++)
2510 if (*pt == ALTSEP) 3524 if (*pt == ALTSEP)
2511 *pt = SEP; 3525 *pt = SEP;
2512 if (namebuf[len-1] != SEP) 3526 if (namebuf[len-1] != SEP)
2513 namebuf[len++] = SEP; 3527 namebuf[len++] = SEP;
2514 strcpy(namebuf + len, "*.*"); 3528 strcpy(namebuf + len, "*.*");
2515 3529
2516 if ((d = PyList_New(0)) == NULL) { 3530 if ((list = PyList_New(0)) == NULL) {
2517 Py_DECREF(oname); 3531 goto exit;
2518 return NULL;
2519 } 3532 }
2520 3533
2521 rc = DosFindFirst(namebuf, /* Wildcard Pattern to Match */ 3534 rc = DosFindFirst(namebuf, /* Wildcard Pattern to Match */
2522 &hdir, /* Handle to Use While Search Directory * / 3535 &hdir, /* Handle to Use While Search Directory * /
2523 FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY , 3536 FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY ,
2524 &ep, sizeof(ep), /* Structure to Receive Directory Entry * / 3537 &ep, sizeof(ep), /* Structure to Receive Directory Entry * /
2525 &srchcnt, /* Max and Actual Count of Entries Per It eration */ 3538 &srchcnt, /* Max and Actual Count of Entries Per It eration */
2526 FIL_STANDARD); /* Format of Entry (EAs or Not) */ 3539 FIL_STANDARD); /* Format of Entry (EAs or Not) */
2527 3540
2528 if (rc != NO_ERROR) { 3541 if (rc != NO_ERROR) {
2529 errno = ENOENT; 3542 errno = ENOENT;
2530 return posix_error_with_allocated_filename(oname); 3543 Py_DECREF(list);
3544 list = posix_error_with_filename(path.narrow);
3545 goto exit;
2531 } 3546 }
2532 3547
2533 if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */ 3548 if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
2534 do { 3549 do {
2535 if (ep.achName[0] == '.' 3550 if (ep.achName[0] == '.'
2536 && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0'))) 3551 && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
2537 continue; /* Skip Over "." and ".." Names */ 3552 continue; /* Skip Over "." and ".." Names */
2538 3553
2539 strcpy(namebuf, ep.achName); 3554 strcpy(namebuf, ep.achName);
2540 3555
2541 /* Leave Case of Name Alone -- In Native Form */ 3556 /* Leave Case of Name Alone -- In Native Form */
2542 /* (Removed Forced Lowercasing Code) */ 3557 /* (Removed Forced Lowercasing Code) */
2543 3558
2544 v = PyBytes_FromString(namebuf); 3559 v = PyBytes_FromString(namebuf);
2545 if (v == NULL) { 3560 if (v == NULL) {
2546 Py_DECREF(d); 3561 Py_DECREF(list);
2547 d = NULL; 3562 list = NULL;
2548 break; 3563 break;
2549 } 3564 }
2550 if (PyList_Append(d, v) != 0) { 3565 if (PyList_Append(list, v) != 0) {
2551 Py_DECREF(v); 3566 Py_DECREF(v);
2552 Py_DECREF(d); 3567 Py_DECREF(list);
2553 d = NULL; 3568 list = NULL;
2554 break; 3569 break;
2555 } 3570 }
2556 Py_DECREF(v); 3571 Py_DECREF(v);
2557 } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && src hcnt > 0); 3572 } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && src hcnt > 0);
2558 } 3573 }
2559 3574
2560 Py_DECREF(oname); 3575 exit:
2561 return d; 3576 path_cleanup(&path);
3577
3578 return list;
2562 #else 3579 #else
2563 PyObject *oname;
2564 char *name;
2565 PyObject *d, *v;
2566 DIR *dirp;
2567 struct dirent *ep;
2568 int arg_is_unicode = 1;
2569 3580
2570 errno = 0; 3581 errno = 0;
2571 /* v is never read, so it does not need to be initialized yet. */ 3582 #ifdef HAVE_FDOPENDIR
2572 if (!PyArg_ParseTuple(args, "|U:listdir", &v)) { 3583 if (path.fd != -1) {
2573 arg_is_unicode = 0; 3584 /* closedir() closes the FD, so we duplicate it */
2574 PyErr_Clear(); 3585 Py_BEGIN_ALLOW_THREADS
2575 } 3586 fd = dup(path.fd);
2576 oname = NULL; 3587 Py_END_ALLOW_THREADS
2577 if (!PyArg_ParseTuple(args, "|O&:listdir", PyUnicode_FSConverter, &oname)) 3588
2578 return NULL; 3589 if (fd == -1) {
2579 if (oname == NULL) { // Default arg: "." 3590 list = posix_error();
2580 oname = PyBytes_FromString("."); 3591 goto exit;
2581 } 3592 }
2582 name = PyBytes_AsString(oname); 3593
2583 if ((dirp = opendir(name)) == NULL) { 3594 return_str = 1;
2584 return posix_error_with_allocated_filename(oname); 3595
2585 } 3596 Py_BEGIN_ALLOW_THREADS
2586 if ((d = PyList_New(0)) == NULL) { 3597 dirp = fdopendir(fd);
2587 closedir(dirp); 3598 Py_END_ALLOW_THREADS
2588 Py_DECREF(oname); 3599 }
2589 return NULL; 3600 else
3601 #endif
3602 {
3603 char *name;
3604 if (path.narrow) {
3605 name = path.narrow;
3606 /* only return bytes if they specified a bytes object */
3607 return_str = !(PyBytes_Check(path.object));
3608 }
3609 else {
3610 name = ".";
3611 return_str = 1;
3612 }
3613
3614 Py_BEGIN_ALLOW_THREADS
3615 dirp = opendir(name);
3616 Py_END_ALLOW_THREADS
3617 }
3618
3619 if (dirp == NULL) {
3620 list = path_error("listdir", &path);
3621 goto exit;
3622 }
3623 if ((list = PyList_New(0)) == NULL) {
3624 goto exit;
2590 } 3625 }
2591 for (;;) { 3626 for (;;) {
2592 errno = 0; 3627 errno = 0;
2593 Py_BEGIN_ALLOW_THREADS 3628 Py_BEGIN_ALLOW_THREADS
2594 ep = readdir(dirp); 3629 ep = readdir(dirp);
2595 Py_END_ALLOW_THREADS 3630 Py_END_ALLOW_THREADS
2596 if (ep == NULL) { 3631 if (ep == NULL) {
2597 if (errno == 0) { 3632 if (errno == 0) {
2598 break; 3633 break;
2599 } else { 3634 } else {
2600 closedir(dirp); 3635 Py_DECREF(list);
2601 Py_DECREF(d); 3636 list = path_error("listdir", &path);
2602 return posix_error_with_allocated_filename(oname); 3637 goto exit;
2603 } 3638 }
2604 } 3639 }
2605 if (ep->d_name[0] == '.' && 3640 if (ep->d_name[0] == '.' &&
2606 (NAMLEN(ep) == 1 || 3641 (NAMLEN(ep) == 1 ||
2607 (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) 3642 (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
2608 continue; 3643 continue;
2609 if (arg_is_unicode) 3644 if (return_str)
2610 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); 3645 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
2611 else 3646 else
2612 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); 3647 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
2613 if (v == NULL) { 3648 if (v == NULL) {
2614 Py_CLEAR(d); 3649 Py_CLEAR(list);
2615 break; 3650 break;
2616 } 3651 }
2617 if (PyList_Append(d, v) != 0) { 3652 if (PyList_Append(list, v) != 0) {
2618 Py_DECREF(v); 3653 Py_DECREF(v);
2619 Py_CLEAR(d); 3654 Py_CLEAR(list);
2620 break; 3655 break;
2621 } 3656 }
2622 Py_DECREF(v); 3657 Py_DECREF(v);
2623 } 3658 }
2624 closedir(dirp); 3659
2625 Py_DECREF(oname); 3660 exit:
2626 3661 if (dirp != NULL) {
2627 return d; 3662 Py_BEGIN_ALLOW_THREADS
3663 if (fd > -1)
3664 rewinddir(dirp);
3665 closedir(dirp);
3666 Py_END_ALLOW_THREADS
3667 }
3668
3669 path_cleanup(&path);
3670
3671 return list;
2628 3672
2629 #endif /* which OS */ 3673 #endif /* which OS */
2630 } /* end of posix_listdir */ 3674 } /* end of posix_listdir */
2631 3675
2632 #ifdef MS_WINDOWS 3676 #ifdef MS_WINDOWS
2633 /* A helper function for abspath on win32 */ 3677 /* A helper function for abspath on win32 */
2634 static PyObject * 3678 static PyObject *
2635 posix__getfullpathname(PyObject *self, PyObject *args) 3679 posix__getfullpathname(PyObject *self, PyObject *args)
2636 { 3680 {
2637 PyObject *opath; 3681 const char *path;
2638 char *path;
2639 char outbuf[MAX_PATH*2]; 3682 char outbuf[MAX_PATH*2];
2640 char *temp; 3683 char *temp;
2641 #ifdef MS_WINDOWS 3684 PyObject *po;
2642 PyUnicodeObject *po; 3685
2643 if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) { 3686 if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po))
2644 Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po); 3687 {
2645 Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf; 3688 wchar_t *wpath;
2646 Py_UNICODE *wtemp; 3689 wchar_t woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
3690 wchar_t *wtemp;
2647 DWORD result; 3691 DWORD result;
2648 PyObject *v; 3692 PyObject *v;
3693
3694 wpath = PyUnicode_AsUnicode(po);
3695 if (wpath == NULL)
3696 return NULL;
2649 result = GetFullPathNameW(wpath, 3697 result = GetFullPathNameW(wpath,
2650 sizeof(woutbuf)/sizeof(woutbuf[0]), 3698 Py_ARRAY_LENGTH(woutbuf),
2651 woutbuf, &wtemp); 3699 woutbuf, &wtemp);
2652 if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) { 3700 if (result > Py_ARRAY_LENGTH(woutbuf)) {
2653 woutbufp = malloc(result * sizeof(Py_UNICODE)); 3701 woutbufp = malloc(result * sizeof(wchar_t));
2654 if (!woutbufp) 3702 if (!woutbufp)
2655 return PyErr_NoMemory(); 3703 return PyErr_NoMemory();
2656 result = GetFullPathNameW(wpath, result, woutbufp, &wtemp); 3704 result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
2657 } 3705 }
2658 if (result) 3706 if (result)
2659 v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp)); 3707 v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
2660 else 3708 else
2661 v = win32_error_unicode("GetFullPathNameW", wpath); 3709 v = win32_error_object("GetFullPathNameW", po);
2662 if (woutbufp != woutbuf) 3710 if (woutbufp != woutbuf)
2663 free(woutbufp); 3711 free(woutbufp);
2664 return v; 3712 return v;
2665 } 3713 }
2666 /* Drop the argument parsing error as narrow strings 3714 /* Drop the argument parsing error as narrow strings
2667 are also valid. */ 3715 are also valid. */
2668 PyErr_Clear(); 3716 PyErr_Clear();
2669 3717
2670 #endif 3718 if (!PyArg_ParseTuple (args, "y:_getfullpathname",
2671 if (!PyArg_ParseTuple (args, "O&:_getfullpathname", 3719 &path))
2672 PyUnicode_FSConverter, &opath)) 3720 return NULL;
2673 return NULL; 3721 if (win32_warn_bytes_api())
2674 path = PyBytes_AsString(opath); 3722 return NULL;
2675 if (!GetFullPathName(path, sizeof(outbuf)/sizeof(outbuf[0]), 3723 if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf),
2676 outbuf, &temp)) { 3724 outbuf, &temp)) {
2677 win32_error("GetFullPathName", path); 3725 win32_error("GetFullPathName", path);
2678 Py_DECREF(opath); 3726 return NULL;
2679 return NULL; 3727 }
2680 }
2681 Py_DECREF(opath);
2682 if (PyUnicode_Check(PyTuple_GetItem(args, 0))) { 3728 if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
2683 return PyUnicode_Decode(outbuf, strlen(outbuf), 3729 return PyUnicode_Decode(outbuf, strlen(outbuf),
2684 Py_FileSystemDefaultEncoding, NULL); 3730 Py_FileSystemDefaultEncoding, NULL);
2685 } 3731 }
2686 return PyBytes_FromString(outbuf); 3732 return PyBytes_FromString(outbuf);
2687 } /* end of posix__getfullpathname */ 3733 } /* end of posix__getfullpathname */
3734
2688 3735
2689 /* A helper function for samepath on windows */ 3736 /* A helper function for samepath on windows */
2690 static PyObject * 3737 static PyObject *
2691 posix__getfinalpathname(PyObject *self, PyObject *args) 3738 posix__getfinalpathname(PyObject *self, PyObject *args)
2692 { 3739 {
2693 HANDLE hFile; 3740 HANDLE hFile;
2694 int buf_size; 3741 int buf_size;
2695 wchar_t *target_path; 3742 wchar_t *target_path;
2696 int result_length; 3743 int result_length;
2697 PyObject *result; 3744 PyObject *po, *result;
2698 wchar_t *path; 3745 wchar_t *path;
2699 3746
2700 if (!PyArg_ParseTuple(args, "u|:_getfullpathname", &path)) { 3747 if (!PyArg_ParseTuple(args, "U|:_getfinalpathname", &po))
2701 return NULL; 3748 return NULL;
2702 } 3749 path = PyUnicode_AsUnicode(po);
3750 if (path == NULL)
3751 return NULL;
2703 3752
2704 if(!check_GetFinalPathNameByHandle()) { 3753 if(!check_GetFinalPathNameByHandle()) {
2705 /* If the OS doesn't have GetFinalPathNameByHandle, return a 3754 /* If the OS doesn't have GetFinalPathNameByHandle, return a
2706 NotImplementedError. */ 3755 NotImplementedError. */
2707 return PyErr_Format(PyExc_NotImplementedError, 3756 return PyErr_Format(PyExc_NotImplementedError,
2708 "GetFinalPathNameByHandle not available on this platform"); 3757 "GetFinalPathNameByHandle not available on this platform");
2709 } 3758 }
2710 3759
2711 hFile = CreateFileW( 3760 hFile = CreateFileW(
2712 path, 3761 path,
2713 0, /* desired access */ 3762 0, /* desired access */
2714 0, /* share mode */ 3763 0, /* share mode */
2715 NULL, /* security attributes */ 3764 NULL, /* security attributes */
2716 OPEN_EXISTING, 3765 OPEN_EXISTING,
2717 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 3766 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
2718 FILE_FLAG_BACKUP_SEMANTICS, 3767 FILE_FLAG_BACKUP_SEMANTICS,
2719 NULL); 3768 NULL);
2720 3769
2721 if(hFile == INVALID_HANDLE_VALUE) { 3770 if(hFile == INVALID_HANDLE_VALUE)
2722 return win32_error_unicode("GetFinalPathNamyByHandle", path); 3771 return win32_error_object("CreateFileW", po);
2723 return PyErr_Format(PyExc_RuntimeError,
2724 "Could not get a handle to file.");
2725 }
2726 3772
2727 /* We have a good handle to the target, use it to determine the 3773 /* We have a good handle to the target, use it to determine the
2728 target path name. */ 3774 target path name. */
2729 buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); 3775 buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
2730 3776
2731 if(!buf_size) 3777 if(!buf_size)
2732 return win32_error_unicode("GetFinalPathNameByHandle", path); 3778 return win32_error_object("GetFinalPathNameByHandle", po);
2733 3779
2734 target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t)); 3780 target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
2735 if(!target_path) 3781 if(!target_path)
2736 return PyErr_NoMemory(); 3782 return PyErr_NoMemory();
2737 3783
2738 result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, 3784 result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
2739 buf_size, VOLUME_NAME_DOS); 3785 buf_size, VOLUME_NAME_DOS);
2740 if(!result_length) 3786 if(!result_length)
2741 return win32_error_unicode("GetFinalPathNamyByHandle", path); 3787 return win32_error_object("GetFinalPathNamyByHandle", po);
2742 3788
2743 if(!CloseHandle(hFile)) 3789 if(!CloseHandle(hFile))
2744 return win32_error_unicode("GetFinalPathNameByHandle", path); 3790 return win32_error_object("CloseHandle", po);
2745 3791
2746 target_path[result_length] = 0; 3792 target_path[result_length] = 0;
2747 result = PyUnicode_FromUnicode(target_path, result_length); 3793 result = PyUnicode_FromWideChar(target_path, result_length);
2748 free(target_path); 3794 free(target_path);
2749 return result; 3795 return result;
2750 3796
2751 } /* end of posix__getfinalpathname */ 3797 } /* end of posix__getfinalpathname */
2752 #endif /* MS_WINDOWS */ 3798
2753 3799 static PyObject *
2754 PyDoc_STRVAR(posix_mkdir__doc__, 3800 posix__getfileinformation(PyObject *self, PyObject *args)
2755 "mkdir(path [, mode=0777])\n\n\ 3801 {
2756 Create a directory."); 3802 HANDLE hFile;
2757 3803 BY_HANDLE_FILE_INFORMATION info;
2758 static PyObject * 3804 int fd;
2759 posix_mkdir(PyObject *self, PyObject *args) 3805
2760 { 3806 if (!PyArg_ParseTuple(args, "i:_getfileinformation", &fd))
2761 int res; 3807 return NULL;
2762 PyObject *opath; 3808
2763 char *path; 3809 if (!_PyVerify_fd(fd))
2764 int mode = 0777; 3810 return posix_error();
2765 3811
2766 #ifdef MS_WINDOWS 3812 hFile = (HANDLE)_get_osfhandle(fd);
2767 PyUnicodeObject *po; 3813 if (hFile == INVALID_HANDLE_VALUE)
2768 if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) { 3814 return posix_error();
2769 Py_BEGIN_ALLOW_THREADS 3815
2770 /* PyUnicode_AS_UNICODE OK without thread lock as 3816 if (!GetFileInformationByHandle(hFile, &info))
2771 it is a simple dereference. */ 3817 return win32_error("_getfileinformation", NULL);
2772 res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL); 3818
2773 Py_END_ALLOW_THREADS 3819 return Py_BuildValue("iii", info.dwVolumeSerialNumber,
2774 if (!res) 3820 info.nFileIndexHigh,
2775 return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po)); 3821 info.nFileIndexLow);
2776 Py_INCREF(Py_None); 3822 }
2777 return Py_None; 3823
3824 PyDoc_STRVAR(posix__isdir__doc__,
3825 "Return true if the pathname refers to an existing directory.");
3826
3827 static PyObject *
3828 posix__isdir(PyObject *self, PyObject *args)
3829 {
3830 const char *path;
3831 PyObject *po;
3832 DWORD attributes;
3833
3834 if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
3835 wchar_t *wpath = PyUnicode_AsUnicode(po);
3836 if (wpath == NULL)
3837 return NULL;
3838
3839 attributes = GetFileAttributesW(wpath);
3840 if (attributes == INVALID_FILE_ATTRIBUTES)
3841 Py_RETURN_FALSE;
3842 goto check;
2778 } 3843 }
2779 /* Drop the argument parsing error as narrow strings 3844 /* Drop the argument parsing error as narrow strings
2780 are also valid. */ 3845 are also valid. */
2781 PyErr_Clear(); 3846 PyErr_Clear();
2782 if (!PyArg_ParseTuple(args, "O&|i:mkdir", 3847
2783 PyUnicode_FSConverter, &opath, &mode)) 3848 if (!PyArg_ParseTuple(args, "y:_isdir", &path))
2784 return NULL; 3849 return NULL;
2785 path = PyBytes_AsString(opath); 3850 if (win32_warn_bytes_api())
3851 return NULL;
3852 attributes = GetFileAttributesA(path);
3853 if (attributes == INVALID_FILE_ATTRIBUTES)
3854 Py_RETURN_FALSE;
3855
3856 check:
3857 if (attributes & FILE_ATTRIBUTE_DIRECTORY)
3858 Py_RETURN_TRUE;
3859 else
3860 Py_RETURN_FALSE;
3861 }
3862 #endif /* MS_WINDOWS */
3863
3864 PyDoc_STRVAR(posix_mkdir__doc__,
3865 "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
3866 Create a directory.\n\
3867 \n\
3868 If dir_fd is not None, it should be a file descriptor open to a directory,\n\
3869 and path should be relative; path will then be relative to that directory.\n\
3870 dir_fd may not be implemented on your platform.\n\
3871 If it is unavailable, using it will raise a NotImplementedError.\n\
3872 \n\
3873 The mode argument is ignored on Windows.");
3874
3875 static PyObject *
3876 posix_mkdir(PyObject *self, PyObject *args, PyObject *kwargs)
3877 {
3878 path_t path;
3879 int mode = 0777;
3880 int dir_fd = DEFAULT_DIR_FD;
3881 static char *keywords[] = {"path", "mode", "dir_fd", NULL};
3882 PyObject *return_value = NULL;
3883 int result;
3884
3885 memset(&path, 0, sizeof(path));
3886 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", keywords,
3887 path_converter, &path, &mode,
3888 #ifdef HAVE_MKDIRAT
3889 dir_fd_converter, &dir_fd
3890 #else
3891 dir_fd_unavailable, &dir_fd
3892 #endif
3893 ))
3894 return NULL;
3895
3896 #ifdef MS_WINDOWS
2786 Py_BEGIN_ALLOW_THREADS 3897 Py_BEGIN_ALLOW_THREADS
2787 /* PyUnicode_AS_UNICODE OK without thread lock as 3898 if (path.wide)
2788 it is a simple dereference. */ 3899 result = CreateDirectoryW(path.wide, NULL);
2789 res = CreateDirectoryA(path, NULL); 3900 else
3901 result = CreateDirectoryA(path.narrow, NULL);
2790 Py_END_ALLOW_THREADS 3902 Py_END_ALLOW_THREADS
2791 if (!res) { 3903
2792 win32_error("mkdir", path); 3904 if (!result) {
2793 Py_DECREF(opath); 3905 return_value = win32_error_object("mkdir", path.object);
2794 return NULL; 3906 goto exit;
2795 } 3907 }
2796 Py_DECREF(opath); 3908 #else
3909 Py_BEGIN_ALLOW_THREADS
3910 #if HAVE_MKDIRAT
3911 if (dir_fd != DEFAULT_DIR_FD)
3912 result = mkdirat(dir_fd, path.narrow, mode);
3913 else
3914 #endif
3915 #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
3916 result = mkdir(path.narrow);
3917 #else
3918 result = mkdir(path.narrow, mode);
3919 #endif
3920 Py_END_ALLOW_THREADS
3921 if (result < 0) {
3922 return_value = path_error("mkdir", &path);
3923 goto exit;
3924 }
3925 #endif
3926 return_value = Py_None;
2797 Py_INCREF(Py_None); 3927 Py_INCREF(Py_None);
2798 return Py_None; 3928 exit:
2799 #else 3929 path_cleanup(&path);
2800 3930 return return_value;
2801 if (!PyArg_ParseTuple(args, "O&|i:mkdir",
2802 PyUnicode_FSConverter, &opath, &mode))
2803 return NULL;
2804 path = PyBytes_AsString(opath);
2805 Py_BEGIN_ALLOW_THREADS
2806 #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
2807 res = mkdir(path);
2808 #else
2809 res = mkdir(path, mode);
2810 #endif
2811 Py_END_ALLOW_THREADS
2812 if (res < 0)
2813 return posix_error_with_allocated_filename(opath);
2814 Py_DECREF(opath);
2815 Py_INCREF(Py_None);
2816 return Py_None;
2817 #endif
2818 } 3931 }
2819 3932
2820 3933
2821 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ 3934 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
2822 #if defined(HAVE_SYS_RESOURCE_H) 3935 #if defined(HAVE_SYS_RESOURCE_H)
2823 #include <sys/resource.h> 3936 #include <sys/resource.h>
2824 #endif 3937 #endif
2825 3938
2826 3939
2827 #ifdef HAVE_NICE 3940 #ifdef HAVE_NICE
(...skipping 25 matching lines...) Expand all
2853 if (value == 0) 3966 if (value == 0)
2854 value = getpriority(PRIO_PROCESS, 0); 3967 value = getpriority(PRIO_PROCESS, 0);
2855 #endif 3968 #endif
2856 if (value == -1 && errno != 0) 3969 if (value == -1 && errno != 0)
2857 /* either nice() or getpriority() returned an error */ 3970 /* either nice() or getpriority() returned an error */
2858 return posix_error(); 3971 return posix_error();
2859 return PyLong_FromLong((long) value); 3972 return PyLong_FromLong((long) value);
2860 } 3973 }
2861 #endif /* HAVE_NICE */ 3974 #endif /* HAVE_NICE */
2862 3975
3976
3977 #ifdef HAVE_GETPRIORITY
3978 PyDoc_STRVAR(posix_getpriority__doc__,
3979 "getpriority(which, who) -> current_priority\n\n\
3980 Get program scheduling priority.");
3981
3982 static PyObject *
3983 posix_getpriority(PyObject *self, PyObject *args)
3984 {
3985 int which, who, retval;
3986
3987 if (!PyArg_ParseTuple(args, "ii", &which, &who))
3988 return NULL;
3989 errno = 0;
3990 retval = getpriority(which, who);
3991 if (errno != 0)
3992 return posix_error();
3993 return PyLong_FromLong((long)retval);
3994 }
3995 #endif /* HAVE_GETPRIORITY */
3996
3997
3998 #ifdef HAVE_SETPRIORITY
3999 PyDoc_STRVAR(posix_setpriority__doc__,
4000 "setpriority(which, who, prio) -> None\n\n\
4001 Set program scheduling priority.");
4002
4003 static PyObject *
4004 posix_setpriority(PyObject *self, PyObject *args)
4005 {
4006 int which, who, prio, retval;
4007
4008 if (!PyArg_ParseTuple(args, "iii", &which, &who, &prio))
4009 return NULL;
4010 retval = setpriority(which, who, prio);
4011 if (retval == -1)
4012 return posix_error();
4013 Py_RETURN_NONE;
4014 }
4015 #endif /* HAVE_SETPRIORITY */
4016
4017
4018 static PyObject *
4019 internal_rename(PyObject *args, PyObject *kwargs, int is_replace)
4020 {
4021 char *function_name = is_replace ? "replace" : "rename";
4022 path_t src;
4023 path_t dst;
4024 int src_dir_fd = DEFAULT_DIR_FD;
4025 int dst_dir_fd = DEFAULT_DIR_FD;
4026 int dir_fd_specified;
4027 PyObject *return_value = NULL;
4028 char format[24];
4029 static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
4030
4031 #ifdef MS_WINDOWS
4032 BOOL result;
4033 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4034 #else
4035 int result;
4036 #endif
4037
4038 memset(&src, 0, sizeof(src));
4039 memset(&dst, 0, sizeof(dst));
4040 strcpy(format, "O&O&|$O&O&:");
4041 strcat(format, function_name);
4042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, keywords,
4043 path_converter, &src,
4044 path_converter, &dst,
<