Line data Source code
1 :
2 : /* POSIX module implementation */
3 :
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
6 : functions are either unimplemented or implemented differently. The source
7 : assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
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
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
12 : as the compiler specific macro for the EMX port of gcc to OS/2. */
13 :
14 : #ifdef __APPLE__
15 : /*
16 : * Step 1 of support for weak-linking a number of symbols existing on
17 : * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
18 : * at the end of this file for more information.
19 : */
20 : # pragma weak lchown
21 : # pragma weak statvfs
22 : # pragma weak fstatvfs
23 :
24 : #endif /* __APPLE__ */
25 :
26 : #define PY_SSIZE_T_CLEAN
27 :
28 : #include "Python.h"
29 :
30 : #if defined(__VMS)
31 : # error "PEP 11: VMS is now unsupported, code will be removed in Python 3.4"
32 : # include <unixio.h>
33 : #endif /* defined(__VMS) */
34 :
35 : #ifdef __cplusplus
36 : extern "C" {
37 : #endif
38 :
39 : PyDoc_STRVAR(posix__doc__,
40 : "This module provides access to operating system functionality that is\n\
41 : standardized by the C Standard and the POSIX standard (a thinly\n\
42 : disguised Unix interface). Refer to the library manual and\n\
43 : corresponding Unix manual entries for more information on calls.");
44 :
45 :
46 : #if defined(PYOS_OS2)
47 : #error "PEP 11: OS/2 is now unsupported, code will be removed in Python 3.4"
48 : #define INCL_DOS
49 : #define INCL_DOSERRORS
50 : #define INCL_DOSPROCESS
51 : #define INCL_NOPMAPI
52 : #include <os2.h>
53 : #if defined(PYCC_GCC)
54 : #include <ctype.h>
55 : #include <io.h>
56 : #include <stdio.h>
57 : #include <process.h>
58 : #endif
59 : #include "osdefs.h"
60 : #endif
61 :
62 : #ifdef HAVE_SYS_UIO_H
63 : #include <sys/uio.h>
64 : #endif
65 :
66 : #ifdef HAVE_SYS_TYPES_H
67 : #include <sys/types.h>
68 : #endif /* HAVE_SYS_TYPES_H */
69 :
70 : #ifdef HAVE_SYS_STAT_H
71 : #include <sys/stat.h>
72 : #endif /* HAVE_SYS_STAT_H */
73 :
74 : #ifdef HAVE_SYS_WAIT_H
75 : #include <sys/wait.h> /* For WNOHANG */
76 : #endif
77 :
78 : #ifdef HAVE_SIGNAL_H
79 : #include <signal.h>
80 : #endif
81 :
82 : #ifdef HAVE_FCNTL_H
83 : #include <fcntl.h>
84 : #endif /* HAVE_FCNTL_H */
85 :
86 : #ifdef HAVE_GRP_H
87 : #include <grp.h>
88 : #endif
89 :
90 : #ifdef HAVE_SYSEXITS_H
91 : #include <sysexits.h>
92 : #endif /* HAVE_SYSEXITS_H */
93 :
94 : #ifdef HAVE_SYS_LOADAVG_H
95 : #include <sys/loadavg.h>
96 : #endif
97 :
98 : #ifdef HAVE_LANGINFO_H
99 : #include <langinfo.h>
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 */
143 :
144 : /* Various compilers have only certain posix functions */
145 : /* XXX Gosh I wish these were all moved into pyconfig.h */
146 : #if defined(PYCC_VACPP) && defined(PYOS_OS2)
147 : #include <process.h>
148 : #else
149 : #if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */
150 : #define HAVE_GETCWD 1
151 : #define HAVE_OPENDIR 1
152 : #define HAVE_SYSTEM 1
153 : #if defined(__OS2__)
154 : #define HAVE_EXECV 1
155 : #define HAVE_WAIT 1
156 : #endif
157 : #include <process.h>
158 : #else
159 : #ifdef __BORLANDC__ /* Borland compiler */
160 : #define HAVE_EXECV 1
161 : #define HAVE_GETCWD 1
162 : #define HAVE_OPENDIR 1
163 : #define HAVE_PIPE 1
164 : #define HAVE_SYSTEM 1
165 : #define HAVE_WAIT 1
166 : #else
167 : #ifdef _MSC_VER /* Microsoft compiler */
168 : #define HAVE_GETCWD 1
169 : #define HAVE_GETPPID 1
170 : #define HAVE_GETLOGIN 1
171 : #define HAVE_SPAWNV 1
172 : #define HAVE_EXECV 1
173 : #define HAVE_PIPE 1
174 : #define HAVE_SYSTEM 1
175 : #define HAVE_CWAIT 1
176 : #define HAVE_FSYNC 1
177 : #define fsync _commit
178 : #else
179 : #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
180 : /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
181 : #else /* all other compilers */
182 : /* Unix functions that the configure script doesn't check for */
183 : #define HAVE_EXECV 1
184 : #define HAVE_FORK 1
185 : #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */
186 : #define HAVE_FORK1 1
187 : #endif
188 : #define HAVE_GETCWD 1
189 : #define HAVE_GETEGID 1
190 : #define HAVE_GETEUID 1
191 : #define HAVE_GETGID 1
192 : #define HAVE_GETPPID 1
193 : #define HAVE_GETUID 1
194 : #define HAVE_KILL 1
195 : #define HAVE_OPENDIR 1
196 : #define HAVE_PIPE 1
197 : #define HAVE_SYSTEM 1
198 : #define HAVE_WAIT 1
199 : #define HAVE_TTYNAME 1
200 : #endif /* PYOS_OS2 && PYCC_GCC && __VMS */
201 : #endif /* _MSC_VER */
202 : #endif /* __BORLANDC__ */
203 : #endif /* ! __WATCOMC__ || __QNX__ */
204 : #endif /* ! __IBMC__ */
205 :
206 :
207 :
208 :
209 : #ifndef _MSC_VER
210 :
211 : #if defined(__sgi)&&_COMPILER_VERSION>=700
212 : /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
213 : (default) */
214 : extern char *ctermid_r(char *);
215 : #endif
216 :
217 : #ifndef HAVE_UNISTD_H
218 : #if defined(PYCC_VACPP)
219 : extern int mkdir(char *);
220 : #else
221 : #if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
222 : extern int mkdir(const char *);
223 : #else
224 : extern int mkdir(const char *, mode_t);
225 : #endif
226 : #endif
227 : #if defined(__IBMC__) || defined(__IBMCPP__)
228 : extern int chdir(char *);
229 : extern int rmdir(char *);
230 : #else
231 : extern int chdir(const char *);
232 : extern int rmdir(const char *);
233 : #endif
234 : #ifdef __BORLANDC__
235 : extern int chmod(const char *, int);
236 : #else
237 : extern int chmod(const char *, mode_t);
238 : #endif
239 : /*#ifdef HAVE_FCHMOD
240 : extern int fchmod(int, mode_t);
241 : #endif*/
242 : /*#ifdef HAVE_LCHMOD
243 : extern int lchmod(const char *, mode_t);
244 : #endif*/
245 : extern int chown(const char *, uid_t, gid_t);
246 : extern char *getcwd(char *, int);
247 : extern char *strerror(int);
248 : extern int link(const char *, const char *);
249 : extern int rename(const char *, const char *);
250 : extern int stat(const char *, struct stat *);
251 : extern int unlink(const char *);
252 : #ifdef HAVE_SYMLINK
253 : extern int symlink(const char *, const char *);
254 : #endif /* HAVE_SYMLINK */
255 : #ifdef HAVE_LSTAT
256 : extern int lstat(const char *, struct stat *);
257 : #endif /* HAVE_LSTAT */
258 : #endif /* !HAVE_UNISTD_H */
259 :
260 : #endif /* !_MSC_VER */
261 :
262 : #ifdef HAVE_UTIME_H
263 : #include <utime.h>
264 : #endif /* HAVE_UTIME_H */
265 :
266 : #ifdef HAVE_SYS_UTIME_H
267 : #include <sys/utime.h>
268 : #define HAVE_UTIME_H /* pretend we do for the rest of this file */
269 : #endif /* HAVE_SYS_UTIME_H */
270 :
271 : #ifdef HAVE_SYS_TIMES_H
272 : #include <sys/times.h>
273 : #endif /* HAVE_SYS_TIMES_H */
274 :
275 : #ifdef HAVE_SYS_PARAM_H
276 : #include <sys/param.h>
277 : #endif /* HAVE_SYS_PARAM_H */
278 :
279 : #ifdef HAVE_SYS_UTSNAME_H
280 : #include <sys/utsname.h>
281 : #endif /* HAVE_SYS_UTSNAME_H */
282 :
283 : #ifdef HAVE_DIRENT_H
284 : #include <dirent.h>
285 : #define NAMLEN(dirent) strlen((dirent)->d_name)
286 : #else
287 : #if defined(__WATCOMC__) && !defined(__QNX__)
288 : #include <direct.h>
289 : #define NAMLEN(dirent) strlen((dirent)->d_name)
290 : #else
291 : #define dirent direct
292 : #define NAMLEN(dirent) (dirent)->d_namlen
293 : #endif
294 : #ifdef HAVE_SYS_NDIR_H
295 : #include <sys/ndir.h>
296 : #endif
297 : #ifdef HAVE_SYS_DIR_H
298 : #include <sys/dir.h>
299 : #endif
300 : #ifdef HAVE_NDIR_H
301 : #include <ndir.h>
302 : #endif
303 : #endif
304 :
305 : #ifdef _MSC_VER
306 : #ifdef HAVE_DIRECT_H
307 : #include <direct.h>
308 : #endif
309 : #ifdef HAVE_IO_H
310 : #include <io.h>
311 : #endif
312 : #ifdef HAVE_PROCESS_H
313 : #include <process.h>
314 : #endif
315 : #ifndef VOLUME_NAME_DOS
316 : #define VOLUME_NAME_DOS 0x0
317 : #endif
318 : #ifndef VOLUME_NAME_NT
319 : #define VOLUME_NAME_NT 0x2
320 : #endif
321 : #ifndef IO_REPARSE_TAG_SYMLINK
322 : #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
323 : #endif
324 : #include "osdefs.h"
325 : #include <malloc.h>
326 : #include <windows.h>
327 : #include <shellapi.h> /* for ShellExecute() */
328 : #include <lmcons.h> /* for UNLEN */
329 : #ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */
330 : #define HAVE_SYMLINK
331 : static int win32_can_symlink = 0;
332 : #endif
333 : #endif /* _MSC_VER */
334 :
335 : #if defined(PYCC_VACPP) && defined(PYOS_OS2)
336 : #include <io.h>
337 : #endif /* OS2 */
338 :
339 : #ifndef MAXPATHLEN
340 : #if defined(PATH_MAX) && PATH_MAX > 1024
341 : #define MAXPATHLEN PATH_MAX
342 : #else
343 : #define MAXPATHLEN 1024
344 : #endif
345 : #endif /* MAXPATHLEN */
346 :
347 : #ifdef UNION_WAIT
348 : /* Emulate some macros on systems that have a union instead of macros */
349 :
350 : #ifndef WIFEXITED
351 : #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
352 : #endif
353 :
354 : #ifndef WEXITSTATUS
355 : #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
356 : #endif
357 :
358 : #ifndef WTERMSIG
359 : #define WTERMSIG(u_wait) ((u_wait).w_termsig)
360 : #endif
361 :
362 : #define WAIT_TYPE union wait
363 : #define WAIT_STATUS_INT(s) (s.w_status)
364 :
365 : #else /* !UNION_WAIT */
366 : #define WAIT_TYPE int
367 : #define WAIT_STATUS_INT(s) (s)
368 : #endif /* UNION_WAIT */
369 :
370 : /* Don't use the "_r" form if we don't need it (also, won't have a
371 : prototype for it, at least on Solaris -- maybe others as well?). */
372 : #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
373 : #define USE_CTERMID_R
374 : #endif
375 :
376 : /* choose the appropriate stat and fstat functions and return structs */
377 : #undef STAT
378 : #undef FSTAT
379 : #undef STRUCT_STAT
380 : #if defined(MS_WIN64) || defined(MS_WINDOWS)
381 : # define STAT win32_stat
382 : # define LSTAT win32_lstat
383 : # define FSTAT win32_fstat
384 : # define STRUCT_STAT struct win32_stat
385 : #else
386 : # define STAT stat
387 : # define LSTAT lstat
388 : # define FSTAT fstat
389 : # define STRUCT_STAT struct stat
390 : #endif
391 :
392 : #if defined(MAJOR_IN_MKDEV)
393 : #include <sys/mkdev.h>
394 : #else
395 : #if defined(MAJOR_IN_SYSMACROS)
396 : #include <sys/sysmacros.h>
397 : #endif
398 : #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
399 : #include <sys/mkdev.h>
400 : #endif
401 : #endif
402 :
403 :
404 : #ifdef MS_WINDOWS
405 : static int
406 : win32_warn_bytes_api()
407 : {
408 : return PyErr_WarnEx(PyExc_DeprecationWarning,
409 : "The Windows bytes API has been deprecated, "
410 : "use Unicode filenames instead",
411 : 1);
412 : }
413 : #endif
414 :
415 :
416 : #ifdef AT_FDCWD
417 : #define DEFAULT_DIR_FD AT_FDCWD
418 : #else
419 : #define DEFAULT_DIR_FD (-100)
420 : #endif
421 :
422 : static int
423 2 : _fd_converter(PyObject *o, int *p, int default_value) {
424 : long long_value;
425 2 : if (o == Py_None) {
426 2 : *p = default_value;
427 2 : return 1;
428 : }
429 0 : if (PyFloat_Check(o)) {
430 0 : PyErr_SetString(PyExc_TypeError,
431 : "integer argument expected, got float" );
432 0 : return 0;
433 : }
434 0 : long_value = PyLong_AsLong(o);
435 0 : if (long_value == -1 && PyErr_Occurred())
436 0 : return 0;
437 : if (long_value > INT_MAX) {
438 : PyErr_SetString(PyExc_OverflowError,
439 : "signed integer is greater than maximum");
440 : return 0;
441 : }
442 : if (long_value < INT_MIN) {
443 : PyErr_SetString(PyExc_OverflowError,
444 : "signed integer is less than minimum");
445 : return 0;
446 : }
447 0 : *p = (int)long_value;
448 0 : return 1;
449 : }
450 :
451 : static int
452 1 : dir_fd_converter(PyObject *o, void *p) {
453 1 : return _fd_converter(o, (int *)p, DEFAULT_DIR_FD);
454 : }
455 :
456 :
457 :
458 : /*
459 : * A PyArg_ParseTuple "converter" function
460 : * that handles filesystem paths in the manner
461 : * preferred by the os module.
462 : *
463 : * path_converter accepts (Unicode) strings and their
464 : * subclasses, and bytes and their subclasses. What
465 : * it does with the argument depends on the platform:
466 : *
467 : * * On Windows, if we get a (Unicode) string we
468 : * extract the wchar_t * and return it; if we get
469 : * bytes we extract the char * and return that.
470 : *
471 : * * On all other platforms, strings are encoded
472 : * to bytes using PyUnicode_FSConverter, then we
473 : * extract the char * from the bytes object and
474 : * return that.
475 : *
476 : * path_converter also optionally accepts signed
477 : * integers (representing open file descriptors) instead
478 : * of path strings.
479 : *
480 : * Input fields:
481 : * path.nullable
482 : * If nonzero, the path is permitted to be None.
483 : * path.allow_fd
484 : * If nonzero, the path is permitted to be a file handle
485 : * (a signed int) instead of a string.
486 : * path.function_name
487 : * If non-NULL, path_converter will use that as the name
488 : * of the function in error messages.
489 : * (If path.argument_name is NULL it omits the function name.)
490 : * path.argument_name
491 : * If non-NULL, path_converter will use that as the name
492 : * of the parameter in error messages.
493 : * (If path.argument_name is NULL it uses "path".)
494 : *
495 : * Output fields:
496 : * path.wide
497 : * Points to the path if it was expressed as Unicode
498 : * and was not encoded. (Only used on Windows.)
499 : * path.narrow
500 : * Points to the path if it was expressed as bytes,
501 : * or it was Unicode and was encoded to bytes.
502 : * path.fd
503 : * Contains a file descriptor if path.accept_fd was true
504 : * and the caller provided a signed integer instead of any
505 : * sort of string.
506 : *
507 : * WARNING: if your "path" parameter is optional, and is
508 : * unspecified, path_converter will never get called.
509 : * So if you set allow_fd, you *MUST* initialize path.fd = -1
510 : * yourself!
511 : * path.length
512 : * The length of the path in characters, if specified as
513 : * a string.
514 : * path.object
515 : * The original object passed in.
516 : * path.cleanup
517 : * For internal use only. May point to a temporary object.
518 : * (Pay no attention to the man behind the curtain.)
519 : *
520 : * At most one of path.wide or path.narrow will be non-NULL.
521 : * If path was None and path.nullable was set,
522 : * or if path was an integer and path.allow_fd was set,
523 : * both path.wide and path.narrow will be NULL
524 : * and path.length will be 0.
525 : *
526 : * path_converter takes care to not write to the path_t
527 : * unless it's successful. However it must reset the
528 : * "cleanup" field each time it's called.
529 : *
530 : * Use as follows:
531 : * path_t path;
532 : * memset(&path, 0, sizeof(path));
533 : * PyArg_ParseTuple(args, "O&", path_converter, &path);
534 : * // ... use values from path ...
535 : * path_cleanup(&path);
536 : *
537 : * (Note that if PyArg_Parse fails you don't need to call
538 : * path_cleanup(). However it is safe to do so.)
539 : */
540 : typedef struct {
541 : char *function_name;
542 : char *argument_name;
543 : int nullable;
544 : int allow_fd;
545 : wchar_t *wide;
546 : char *narrow;
547 : int fd;
548 : Py_ssize_t length;
549 : PyObject *object;
550 : PyObject *cleanup;
551 : } path_t;
552 :
553 : static void
554 360 : path_cleanup(path_t *path) {
555 360 : if (path->cleanup) {
556 360 : Py_DECREF(path->cleanup);
557 360 : path->cleanup = NULL;
558 : }
559 360 : }
560 :
561 : static int
562 360 : path_converter(PyObject *o, void *p) {
563 360 : path_t *path = (path_t *)p;
564 : PyObject *unicode, *bytes;
565 : Py_ssize_t length;
566 : char *narrow;
567 :
568 : #define FORMAT_EXCEPTION(exc, fmt) \
569 : PyErr_Format(exc, "%s%s" fmt, \
570 : path->function_name ? path->function_name : "", \
571 : path->function_name ? ": " : "", \
572 : path->argument_name ? path->argument_name : "path")
573 :
574 : /* Py_CLEANUP_SUPPORTED support */
575 360 : if (o == NULL) {
576 0 : path_cleanup(path);
577 0 : return 1;
578 : }
579 :
580 : /* ensure it's always safe to call path_cleanup() */
581 360 : path->cleanup = NULL;
582 :
583 360 : if (o == Py_None) {
584 0 : if (!path->nullable) {
585 0 : FORMAT_EXCEPTION(PyExc_TypeError,
586 : "can't specify None for %s argument");
587 0 : return 0;
588 : }
589 0 : path->wide = NULL;
590 0 : path->narrow = NULL;
591 0 : path->length = 0;
592 0 : path->object = o;
593 0 : path->fd = -1;
594 0 : return 1;
595 : }
596 :
597 360 : unicode = PyUnicode_FromObject(o);
598 360 : if (unicode) {
599 : #ifdef MS_WINDOWS
600 : wchar_t *wide;
601 : length = PyUnicode_GET_SIZE(unicode);
602 : if (length > 32767) {
603 : FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
604 : Py_DECREF(unicode);
605 : return 0;
606 : }
607 :
608 : wide = PyUnicode_AsUnicode(unicode);
609 : if (!wide) {
610 : Py_DECREF(unicode);
611 : return 0;
612 : }
613 :
614 : path->wide = wide;
615 : path->narrow = NULL;
616 : path->length = length;
617 : path->object = o;
618 : path->fd = -1;
619 : path->cleanup = unicode;
620 : return Py_CLEANUP_SUPPORTED;
621 : #else
622 358 : int converted = PyUnicode_FSConverter(unicode, &bytes);
623 358 : Py_DECREF(unicode);
624 358 : if (!converted)
625 0 : bytes = NULL;
626 : #endif
627 : }
628 : else {
629 2 : PyErr_Clear();
630 2 : bytes = PyBytes_FromObject(o);
631 2 : if (!bytes) {
632 0 : PyErr_Clear();
633 0 : if (path->allow_fd) {
634 : int fd;
635 : /*
636 : * note: _fd_converter always permits None.
637 : * but we've already done our None check.
638 : * so o cannot be None at this point.
639 : */
640 0 : int result = _fd_converter(o, &fd, -1);
641 0 : if (result) {
642 0 : path->wide = NULL;
643 0 : path->narrow = NULL;
644 0 : path->length = 0;
645 0 : path->object = o;
646 0 : path->fd = fd;
647 0 : return result;
648 : }
649 : }
650 : }
651 : }
652 :
653 360 : if (!bytes) {
654 0 : if (!PyErr_Occurred())
655 0 : FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter");
656 0 : return 0;
657 : }
658 :
659 : #ifdef MS_WINDOWS
660 : if (win32_warn_bytes_api()) {
661 : Py_DECREF(bytes);
662 : return 0;
663 : }
664 : #endif
665 :
666 360 : length = PyBytes_GET_SIZE(bytes);
667 : #ifdef MS_WINDOWS
668 : if (length > MAX_PATH) {
669 : FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
670 : Py_DECREF(bytes);
671 : return 0;
672 : }
673 : #endif
674 :
675 360 : narrow = PyBytes_AS_STRING(bytes);
676 360 : if (length != strlen(narrow)) {
677 0 : FORMAT_EXCEPTION(PyExc_ValueError, "embedded NUL character in %s");
678 0 : Py_DECREF(bytes);
679 0 : return 0;
680 : }
681 :
682 360 : path->wide = NULL;
683 360 : path->narrow = narrow;
684 360 : path->length = length;
685 360 : path->object = o;
686 360 : path->fd = -1;
687 360 : path->cleanup = bytes;
688 360 : return Py_CLEANUP_SUPPORTED;
689 : }
690 :
691 : static void
692 0 : argument_unavailable_error(char *function_name, char *argument_name) {
693 0 : PyErr_Format(PyExc_NotImplementedError,
694 : "%s%s%s unavailable on this platform",
695 : (function_name != NULL) ? function_name : "",
696 : (function_name != NULL) ? ": ": "",
697 : argument_name);
698 0 : }
699 :
700 : static int
701 1 : dir_fd_unavailable(PyObject *o, void *p) {
702 1 : int *dir_fd = (int *)p;
703 1 : int return_value = _fd_converter(o, dir_fd, DEFAULT_DIR_FD);
704 1 : if (!return_value)
705 0 : return 0;
706 1 : if (*dir_fd == DEFAULT_DIR_FD)
707 1 : return 1;
708 0 : argument_unavailable_error(NULL, "dir_fd");
709 0 : return 0;
710 : }
711 :
712 : static int
713 1 : fd_specified(char *function_name, int fd) {
714 1 : if (fd == -1)
715 1 : return 0;
716 :
717 0 : argument_unavailable_error(function_name, "fd");
718 0 : return 1;
719 : }
720 :
721 : static int
722 1 : follow_symlinks_specified(char *function_name, int follow_symlinks) {
723 1 : if (follow_symlinks)
724 1 : return 0;
725 :
726 0 : argument_unavailable_error(function_name, "follow_symlinks");
727 0 : return 1;
728 : }
729 :
730 : static int
731 347 : path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) {
732 347 : if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) {
733 0 : PyErr_Format(PyExc_ValueError,
734 : "%s: can't specify dir_fd without matching path",
735 : function_name);
736 0 : return 1;
737 : }
738 347 : return 0;
739 : }
740 :
741 : static int
742 347 : dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) {
743 347 : if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
744 0 : PyErr_Format(PyExc_ValueError,
745 : "%s: can't specify both dir_fd and fd",
746 : function_name);
747 0 : return 1;
748 : }
749 347 : return 0;
750 : }
751 :
752 : static int
753 347 : fd_and_follow_symlinks_invalid(char *function_name, int fd,
754 : int follow_symlinks) {
755 347 : if ((fd > 0) && (!follow_symlinks)) {
756 0 : PyErr_Format(PyExc_ValueError,
757 : "%s: cannot use fd and follow_symlinks together",
758 : function_name);
759 0 : return 1;
760 : }
761 347 : return 0;
762 : }
763 :
764 : static int
765 1 : dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd,
766 : int follow_symlinks) {
767 1 : if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
768 0 : PyErr_Format(PyExc_ValueError,
769 : "%s: cannot use dir_fd and follow_symlinks together",
770 : function_name);
771 0 : return 1;
772 : }
773 1 : return 0;
774 : }
775 :
776 : /* A helper used by a number of POSIX-only functions */
777 : #ifndef MS_WINDOWS
778 : static int
779 0 : _parse_off_t(PyObject* arg, void* addr)
780 : {
781 : #if !defined(HAVE_LARGEFILE_SUPPORT)
782 : *((off_t*)addr) = PyLong_AsLong(arg);
783 : #else
784 0 : *((off_t*)addr) = PyLong_AsLongLong(arg);
785 : #endif
786 0 : if (PyErr_Occurred())
787 0 : return 0;
788 0 : return 1;
789 : }
790 : #endif
791 :
792 : #if defined _MSC_VER && _MSC_VER >= 1400
793 : /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
794 : * valid and throw an assertion if it isn't.
795 : * Normally, an invalid fd is likely to be a C program error and therefore
796 : * an assertion can be useful, but it does contradict the POSIX standard
797 : * which for write(2) states:
798 : * "Otherwise, -1 shall be returned and errno set to indicate the error."
799 : * "[EBADF] The fildes argument is not a valid file descriptor open for
800 : * writing."
801 : * Furthermore, python allows the user to enter any old integer
802 : * as a fd and should merely raise a python exception on error.
803 : * The Microsoft CRT doesn't provide an official way to check for the
804 : * validity of a file descriptor, but we can emulate its internal behaviour
805 : * by using the exported __pinfo data member and knowledge of the
806 : * internal structures involved.
807 : * The structures below must be updated for each version of visual studio
808 : * according to the file internal.h in the CRT source, until MS comes
809 : * up with a less hacky way to do this.
810 : * (all of this is to avoid globally modifying the CRT behaviour using
811 : * _set_invalid_parameter_handler() and _CrtSetReportMode())
812 : */
813 : /* The actual size of the structure is determined at runtime.
814 : * Only the first items must be present.
815 : */
816 : typedef struct {
817 : intptr_t osfhnd;
818 : char osfile;
819 : } my_ioinfo;
820 :
821 : extern __declspec(dllimport) char * __pioinfo[];
822 : #define IOINFO_L2E 5
823 : #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
824 : #define IOINFO_ARRAYS 64
825 : #define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
826 : #define FOPEN 0x01
827 : #define _NO_CONSOLE_FILENO (intptr_t)-2
828 :
829 : /* This function emulates what the windows CRT does to validate file handles */
830 : int
831 : _PyVerify_fd(int fd)
832 : {
833 : const int i1 = fd >> IOINFO_L2E;
834 : const int i2 = fd & ((1 << IOINFO_L2E) - 1);
835 :
836 : static size_t sizeof_ioinfo = 0;
837 :
838 : /* Determine the actual size of the ioinfo structure,
839 : * as used by the CRT loaded in memory
840 : */
841 : if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
842 : sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
843 : }
844 : if (sizeof_ioinfo == 0) {
845 : /* This should not happen... */
846 : goto fail;
847 : }
848 :
849 : /* See that it isn't a special CLEAR fileno */
850 : if (fd != _NO_CONSOLE_FILENO) {
851 : /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that. Instead
852 : * we check pointer validity and other info
853 : */
854 : if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
855 : /* finally, check that the file is open */
856 : my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
857 : if (info->osfile & FOPEN) {
858 : return 1;
859 : }
860 : }
861 : }
862 : fail:
863 : errno = EBADF;
864 : return 0;
865 : }
866 :
867 : /* the special case of checking dup2. The target fd must be in a sensible range */
868 : static int
869 : _PyVerify_fd_dup2(int fd1, int fd2)
870 : {
871 : if (!_PyVerify_fd(fd1))
872 : return 0;
873 : if (fd2 == _NO_CONSOLE_FILENO)
874 : return 0;
875 : if ((unsigned)fd2 < _NHANDLE_)
876 : return 1;
877 : else
878 : return 0;
879 : }
880 : #else
881 : /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
882 : #define _PyVerify_fd_dup2(A, B) (1)
883 : #endif
884 :
885 : #ifdef MS_WINDOWS
886 : /* The following structure was copied from
887 : http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
888 : include doesn't seem to be present in the Windows SDK (at least as included
889 : with Visual Studio Express). */
890 : typedef struct _REPARSE_DATA_BUFFER {
891 : ULONG ReparseTag;
892 : USHORT ReparseDataLength;
893 : USHORT Reserved;
894 : union {
895 : struct {
896 : USHORT SubstituteNameOffset;
897 : USHORT SubstituteNameLength;
898 : USHORT PrintNameOffset;
899 : USHORT PrintNameLength;
900 : ULONG Flags;
901 : WCHAR PathBuffer[1];
902 : } SymbolicLinkReparseBuffer;
903 :
904 : struct {
905 : USHORT SubstituteNameOffset;
906 : USHORT SubstituteNameLength;
907 : USHORT PrintNameOffset;
908 : USHORT PrintNameLength;
909 : WCHAR PathBuffer[1];
910 : } MountPointReparseBuffer;
911 :
912 : struct {
913 : UCHAR DataBuffer[1];
914 : } GenericReparseBuffer;
915 : };
916 : } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
917 :
918 : #define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER,\
919 : GenericReparseBuffer)
920 : #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE ( 16 * 1024 )
921 :
922 : static int
923 : win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
924 : {
925 : char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
926 : REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
927 : DWORD n_bytes_returned;
928 :
929 : if (0 == DeviceIoControl(
930 : reparse_point_handle,
931 : FSCTL_GET_REPARSE_POINT,
932 : NULL, 0, /* in buffer */
933 : target_buffer, sizeof(target_buffer),
934 : &n_bytes_returned,
935 : NULL)) /* we're not using OVERLAPPED_IO */
936 : return FALSE;
937 :
938 : if (reparse_tag)
939 : *reparse_tag = rdb->ReparseTag;
940 :
941 : return TRUE;
942 : }
943 :
944 : #endif /* MS_WINDOWS */
945 :
946 : /* Return a dictionary corresponding to the POSIX environment table */
947 : #ifdef WITH_NEXT_FRAMEWORK
948 : /* On Darwin/MacOSX a shared library or framework has no access to
949 : ** environ directly, we must obtain it with _NSGetEnviron().
950 : */
951 : #include <crt_externs.h>
952 : static char **environ;
953 : #elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
954 : extern char **environ;
955 : #endif /* !_MSC_VER */
956 :
957 : static PyObject *
958 1 : convertenviron(void)
959 : {
960 : PyObject *d;
961 : #ifdef MS_WINDOWS
962 : wchar_t **e;
963 : #else
964 : char **e;
965 : #endif
966 : #if defined(PYOS_OS2)
967 : APIRET rc;
968 : char buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
969 : #endif
970 :
971 1 : d = PyDict_New();
972 1 : if (d == NULL)
973 0 : return NULL;
974 : #ifdef WITH_NEXT_FRAMEWORK
975 : if (environ == NULL)
976 : environ = *_NSGetEnviron();
977 : #endif
978 : #ifdef MS_WINDOWS
979 : /* _wenviron must be initialized in this way if the program is started
980 : through main() instead of wmain(). */
981 : _wgetenv(L"");
982 : if (_wenviron == NULL)
983 : return d;
984 : /* This part ignores errors */
985 : for (e = _wenviron; *e != NULL; e++) {
986 : PyObject *k;
987 : PyObject *v;
988 : wchar_t *p = wcschr(*e, L'=');
989 : if (p == NULL)
990 : continue;
991 : k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
992 : if (k == NULL) {
993 : PyErr_Clear();
994 : continue;
995 : }
996 : v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
997 : if (v == NULL) {
998 : PyErr_Clear();
999 : Py_DECREF(k);
1000 : continue;
1001 : }
1002 : if (PyDict_GetItem(d, k) == NULL) {
1003 : if (PyDict_SetItem(d, k, v) != 0)
1004 : PyErr_Clear();
1005 : }
1006 : Py_DECREF(k);
1007 : Py_DECREF(v);
1008 : }
1009 : #else
1010 1 : if (environ == NULL)
1011 0 : return d;
1012 : /* This part ignores errors */
1013 747 : for (e = environ; *e != NULL; e++) {
1014 : PyObject *k;
1015 : PyObject *v;
1016 746 : char *p = strchr(*e, '=');
1017 746 : if (p == NULL)
1018 0 : continue;
1019 746 : k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1020 746 : if (k == NULL) {
1021 0 : PyErr_Clear();
1022 0 : continue;
1023 : }
1024 746 : v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1025 746 : if (v == NULL) {
1026 0 : PyErr_Clear();
1027 0 : Py_DECREF(k);
1028 0 : continue;
1029 : }
1030 746 : if (PyDict_GetItem(d, k) == NULL) {
1031 746 : if (PyDict_SetItem(d, k, v) != 0)
1032 0 : PyErr_Clear();
1033 : }
1034 746 : Py_DECREF(k);
1035 746 : Py_DECREF(v);
1036 : }
1037 : #endif
1038 : #if defined(PYOS_OS2)
1039 : rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
1040 : if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
1041 : PyObject *v = PyBytes_FromString(buffer);
1042 : PyDict_SetItemString(d, "BEGINLIBPATH", v);
1043 : Py_DECREF(v);
1044 : }
1045 : rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
1046 : if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
1047 : PyObject *v = PyBytes_FromString(buffer);
1048 : PyDict_SetItemString(d, "ENDLIBPATH", v);
1049 : Py_DECREF(v);
1050 : }
1051 : #endif
1052 1 : return d;
1053 : }
1054 :
1055 : /* Set a POSIX-specific error from errno, and return NULL */
1056 :
1057 : static PyObject *
1058 0 : posix_error(void)
1059 : {
1060 0 : return PyErr_SetFromErrno(PyExc_OSError);
1061 : }
1062 : static PyObject *
1063 23 : posix_error_with_filename(char* name)
1064 : {
1065 23 : return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
1066 : }
1067 :
1068 :
1069 : static PyObject *
1070 0 : posix_error_with_allocated_filename(PyObject* name)
1071 : {
1072 : PyObject *name_str, *rc;
1073 0 : name_str = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AsString(name),
1074 : PyBytes_GET_SIZE(name));
1075 0 : Py_DECREF(name);
1076 0 : rc = PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
1077 : name_str);
1078 0 : Py_XDECREF(name_str);
1079 0 : return rc;
1080 : }
1081 :
1082 : #ifdef MS_WINDOWS
1083 : static PyObject *
1084 : win32_error(char* function, const char* filename)
1085 : {
1086 : /* XXX We should pass the function name along in the future.
1087 : (winreg.c also wants to pass the function name.)
1088 : This would however require an additional param to the
1089 : Windows error object, which is non-trivial.
1090 : */
1091 : errno = GetLastError();
1092 : if (filename)
1093 : return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1094 : else
1095 : return PyErr_SetFromWindowsErr(errno);
1096 : }
1097 :
1098 : static PyObject *
1099 : win32_error_unicode(char* function, wchar_t* filename)
1100 : {
1101 : /* XXX - see win32_error for comments on 'function' */
1102 : errno = GetLastError();
1103 : if (filename)
1104 : return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
1105 : else
1106 : return PyErr_SetFromWindowsErr(errno);
1107 : }
1108 :
1109 : static PyObject *
1110 : win32_error_object(char* function, PyObject* filename)
1111 : {
1112 : /* XXX - see win32_error for comments on 'function' */
1113 : errno = GetLastError();
1114 : if (filename)
1115 : return PyErr_SetExcFromWindowsErrWithFilenameObject(
1116 : PyExc_WindowsError,
1117 : errno,
1118 : filename);
1119 : else
1120 : return PyErr_SetFromWindowsErr(errno);
1121 : }
1122 :
1123 : #endif /* MS_WINDOWS */
1124 :
1125 : /*
1126 : * Some functions return Win32 errors, others only ever use posix_error
1127 : * (this is for backwards compatibility with exceptions)
1128 : */
1129 : static PyObject *
1130 23 : path_posix_error(char *function_name, path_t *path)
1131 : {
1132 23 : if (path->narrow)
1133 23 : return posix_error_with_filename(path->narrow);
1134 0 : return posix_error();
1135 : }
1136 :
1137 : static PyObject *
1138 23 : path_error(char *function_name, path_t *path)
1139 : {
1140 : #ifdef MS_WINDOWS
1141 : if (path->narrow)
1142 : return win32_error(function_name, path->narrow);
1143 : if (path->wide)
1144 : return win32_error_unicode(function_name, path->wide);
1145 : return win32_error(function_name, NULL);
1146 : #else
1147 23 : return path_posix_error(function_name, path);
1148 : #endif
1149 : }
1150 :
1151 : #if defined(PYOS_OS2)
1152 : /**********************************************************************
1153 : * Helper Function to Trim and Format OS/2 Messages
1154 : **********************************************************************/
1155 : static void
1156 : os2_formatmsg(char *msgbuf, int msglen, char *reason)
1157 : {
1158 : msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
1159 :
1160 : if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
1161 : char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
1162 :
1163 : while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
1164 : *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
1165 : }
1166 :
1167 : /* Add Optional Reason Text */
1168 : if (reason) {
1169 : strcat(msgbuf, " : ");
1170 : strcat(msgbuf, reason);
1171 : }
1172 : }
1173 :
1174 : /**********************************************************************
1175 : * Decode an OS/2 Operating System Error Code
1176 : *
1177 : * A convenience function to lookup an OS/2 error code and return a
1178 : * text message we can use to raise a Python exception.
1179 : *
1180 : * Notes:
1181 : * The messages for errors returned from the OS/2 kernel reside in
1182 : * the file OSO001.MSG in the \OS2 directory hierarchy.
1183 : *
1184 : **********************************************************************/
1185 : static char *
1186 : os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
1187 : {
1188 : APIRET rc;
1189 : ULONG msglen;
1190 :
1191 : /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
1192 : Py_BEGIN_ALLOW_THREADS
1193 : rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
1194 : errorcode, "oso001.msg", &msglen);
1195 : Py_END_ALLOW_THREADS
1196 :
1197 : if (rc == NO_ERROR)
1198 : os2_formatmsg(msgbuf, msglen, reason);
1199 : else
1200 : PyOS_snprintf(msgbuf, msgbuflen,
1201 : "unknown OS error #%d", errorcode);
1202 :
1203 : return msgbuf;
1204 : }
1205 :
1206 : /* Set an OS/2-specific error and return NULL. OS/2 kernel
1207 : errors are not in a global variable e.g. 'errno' nor are
1208 : they congruent with posix error numbers. */
1209 :
1210 : static PyObject *
1211 : os2_error(int code)
1212 : {
1213 : char text[1024];
1214 : PyObject *v;
1215 :
1216 : os2_strerror(text, sizeof(text), code, "");
1217 :
1218 : v = Py_BuildValue("(is)", code, text);
1219 : if (v != NULL) {
1220 : PyErr_SetObject(PyExc_OSError, v);
1221 : Py_DECREF(v);
1222 : }
1223 : return NULL; /* Signal to Python that an Exception is Pending */
1224 : }
1225 :
1226 : #endif /* OS2 */
1227 :
1228 : /* POSIX generic methods */
1229 :
1230 : static PyObject *
1231 0 : posix_fildes(PyObject *fdobj, int (*func)(int))
1232 : {
1233 : int fd;
1234 : int res;
1235 0 : fd = PyObject_AsFileDescriptor(fdobj);
1236 0 : if (fd < 0)
1237 0 : return NULL;
1238 : if (!_PyVerify_fd(fd))
1239 : return posix_error();
1240 0 : Py_BEGIN_ALLOW_THREADS
1241 0 : res = (*func)(fd);
1242 0 : Py_END_ALLOW_THREADS
1243 0 : if (res < 0)
1244 0 : return posix_error();
1245 0 : Py_INCREF(Py_None);
1246 0 : return Py_None;
1247 : }
1248 :
1249 : static PyObject *
1250 0 : posix_1str(PyObject *args, char *format, int (*func)(const char*))
1251 : {
1252 0 : PyObject *opath1 = NULL;
1253 : char *path1;
1254 : int res;
1255 0 : if (!PyArg_ParseTuple(args, format,
1256 : PyUnicode_FSConverter, &opath1))
1257 0 : return NULL;
1258 0 : path1 = PyBytes_AsString(opath1);
1259 0 : Py_BEGIN_ALLOW_THREADS
1260 0 : res = (*func)(path1);
1261 0 : Py_END_ALLOW_THREADS
1262 0 : if (res < 0)
1263 0 : return posix_error_with_allocated_filename(opath1);
1264 0 : Py_DECREF(opath1);
1265 0 : Py_INCREF(Py_None);
1266 0 : return Py_None;
1267 : }
1268 :
1269 :
1270 : #ifdef MS_WINDOWS
1271 : static PyObject*
1272 : win32_1str(PyObject* args, char* func,
1273 : char* format, BOOL (__stdcall *funcA)(LPCSTR),
1274 : char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
1275 : {
1276 : PyObject *uni;
1277 : const char *ansi;
1278 : BOOL result;
1279 :
1280 : if (PyArg_ParseTuple(args, wformat, &uni))
1281 : {
1282 : wchar_t *wstr = PyUnicode_AsUnicode(uni);
1283 : if (wstr == NULL)
1284 : return NULL;
1285 : Py_BEGIN_ALLOW_THREADS
1286 : result = funcW(wstr);
1287 : Py_END_ALLOW_THREADS
1288 : if (!result)
1289 : return win32_error_object(func, uni);
1290 : Py_INCREF(Py_None);
1291 : return Py_None;
1292 : }
1293 : PyErr_Clear();
1294 :
1295 : if (!PyArg_ParseTuple(args, format, &ansi))
1296 : return NULL;
1297 : if (win32_warn_bytes_api())
1298 : return NULL;
1299 : Py_BEGIN_ALLOW_THREADS
1300 : result = funcA(ansi);
1301 : Py_END_ALLOW_THREADS
1302 : if (!result)
1303 : return win32_error(func, ansi);
1304 : Py_INCREF(Py_None);
1305 : return Py_None;
1306 :
1307 : }
1308 :
1309 : /* This is a reimplementation of the C library's chdir function,
1310 : but one that produces Win32 errors instead of DOS error codes.
1311 : chdir is essentially a wrapper around SetCurrentDirectory; however,
1312 : it also needs to set "magic" environment variables indicating
1313 : the per-drive current directory, which are of the form =<drive>: */
1314 : static BOOL __stdcall
1315 : win32_chdir(LPCSTR path)
1316 : {
1317 : char new_path[MAX_PATH+1];
1318 : int result;
1319 : char env[4] = "=x:";
1320 :
1321 : if(!SetCurrentDirectoryA(path))
1322 : return FALSE;
1323 : result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
1324 : if (!result)
1325 : return FALSE;
1326 : /* In the ANSI API, there should not be any paths longer
1327 : than MAX_PATH. */
1328 : assert(result <= MAX_PATH+1);
1329 : if (strncmp(new_path, "\\\\", 2) == 0 ||
1330 : strncmp(new_path, "//", 2) == 0)
1331 : /* UNC path, nothing to do. */
1332 : return TRUE;
1333 : env[1] = new_path[0];
1334 : return SetEnvironmentVariableA(env, new_path);
1335 : }
1336 :
1337 : /* The Unicode version differs from the ANSI version
1338 : since the current directory might exceed MAX_PATH characters */
1339 : static BOOL __stdcall
1340 : win32_wchdir(LPCWSTR path)
1341 : {
1342 : wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
1343 : int result;
1344 : wchar_t env[4] = L"=x:";
1345 :
1346 : if(!SetCurrentDirectoryW(path))
1347 : return FALSE;
1348 : result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
1349 : if (!result)
1350 : return FALSE;
1351 : if (result > MAX_PATH+1) {
1352 : new_path = malloc(result * sizeof(wchar_t));
1353 : if (!new_path) {
1354 : SetLastError(ERROR_OUTOFMEMORY);
1355 : return FALSE;
1356 : }
1357 : result = GetCurrentDirectoryW(result, new_path);
1358 : if (!result) {
1359 : free(new_path);
1360 : return FALSE;
1361 : }
1362 : }
1363 : if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1364 : wcsncmp(new_path, L"//", 2) == 0)
1365 : /* UNC path, nothing to do. */
1366 : return TRUE;
1367 : env[1] = new_path[0];
1368 : result = SetEnvironmentVariableW(env, new_path);
1369 : if (new_path != _new_path)
1370 : free(new_path);
1371 : return result;
1372 : }
1373 : #endif
1374 :
1375 : #ifdef MS_WINDOWS
1376 : /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1377 : - time stamps are restricted to second resolution
1378 : - file modification times suffer from forth-and-back conversions between
1379 : UTC and local time
1380 : Therefore, we implement our own stat, based on the Win32 API directly.
1381 : */
1382 : #define HAVE_STAT_NSEC 1
1383 :
1384 : struct win32_stat{
1385 : int st_dev;
1386 : __int64 st_ino;
1387 : unsigned short st_mode;
1388 : int st_nlink;
1389 : int st_uid;
1390 : int st_gid;
1391 : int st_rdev;
1392 : __int64 st_size;
1393 : time_t st_atime;
1394 : int st_atime_nsec;
1395 : time_t st_mtime;
1396 : int st_mtime_nsec;
1397 : time_t st_ctime;
1398 : int st_ctime_nsec;
1399 : };
1400 :
1401 : static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
1402 :
1403 : static void
1404 : FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
1405 : {
1406 : /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
1407 : /* Cannot simply cast and dereference in_ptr,
1408 : since it might not be aligned properly */
1409 : __int64 in;
1410 : memcpy(&in, in_ptr, sizeof(in));
1411 : *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
1412 : *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
1413 : }
1414 :
1415 : static void
1416 : time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
1417 : {
1418 : /* XXX endianness */
1419 : __int64 out;
1420 : out = time_in + secs_between_epochs;
1421 : out = out * 10000000 + nsec_in / 100;
1422 : memcpy(out_ptr, &out, sizeof(out));
1423 : }
1424 :
1425 : /* Below, we *know* that ugo+r is 0444 */
1426 : #if _S_IREAD != 0400
1427 : #error Unsupported C library
1428 : #endif
1429 : static int
1430 : attributes_to_mode(DWORD attr)
1431 : {
1432 : int m = 0;
1433 : if (attr & FILE_ATTRIBUTE_DIRECTORY)
1434 : m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
1435 : else
1436 : m |= _S_IFREG;
1437 : if (attr & FILE_ATTRIBUTE_READONLY)
1438 : m |= 0444;
1439 : else
1440 : m |= 0666;
1441 : return m;
1442 : }
1443 :
1444 : static int
1445 : attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct win32_stat *result)
1446 : {
1447 : memset(result, 0, sizeof(*result));
1448 : result->st_mode = attributes_to_mode(info->dwFileAttributes);
1449 : result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
1450 : FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
1451 : FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1452 : FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
1453 : result->st_nlink = info->nNumberOfLinks;
1454 : result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
1455 : if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
1456 : /* first clear the S_IFMT bits */
1457 : result->st_mode ^= (result->st_mode & 0170000);
1458 : /* now set the bits that make this a symlink */
1459 : result->st_mode |= 0120000;
1460 : }
1461 :
1462 : return 0;
1463 : }
1464 :
1465 : static BOOL
1466 : attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1467 : {
1468 : HANDLE hFindFile;
1469 : WIN32_FIND_DATAA FileData;
1470 : hFindFile = FindFirstFileA(pszFile, &FileData);
1471 : if (hFindFile == INVALID_HANDLE_VALUE)
1472 : return FALSE;
1473 : FindClose(hFindFile);
1474 : memset(info, 0, sizeof(*info));
1475 : *reparse_tag = 0;
1476 : info->dwFileAttributes = FileData.dwFileAttributes;
1477 : info->ftCreationTime = FileData.ftCreationTime;
1478 : info->ftLastAccessTime = FileData.ftLastAccessTime;
1479 : info->ftLastWriteTime = FileData.ftLastWriteTime;
1480 : info->nFileSizeHigh = FileData.nFileSizeHigh;
1481 : info->nFileSizeLow = FileData.nFileSizeLow;
1482 : /* info->nNumberOfLinks = 1; */
1483 : if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1484 : *reparse_tag = FileData.dwReserved0;
1485 : return TRUE;
1486 : }
1487 :
1488 : static BOOL
1489 : attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1490 : {
1491 : HANDLE hFindFile;
1492 : WIN32_FIND_DATAW FileData;
1493 : hFindFile = FindFirstFileW(pszFile, &FileData);
1494 : if (hFindFile == INVALID_HANDLE_VALUE)
1495 : return FALSE;
1496 : FindClose(hFindFile);
1497 : memset(info, 0, sizeof(*info));
1498 : *reparse_tag = 0;
1499 : info->dwFileAttributes = FileData.dwFileAttributes;
1500 : info->ftCreationTime = FileData.ftCreationTime;
1501 : info->ftLastAccessTime = FileData.ftLastAccessTime;
1502 : info->ftLastWriteTime = FileData.ftLastWriteTime;
1503 : info->nFileSizeHigh = FileData.nFileSizeHigh;
1504 : info->nFileSizeLow = FileData.nFileSizeLow;
1505 : /* info->nNumberOfLinks = 1; */
1506 : if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1507 : *reparse_tag = FileData.dwReserved0;
1508 : return TRUE;
1509 : }
1510 :
1511 : /* Grab GetFinalPathNameByHandle dynamically from kernel32 */
1512 : static int has_GetFinalPathNameByHandle = 0;
1513 : static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
1514 : DWORD);
1515 : static int
1516 : check_GetFinalPathNameByHandle()
1517 : {
1518 : HINSTANCE hKernel32;
1519 : DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
1520 : DWORD);
1521 :
1522 : /* only recheck */
1523 : if (!has_GetFinalPathNameByHandle)
1524 : {
1525 : hKernel32 = GetModuleHandleW(L"KERNEL32");
1526 : *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
1527 : "GetFinalPathNameByHandleA");
1528 : *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
1529 : "GetFinalPathNameByHandleW");
1530 : has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
1531 : Py_GetFinalPathNameByHandleW;
1532 : }
1533 : return has_GetFinalPathNameByHandle;
1534 : }
1535 :
1536 : static BOOL
1537 : get_target_path(HANDLE hdl, wchar_t **target_path)
1538 : {
1539 : int buf_size, result_length;
1540 : wchar_t *buf;
1541 :
1542 : /* We have a good handle to the target, use it to determine
1543 : the target path name (then we'll call lstat on it). */
1544 : buf_size = Py_GetFinalPathNameByHandleW(hdl, 0, 0,
1545 : VOLUME_NAME_DOS);
1546 : if(!buf_size)
1547 : return FALSE;
1548 :
1549 : buf = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
1550 : if (!buf) {
1551 : SetLastError(ERROR_OUTOFMEMORY);
1552 : return FALSE;
1553 : }
1554 :
1555 : result_length = Py_GetFinalPathNameByHandleW(hdl,
1556 : buf, buf_size, VOLUME_NAME_DOS);
1557 :
1558 : if(!result_length) {
1559 : free(buf);
1560 : return FALSE;
1561 : }
1562 :
1563 : if(!CloseHandle(hdl)) {
1564 : free(buf);
1565 : return FALSE;
1566 : }
1567 :
1568 : buf[result_length] = 0;
1569 :
1570 : *target_path = buf;
1571 : return TRUE;
1572 : }
1573 :
1574 : static int
1575 : win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
1576 : BOOL traverse);
1577 : static int
1578 : win32_xstat_impl(const char *path, struct win32_stat *result,
1579 : BOOL traverse)
1580 : {
1581 : int code;
1582 : HANDLE hFile, hFile2;
1583 : BY_HANDLE_FILE_INFORMATION info;
1584 : ULONG reparse_tag = 0;
1585 : wchar_t *target_path;
1586 : const char *dot;
1587 :
1588 : if(!check_GetFinalPathNameByHandle()) {
1589 : /* If the OS doesn't have GetFinalPathNameByHandle, don't
1590 : traverse reparse point. */
1591 : traverse = FALSE;
1592 : }
1593 :
1594 : hFile = CreateFileA(
1595 : path,
1596 : FILE_READ_ATTRIBUTES, /* desired access */
1597 : 0, /* share mode */
1598 : NULL, /* security attributes */
1599 : OPEN_EXISTING,
1600 : /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1601 : /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
1602 : Because of this, calls like GetFinalPathNameByHandle will return
1603 : the symlink path agin and not the actual final path. */
1604 : FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
1605 : FILE_FLAG_OPEN_REPARSE_POINT,
1606 : NULL);
1607 :
1608 : if (hFile == INVALID_HANDLE_VALUE) {
1609 : /* Either the target doesn't exist, or we don't have access to
1610 : get a handle to it. If the former, we need to return an error.
1611 : If the latter, we can use attributes_from_dir. */
1612 : if (GetLastError() != ERROR_SHARING_VIOLATION)
1613 : return -1;
1614 : /* Could not get attributes on open file. Fall back to
1615 : reading the directory. */
1616 : if (!attributes_from_dir(path, &info, &reparse_tag))
1617 : /* Very strange. This should not fail now */
1618 : return -1;
1619 : if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1620 : if (traverse) {
1621 : /* Should traverse, but could not open reparse point handle */
1622 : SetLastError(ERROR_SHARING_VIOLATION);
1623 : return -1;
1624 : }
1625 : }
1626 : } else {
1627 : if (!GetFileInformationByHandle(hFile, &info)) {
1628 : CloseHandle(hFile);
1629 : return -1;
1630 : }
1631 : if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1632 : if (!win32_get_reparse_tag(hFile, &reparse_tag))
1633 : return -1;
1634 :
1635 : /* Close the outer open file handle now that we're about to
1636 : reopen it with different flags. */
1637 : if (!CloseHandle(hFile))
1638 : return -1;
1639 :
1640 : if (traverse) {
1641 : /* In order to call GetFinalPathNameByHandle we need to open
1642 : the file without the reparse handling flag set. */
1643 : hFile2 = CreateFileA(
1644 : path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
1645 : NULL, OPEN_EXISTING,
1646 : FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
1647 : NULL);
1648 : if (hFile2 == INVALID_HANDLE_VALUE)
1649 : return -1;
1650 :
1651 : if (!get_target_path(hFile2, &target_path))
1652 : return -1;
1653 :
1654 : code = win32_xstat_impl_w(target_path, result, FALSE);
1655 : free(target_path);
1656 : return code;
1657 : }
1658 : } else
1659 : CloseHandle(hFile);
1660 : }
1661 : attribute_data_to_stat(&info, reparse_tag, result);
1662 :
1663 : /* Set S_IEXEC if it is an .exe, .bat, ... */
1664 : dot = strrchr(path, '.');
1665 : if (dot) {
1666 : if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
1667 : stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
1668 : result->st_mode |= 0111;
1669 : }
1670 : return 0;
1671 : }
1672 :
1673 : static int
1674 : win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
1675 : BOOL traverse)
1676 : {
1677 : int code;
1678 : HANDLE hFile, hFile2;
1679 : BY_HANDLE_FILE_INFORMATION info;
1680 : ULONG reparse_tag = 0;
1681 : wchar_t *target_path;
1682 : const wchar_t *dot;
1683 :
1684 : if(!check_GetFinalPathNameByHandle()) {
1685 : /* If the OS doesn't have GetFinalPathNameByHandle, don't
1686 : traverse reparse point. */
1687 : traverse = FALSE;
1688 : }
1689 :
1690 : hFile = CreateFileW(
1691 : path,
1692 : FILE_READ_ATTRIBUTES, /* desired access */
1693 : 0, /* share mode */
1694 : NULL, /* security attributes */
1695 : OPEN_EXISTING,
1696 : /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1697 : /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
1698 : Because of this, calls like GetFinalPathNameByHandle will return
1699 : the symlink path agin and not the actual final path. */
1700 : FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
1701 : FILE_FLAG_OPEN_REPARSE_POINT,
1702 : NULL);
1703 :
1704 : if (hFile == INVALID_HANDLE_VALUE) {
1705 : /* Either the target doesn't exist, or we don't have access to
1706 : get a handle to it. If the former, we need to return an error.
1707 : If the latter, we can use attributes_from_dir. */
1708 : if (GetLastError() != ERROR_SHARING_VIOLATION)
1709 : return -1;
1710 : /* Could not get attributes on open file. Fall back to
1711 : reading the directory. */
1712 : if (!attributes_from_dir_w(path, &info, &reparse_tag))
1713 : /* Very strange. This should not fail now */
1714 : return -1;
1715 : if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1716 : if (traverse) {
1717 : /* Should traverse, but could not open reparse point handle */
1718 : SetLastError(ERROR_SHARING_VIOLATION);
1719 : return -1;
1720 : }
1721 : }
1722 : } else {
1723 : if (!GetFileInformationByHandle(hFile, &info)) {
1724 : CloseHandle(hFile);
1725 : return -1;
1726 : }
1727 : if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1728 : if (!win32_get_reparse_tag(hFile, &reparse_tag))
1729 : return -1;
1730 :
1731 : /* Close the outer open file handle now that we're about to
1732 : reopen it with different flags. */
1733 : if (!CloseHandle(hFile))
1734 : return -1;
1735 :
1736 : if (traverse) {
1737 : /* In order to call GetFinalPathNameByHandle we need to open
1738 : the file without the reparse handling flag set. */
1739 : hFile2 = CreateFileW(
1740 : path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
1741 : NULL, OPEN_EXISTING,
1742 : FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
1743 : NULL);
1744 : if (hFile2 == INVALID_HANDLE_VALUE)
1745 : return -1;
1746 :
1747 : if (!get_target_path(hFile2, &target_path))
1748 : return -1;
1749 :
1750 : code = win32_xstat_impl_w(target_path, result, FALSE);
1751 : free(target_path);
1752 : return code;
1753 : }
1754 : } else
1755 : CloseHandle(hFile);
1756 : }
1757 : attribute_data_to_stat(&info, reparse_tag, result);
1758 :
1759 : /* Set S_IEXEC if it is an .exe, .bat, ... */
1760 : dot = wcsrchr(path, '.');
1761 : if (dot) {
1762 : if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
1763 : _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
1764 : result->st_mode |= 0111;
1765 : }
1766 : return 0;
1767 : }
1768 :
1769 : static int
1770 : win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
1771 : {
1772 : /* Protocol violation: we explicitly clear errno, instead of
1773 : setting it to a POSIX error. Callers should use GetLastError. */
1774 : int code = win32_xstat_impl(path, result, traverse);
1775 : errno = 0;
1776 : return code;
1777 : }
1778 :
1779 : static int
1780 : win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
1781 : {
1782 : /* Protocol violation: we explicitly clear errno, instead of
1783 : setting it to a POSIX error. Callers should use GetLastError. */
1784 : int code = win32_xstat_impl_w(path, result, traverse);
1785 : errno = 0;
1786 : return code;
1787 : }
1788 : /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1789 :
1790 : In Posix, stat automatically traverses symlinks and returns the stat
1791 : structure for the target. In Windows, the equivalent GetFileAttributes by
1792 : default does not traverse symlinks and instead returns attributes for
1793 : the symlink.
1794 :
1795 : Therefore, win32_lstat will get the attributes traditionally, and
1796 : win32_stat will first explicitly resolve the symlink target and then will
1797 : call win32_lstat on that result.
1798 :
1799 : The _w represent Unicode equivalents of the aforementioned ANSI functions. */
1800 :
1801 : static int
1802 : win32_lstat(const char* path, struct win32_stat *result)
1803 : {
1804 : return win32_xstat(path, result, FALSE);
1805 : }
1806 :
1807 : static int
1808 : win32_lstat_w(const wchar_t* path, struct win32_stat *result)
1809 : {
1810 : return win32_xstat_w(path, result, FALSE);
1811 : }
1812 :
1813 : static int
1814 : win32_stat(const char* path, struct win32_stat *result)
1815 : {
1816 : return win32_xstat(path, result, TRUE);
1817 : }
1818 :
1819 : static int
1820 : win32_stat_w(const wchar_t* path, struct win32_stat *result)
1821 : {
1822 : return win32_xstat_w(path, result, TRUE);
1823 : }
1824 :
1825 : static int
1826 : win32_fstat(int file_number, struct win32_stat *result)
1827 : {
1828 : BY_HANDLE_FILE_INFORMATION info;
1829 : HANDLE h;
1830 : int type;
1831 :
1832 : if (!_PyVerify_fd(file_number))
1833 : h = INVALID_HANDLE_VALUE;
1834 : else
1835 : h = (HANDLE)_get_osfhandle(file_number);
1836 :
1837 : /* Protocol violation: we explicitly clear errno, instead of
1838 : setting it to a POSIX error. Callers should use GetLastError. */
1839 : errno = 0;
1840 :
1841 : if (h == INVALID_HANDLE_VALUE) {
1842 : /* This is really a C library error (invalid file handle).
1843 : We set the Win32 error to the closes one matching. */
1844 : SetLastError(ERROR_INVALID_HANDLE);
1845 : return -1;
1846 : }
1847 : memset(result, 0, sizeof(*result));
1848 :
1849 : type = GetFileType(h);
1850 : if (type == FILE_TYPE_UNKNOWN) {
1851 : DWORD error = GetLastError();
1852 : if (error != 0) {
1853 : return -1;
1854 : }
1855 : /* else: valid but unknown file */
1856 : }
1857 :
1858 : if (type != FILE_TYPE_DISK) {
1859 : if (type == FILE_TYPE_CHAR)
1860 : result->st_mode = _S_IFCHR;
1861 : else if (type == FILE_TYPE_PIPE)
1862 : result->st_mode = _S_IFIFO;
1863 : return 0;
1864 : }
1865 :
1866 : if (!GetFileInformationByHandle(h, &info)) {
1867 : return -1;
1868 : }
1869 :
1870 : attribute_data_to_stat(&info, 0, result);
1871 : /* specific to fstat() */
1872 : result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1873 : return 0;
1874 : }
1875 :
1876 : #endif /* MS_WINDOWS */
1877 :
1878 : PyDoc_STRVAR(stat_result__doc__,
1879 : "stat_result: Result from stat, fstat, or lstat.\n\n\
1880 : This object may be accessed either as a tuple of\n\
1881 : (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1882 : or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1883 : \n\
1884 : Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1885 : or st_flags, they are available as attributes only.\n\
1886 : \n\
1887 : See os.stat for more information.");
1888 :
1889 : static PyStructSequence_Field stat_result_fields[] = {
1890 : {"st_mode", "protection bits"},
1891 : {"st_ino", "inode"},
1892 : {"st_dev", "device"},
1893 : {"st_nlink", "number of hard links"},
1894 : {"st_uid", "user ID of owner"},
1895 : {"st_gid", "group ID of owner"},
1896 : {"st_size", "total size, in bytes"},
1897 : /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1898 : {NULL, "integer time of last access"},
1899 : {NULL, "integer time of last modification"},
1900 : {NULL, "integer time of last change"},
1901 : {"st_atime", "time of last access"},
1902 : {"st_mtime", "time of last modification"},
1903 : {"st_ctime", "time of last change"},
1904 : {"st_atime_ns", "time of last access in nanoseconds"},
1905 : {"st_mtime_ns", "time of last modification in nanoseconds"},
1906 : {"st_ctime_ns", "time of last change in nanoseconds"},
1907 : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1908 : {"st_blksize", "blocksize for filesystem I/O"},
1909 : #endif
1910 : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1911 : {"st_blocks", "number of blocks allocated"},
1912 : #endif
1913 : #ifdef HAVE_STRUCT_STAT_ST_RDEV
1914 : {"st_rdev", "device type (if inode device)"},
1915 : #endif
1916 : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1917 : {"st_flags", "user defined flags for file"},
1918 : #endif
1919 : #ifdef HAVE_STRUCT_STAT_ST_GEN
1920 : {"st_gen", "generation number"},
1921 : #endif
1922 : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1923 : {"st_birthtime", "time of creation"},
1924 : #endif
1925 : {0}
1926 : };
1927 :
1928 : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1929 : #define ST_BLKSIZE_IDX 16
1930 : #else
1931 : #define ST_BLKSIZE_IDX 15
1932 : #endif
1933 :
1934 : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1935 : #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1936 : #else
1937 : #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1938 : #endif
1939 :
1940 : #ifdef HAVE_STRUCT_STAT_ST_RDEV
1941 : #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1942 : #else
1943 : #define ST_RDEV_IDX ST_BLOCKS_IDX
1944 : #endif
1945 :
1946 : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1947 : #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1948 : #else
1949 : #define ST_FLAGS_IDX ST_RDEV_IDX
1950 : #endif
1951 :
1952 : #ifdef HAVE_STRUCT_STAT_ST_GEN
1953 : #define ST_GEN_IDX (ST_FLAGS_IDX+1)
1954 : #else
1955 : #define ST_GEN_IDX ST_FLAGS_IDX
1956 : #endif
1957 :
1958 : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1959 : #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1960 : #else
1961 : #define ST_BIRTHTIME_IDX ST_GEN_IDX
1962 : #endif
1963 :
1964 : static PyStructSequence_Desc stat_result_desc = {
1965 : "stat_result", /* name */
1966 : stat_result__doc__, /* doc */
1967 : stat_result_fields,
1968 : 10
1969 : };
1970 :
1971 : PyDoc_STRVAR(statvfs_result__doc__,
1972 : "statvfs_result: Result from statvfs or fstatvfs.\n\n\
1973 : This object may be accessed either as a tuple of\n\
1974 : (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1975 : or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1976 : \n\
1977 : See os.statvfs for more information.");
1978 :
1979 : static PyStructSequence_Field statvfs_result_fields[] = {
1980 : {"f_bsize", },
1981 : {"f_frsize", },
1982 : {"f_blocks", },
1983 : {"f_bfree", },
1984 : {"f_bavail", },
1985 : {"f_files", },
1986 : {"f_ffree", },
1987 : {"f_favail", },
1988 : {"f_flag", },
1989 : {"f_namemax",},
1990 : {0}
1991 : };
1992 :
1993 : static PyStructSequence_Desc statvfs_result_desc = {
1994 : "statvfs_result", /* name */
1995 : statvfs_result__doc__, /* doc */
1996 : statvfs_result_fields,
1997 : 10
1998 : };
1999 :
2000 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
2001 : PyDoc_STRVAR(waitid_result__doc__,
2002 : "waitid_result: Result from waitid.\n\n\
2003 : This object may be accessed either as a tuple of\n\
2004 : (si_pid, si_uid, si_signo, si_status, si_code),\n\
2005 : or via the attributes si_pid, si_uid, and so on.\n\
2006 : \n\
2007 : See os.waitid for more information.");
2008 :
2009 : static PyStructSequence_Field waitid_result_fields[] = {
2010 : {"si_pid", },
2011 : {"si_uid", },
2012 : {"si_signo", },
2013 : {"si_status", },
2014 : {"si_code", },
2015 : {0}
2016 : };
2017 :
2018 : static PyStructSequence_Desc waitid_result_desc = {
2019 : "waitid_result", /* name */
2020 : waitid_result__doc__, /* doc */
2021 : waitid_result_fields,
2022 : 5
2023 : };
2024 : static PyTypeObject WaitidResultType;
2025 : #endif
2026 :
2027 : static int initialized;
2028 : static PyTypeObject StatResultType;
2029 : static PyTypeObject StatVFSResultType;
2030 : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
2031 : static PyTypeObject SchedParamType;
2032 : #endif
2033 : static newfunc structseq_new;
2034 :
2035 : static PyObject *
2036 0 : statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2037 : {
2038 : PyStructSequence *result;
2039 : int i;
2040 :
2041 0 : result = (PyStructSequence*)structseq_new(type, args, kwds);
2042 0 : if (!result)
2043 0 : return NULL;
2044 : /* If we have been initialized from a tuple,
2045 : st_?time might be set to None. Initialize it
2046 : from the int slots. */
2047 0 : for (i = 7; i <= 9; i++) {
2048 0 : if (result->ob_item[i+3] == Py_None) {
2049 0 : Py_DECREF(Py_None);
2050 0 : Py_INCREF(result->ob_item[i]);
2051 0 : result->ob_item[i+3] = result->ob_item[i];
2052 : }
2053 : }
2054 0 : return (PyObject*)result;
2055 : }
2056 :
2057 :
2058 :
2059 : /* If true, st_?time is float. */
2060 : static int _stat_float_times = 1;
2061 :
2062 : PyDoc_STRVAR(stat_float_times__doc__,
2063 : "stat_float_times([newval]) -> oldval\n\n\
2064 : Determine whether os.[lf]stat represents time stamps as float objects.\n\
2065 : If newval is True, future calls to stat() return floats, if it is False,\n\
2066 : future calls return ints. \n\
2067 : If newval is omitted, return the current setting.\n");
2068 :
2069 : static PyObject*
2070 0 : stat_float_times(PyObject* self, PyObject *args)
2071 : {
2072 0 : int newval = -1;
2073 0 : if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
2074 0 : return NULL;
2075 0 : if (PyErr_WarnEx(PyExc_DeprecationWarning,
2076 : "stat_float_times() is deprecated",
2077 : 1))
2078 0 : return NULL;
2079 0 : if (newval == -1)
2080 : /* Return old value */
2081 0 : return PyBool_FromLong(_stat_float_times);
2082 0 : _stat_float_times = newval;
2083 0 : Py_INCREF(Py_None);
2084 0 : return Py_None;
2085 : }
2086 :
2087 : static PyObject *billion = NULL;
2088 :
2089 : static void
2090 972 : fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
2091 : {
2092 972 : PyObject *s = _PyLong_FromTime_t(sec);
2093 972 : PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2094 972 : PyObject *s_in_ns = NULL;
2095 972 : PyObject *ns_total = NULL;
2096 972 : PyObject *float_s = NULL;
2097 :
2098 972 : if (!(s && ns_fractional))
2099 : goto exit;
2100 :
2101 972 : s_in_ns = PyNumber_Multiply(s, billion);
2102 972 : if (!s_in_ns)
2103 0 : goto exit;
2104 :
2105 972 : ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2106 972 : if (!ns_total)
2107 0 : goto exit;
2108 :
2109 972 : if (_stat_float_times) {
2110 972 : float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2111 972 : if (!float_s)
2112 0 : goto exit;
2113 : }
2114 : else {
2115 0 : float_s = s;
2116 0 : Py_INCREF(float_s);
2117 : }
2118 :
2119 972 : PyStructSequence_SET_ITEM(v, index, s);
2120 972 : PyStructSequence_SET_ITEM(v, index+3, float_s);
2121 972 : PyStructSequence_SET_ITEM(v, index+6, ns_total);
2122 972 : s = NULL;
2123 972 : float_s = NULL;
2124 972 : ns_total = NULL;
2125 : exit:
2126 972 : Py_XDECREF(s);
2127 972 : Py_XDECREF(ns_fractional);
2128 972 : Py_XDECREF(s_in_ns);
2129 972 : Py_XDECREF(ns_total);
2130 972 : Py_XDECREF(float_s);
2131 972 : }
2132 :
2133 : /* pack a system stat C structure into the Python stat tuple
2134 : (used by posix_stat() and posix_fstat()) */
2135 : static PyObject*
2136 324 : _pystat_fromstructstat(STRUCT_STAT *st)
2137 : {
2138 : unsigned long ansec, mnsec, cnsec;
2139 324 : PyObject *v = PyStructSequence_New(&StatResultType);
2140 324 : if (v == NULL)
2141 0 : return NULL;
2142 :
2143 324 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2144 : #ifdef HAVE_LARGEFILE_SUPPORT
2145 324 : PyStructSequence_SET_ITEM(v, 1,
2146 : PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
2147 : #else
2148 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
2149 : #endif
2150 : #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
2151 324 : PyStructSequence_SET_ITEM(v, 2,
2152 : PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
2153 : #else
2154 : PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long)st->st_dev));
2155 : #endif
2156 324 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2157 324 : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long)st->st_uid));
2158 324 : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long)st->st_gid));
2159 : #ifdef HAVE_LARGEFILE_SUPPORT
2160 324 : PyStructSequence_SET_ITEM(v, 6,
2161 : PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
2162 : #else
2163 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
2164 : #endif
2165 :
2166 : #if defined(HAVE_STAT_TV_NSEC)
2167 324 : ansec = st->st_atim.tv_nsec;
2168 324 : mnsec = st->st_mtim.tv_nsec;
2169 324 : cnsec = st->st_ctim.tv_nsec;
2170 : #elif defined(HAVE_STAT_TV_NSEC2)
2171 : ansec = st->st_atimespec.tv_nsec;
2172 : mnsec = st->st_mtimespec.tv_nsec;
2173 : cnsec = st->st_ctimespec.tv_nsec;
2174 : #elif defined(HAVE_STAT_NSEC)
2175 : ansec = st->st_atime_nsec;
2176 : mnsec = st->st_mtime_nsec;
2177 : cnsec = st->st_ctime_nsec;
2178 : #else
2179 : ansec = mnsec = cnsec = 0;
2180 : #endif
2181 324 : fill_time(v, 7, st->st_atime, ansec);
2182 324 : fill_time(v, 8, st->st_mtime, mnsec);
2183 324 : fill_time(v, 9, st->st_ctime, cnsec);
2184 :
2185 : #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2186 324 : PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2187 : PyLong_FromLong((long)st->st_blksize));
2188 : #endif
2189 : #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2190 324 : PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2191 : PyLong_FromLong((long)st->st_blocks));
2192 : #endif
2193 : #ifdef HAVE_STRUCT_STAT_ST_RDEV
2194 324 : PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2195 : PyLong_FromLong((long)st->st_rdev));
2196 : #endif
2197 : #ifdef HAVE_STRUCT_STAT_ST_GEN
2198 : PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2199 : PyLong_FromLong((long)st->st_gen));
2200 : #endif
2201 : #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2202 : {
2203 : PyObject *val;
2204 : unsigned long bsec,bnsec;
2205 : bsec = (long)st->st_birthtime;
2206 : #ifdef HAVE_STAT_TV_NSEC2
2207 : bnsec = st->st_birthtimespec.tv_nsec;
2208 : #else
2209 : bnsec = 0;
2210 : #endif
2211 : if (_stat_float_times) {
2212 : val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2213 : } else {
2214 : val = PyLong_FromLong((long)bsec);
2215 : }
2216 : PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2217 : val);
2218 : }
2219 : #endif
2220 : #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2221 : PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2222 : PyLong_FromLong((long)st->st_flags));
2223 : #endif
2224 :
2225 324 : if (PyErr_Occurred()) {
2226 0 : Py_DECREF(v);
2227 0 : return NULL;
2228 : }
2229 :
2230 324 : return v;
2231 : }
2232 :
2233 : /* POSIX methods */
2234 :
2235 :
2236 : static PyObject *
2237 347 : posix_do_stat(char *function_name, path_t *path,
2238 : int dir_fd, int follow_symlinks)
2239 : {
2240 : STRUCT_STAT st;
2241 : int result;
2242 :
2243 : #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2244 : if (follow_symlinks_specified(function_name, follow_symlinks))
2245 : return NULL;
2246 : #endif
2247 :
2248 694 : if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2249 694 : dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2250 347 : fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2251 0 : return NULL;
2252 :
2253 347 : Py_BEGIN_ALLOW_THREADS
2254 347 : if (path->fd != -1)
2255 0 : result = FSTAT(path->fd, &st);
2256 : else
2257 : #ifdef MS_WINDOWS
2258 : if (path->wide) {
2259 : if (follow_symlinks)
2260 : result = win32_stat_w(path->wide, &st);
2261 : else
2262 : result = win32_lstat_w(path->wide, &st);
2263 : }
2264 : else
2265 : #endif
2266 : #if defined(HAVE_LSTAT) || defined(MS_WINDOWS)
2267 347 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2268 22 : result = LSTAT(path->narrow, &st);
2269 : else
2270 : #endif
2271 : #ifdef HAVE_FSTATAT
2272 325 : if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks)
2273 0 : result = fstatat(dir_fd, path->narrow, &st,
2274 : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2275 : else
2276 : #endif
2277 325 : result = STAT(path->narrow, &st);
2278 347 : Py_END_ALLOW_THREADS
2279 :
2280 347 : if (result != 0)
2281 23 : return path_error("stat", path);
2282 :
2283 324 : return _pystat_fromstructstat(&st);
2284 : }
2285 :
2286 : PyDoc_STRVAR(posix_stat__doc__,
2287 : "stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result\n\n\
2288 : Perform a stat system call on the given path.\n\
2289 : \n\
2290 : path may be specified as either a string or as an open file descriptor.\n\
2291 : \n\
2292 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
2293 : and path should be relative; path will then be relative to that directory.\n\
2294 : dir_fd may not be supported on your platform; if it is unavailable, using\n\
2295 : it will raise a NotImplementedError.\n\
2296 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
2297 : link, stat will examine the symbolic link itself instead of the file the\n\
2298 : link points to.\n\
2299 : It is an error to use dir_fd or follow_symlinks when specifying path as\n\
2300 : an open file descriptor.");
2301 :
2302 : static PyObject *
2303 325 : posix_stat(PyObject *self, PyObject *args, PyObject *kwargs)
2304 : {
2305 : static char *keywords[] = {"path", "dir_fd", "follow_symlinks", NULL};
2306 : path_t path;
2307 325 : int dir_fd = DEFAULT_DIR_FD;
2308 325 : int follow_symlinks = 1;
2309 : PyObject *return_value;
2310 :
2311 325 : memset(&path, 0, sizeof(path));
2312 325 : path.allow_fd = 1;
2313 325 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", keywords,
2314 : path_converter, &path,
2315 : #ifdef HAVE_FSTATAT
2316 : dir_fd_converter, &dir_fd,
2317 : #else
2318 : dir_fd_unavailable, &dir_fd,
2319 : #endif
2320 : &follow_symlinks))
2321 0 : return NULL;
2322 325 : return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
2323 325 : path_cleanup(&path);
2324 325 : return return_value;
2325 : }
2326 :
2327 : PyDoc_STRVAR(posix_lstat__doc__,
2328 : "lstat(path, *, dir_fd=None) -> stat result\n\n\
2329 : Like stat(), but do not follow symbolic links.\n\
2330 : Equivalent to stat(path, follow_symlinks=False).");
2331 :
2332 : static PyObject *
2333 22 : posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs)
2334 : {
2335 : static char *keywords[] = {"path", "dir_fd", NULL};
2336 : path_t path;
2337 22 : int dir_fd = DEFAULT_DIR_FD;
2338 22 : int follow_symlinks = 0;
2339 : PyObject *return_value;
2340 :
2341 22 : memset(&path, 0, sizeof(path));
2342 22 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", keywords,
2343 : path_converter, &path,
2344 : #ifdef HAVE_FSTATAT
2345 : dir_fd_converter, &dir_fd
2346 : #else
2347 : dir_fd_unavailable, &dir_fd
2348 : #endif
2349 : ))
2350 0 : return NULL;
2351 22 : return_value = posix_do_stat("stat", &path, dir_fd, follow_symlinks);
2352 22 : path_cleanup(&path);
2353 22 : return return_value;
2354 : }
2355 :
2356 : PyDoc_STRVAR(posix_access__doc__,
2357 : "access(path, mode, *, dir_fd=None, effective_ids=False,\
2358 : follow_symlinks=True)\n\n\
2359 : Use the real uid/gid to test for access to a path. Returns True if granted,\n\
2360 : False otherwise.\n\
2361 : \n\
2362 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
2363 : and path should be relative; path will then be relative to that directory.\n\
2364 : If effective_ids is True, access will use the effective uid/gid instead of\n\
2365 : the real uid/gid.\n\
2366 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
2367 : link, access will examine the symbolic link itself instead of the file the\n\
2368 : link points to.\n\
2369 : dir_fd, effective_ids, and follow_symlinks may not be implemented\n\
2370 : on your platform. If they are unavailable, using them will raise a\n\
2371 : NotImplementedError.\n\
2372 : \n\
2373 : Note that most operations will use the effective uid/gid, therefore this\n\
2374 : routine can be used in a suid/sgid environment to test if the invoking user\n\
2375 : has the specified access to the path.\n\
2376 : The mode argument can be F_OK to test existence, or the inclusive-OR\n\
2377 : of R_OK, W_OK, and X_OK.");
2378 :
2379 : static PyObject *
2380 2 : posix_access(PyObject *self, PyObject *args, PyObject *kwargs)
2381 : {
2382 : static char *keywords[] = {"path", "mode", "dir_fd", "effective_ids",
2383 : "follow_symlinks", NULL};
2384 : path_t path;
2385 : int mode;
2386 2 : int dir_fd = DEFAULT_DIR_FD;
2387 2 : int effective_ids = 0;
2388 2 : int follow_symlinks = 1;
2389 2 : PyObject *return_value = NULL;
2390 :
2391 : #ifdef MS_WINDOWS
2392 : DWORD attr;
2393 : #else
2394 : int result;
2395 : #endif
2396 :
2397 2 : memset(&path, 0, sizeof(path));
2398 2 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&pp:access", keywords,
2399 : path_converter, &path, &mode,
2400 : #ifdef HAVE_FACCESSAT
2401 : dir_fd_converter, &dir_fd,
2402 : #else
2403 : dir_fd_unavailable, &dir_fd,
2404 : #endif
2405 : &effective_ids, &follow_symlinks))
2406 0 : return NULL;
2407 :
2408 : #ifndef HAVE_FACCESSAT
2409 : if (follow_symlinks_specified("access", follow_symlinks))
2410 : goto exit;
2411 :
2412 : if (effective_ids) {
2413 : argument_unavailable_error("access", "effective_ids");
2414 : goto exit;
2415 : }
2416 : #endif
2417 :
2418 : #ifdef MS_WINDOWS
2419 : Py_BEGIN_ALLOW_THREADS
2420 : if (path.wide != NULL)
2421 : attr = GetFileAttributesW(path.wide);
2422 : else
2423 : attr = GetFileAttributesA(path.narrow);
2424 : Py_END_ALLOW_THREADS
2425 :
2426 : /*
2427 : * Access is possible if
2428 : * * we didn't get a -1, and
2429 : * * write access wasn't requested,
2430 : * * or the file isn't read-only,
2431 : * * or it's a directory.
2432 : * (Directories cannot be read-only on Windows.)
2433 : */
2434 : return_value = PyBool_FromLong(
2435 : (attr != 0xFFFFFFFF) &&
2436 : (!(mode & 2) ||
2437 : !(attr & FILE_ATTRIBUTE_READONLY) ||
2438 : (attr & FILE_ATTRIBUTE_DIRECTORY)));
2439 : #else
2440 :
2441 2 : Py_BEGIN_ALLOW_THREADS
2442 : #ifdef HAVE_FACCESSAT
2443 2 : if ((dir_fd != DEFAULT_DIR_FD) ||
2444 2 : effective_ids ||
2445 2 : !follow_symlinks) {
2446 0 : int flags = 0;
2447 0 : if (!follow_symlinks)
2448 0 : flags |= AT_SYMLINK_NOFOLLOW;
2449 0 : if (effective_ids)
2450 0 : flags |= AT_EACCESS;
2451 0 : result = faccessat(dir_fd, path.narrow, mode, flags);
2452 : }
2453 : else
2454 : #endif
2455 2 : result = access(path.narrow, mode);
2456 2 : Py_END_ALLOW_THREADS
2457 2 : return_value = PyBool_FromLong(!result);
2458 : #endif
2459 :
2460 : #ifndef HAVE_FACCESSAT
2461 : exit:
2462 : #endif
2463 2 : path_cleanup(&path);
2464 2 : return return_value;
2465 : }
2466 :
2467 : #ifndef F_OK
2468 : #define F_OK 0
2469 : #endif
2470 : #ifndef R_OK
2471 : #define R_OK 4
2472 : #endif
2473 : #ifndef W_OK
2474 : #define W_OK 2
2475 : #endif
2476 : #ifndef X_OK
2477 : #define X_OK 1
2478 : #endif
2479 :
2480 : #ifdef HAVE_TTYNAME
2481 : PyDoc_STRVAR(posix_ttyname__doc__,
2482 : "ttyname(fd) -> string\n\n\
2483 : Return the name of the terminal device connected to 'fd'.");
2484 :
2485 : static PyObject *
2486 0 : posix_ttyname(PyObject *self, PyObject *args)
2487 : {
2488 : int id;
2489 : char *ret;
2490 :
2491 0 : if (!PyArg_ParseTuple(args, "i:ttyname", &id))
2492 0 : return NULL;
2493 :
2494 : #if defined(__VMS)
2495 : /* file descriptor 0 only, the default input device (stdin) */
2496 : if (id == 0) {
2497 : ret = ttyname();
2498 : }
2499 : else {
2500 : ret = NULL;
2501 : }
2502 : #else
2503 0 : ret = ttyname(id);
2504 : #endif
2505 0 : if (ret == NULL)
2506 0 : return posix_error();
2507 0 : return PyUnicode_DecodeFSDefault(ret);
2508 : }
2509 : #endif
2510 :
2511 : #ifdef HAVE_CTERMID
2512 : PyDoc_STRVAR(posix_ctermid__doc__,
2513 : "ctermid() -> string\n\n\
2514 : Return the name of the controlling terminal for this process.");
2515 :
2516 : static PyObject *
2517 0 : posix_ctermid(PyObject *self, PyObject *noargs)
2518 : {
2519 : char *ret;
2520 : char buffer[L_ctermid];
2521 :
2522 : #ifdef USE_CTERMID_R
2523 : ret = ctermid_r(buffer);
2524 : #else
2525 0 : ret = ctermid(buffer);
2526 : #endif
2527 0 : if (ret == NULL)
2528 0 : return posix_error();
2529 0 : return PyUnicode_DecodeFSDefault(buffer);
2530 : }
2531 : #endif
2532 :
2533 : PyDoc_STRVAR(posix_chdir__doc__,
2534 : "chdir(path)\n\n\
2535 : Change the current working directory to the specified path.\n\
2536 : \n\
2537 : path may always be specified as a string.\n\
2538 : On some platforms, path may also be specified as an open file descriptor.\n\
2539 : If this functionality is unavailable, using it raises an exception.");
2540 :
2541 : static PyObject *
2542 0 : posix_chdir(PyObject *self, PyObject *args, PyObject *kwargs)
2543 : {
2544 : path_t path;
2545 : int result;
2546 0 : PyObject *return_value = NULL;
2547 : static char *keywords[] = {"path", NULL};
2548 :
2549 0 : memset(&path, 0, sizeof(path));
2550 : #ifdef HAVE_FCHDIR
2551 0 : path.allow_fd = 1;
2552 : #endif
2553 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", keywords,
2554 : path_converter, &path
2555 : ))
2556 0 : return NULL;
2557 :
2558 0 : Py_BEGIN_ALLOW_THREADS
2559 : #ifdef MS_WINDOWS
2560 : if (path.wide)
2561 : result = win32_wchdir(path.wide);
2562 : else
2563 : result = win32_chdir(path.narrow);
2564 : result = !result; /* on unix, success = 0, on windows, success = !0 */
2565 : #elif defined(PYOS_OS2) && defined(PYCC_GCC)
2566 : result = _chdir2(path.narrow);
2567 : #else
2568 : #ifdef HAVE_FCHDIR
2569 0 : if (path.fd != -1)
2570 0 : result = fchdir(path.fd);
2571 : else
2572 : #endif
2573 0 : result = chdir(path.narrow);
2574 : #endif
2575 0 : Py_END_ALLOW_THREADS
2576 :
2577 0 : if (result) {
2578 0 : return_value = path_error("chdir", &path);
2579 0 : goto exit;
2580 : }
2581 :
2582 0 : return_value = Py_None;
2583 0 : Py_INCREF(Py_None);
2584 :
2585 : exit:
2586 0 : path_cleanup(&path);
2587 0 : return return_value;
2588 : }
2589 :
2590 : #ifdef HAVE_FCHDIR
2591 : PyDoc_STRVAR(posix_fchdir__doc__,
2592 : "fchdir(fd)\n\n\
2593 : Change to the directory of the given file descriptor. fd must be\n\
2594 : opened on a directory, not a file. Equivalent to os.chdir(fd).");
2595 :
2596 : static PyObject *
2597 0 : posix_fchdir(PyObject *self, PyObject *fdobj)
2598 : {
2599 0 : return posix_fildes(fdobj, fchdir);
2600 : }
2601 : #endif /* HAVE_FCHDIR */
2602 :
2603 :
2604 : PyDoc_STRVAR(posix_chmod__doc__,
2605 : "chmod(path, mode, *, dir_fd=None, follow_symlinks=True)\n\n\
2606 : Change the access permissions of a file.\n\
2607 : \n\
2608 : path may always be specified as a string.\n\
2609 : On some platforms, path may also be specified as an open file descriptor.\n\
2610 : If this functionality is unavailable, using it raises an exception.\n\
2611 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
2612 : and path should be relative; path will then be relative to that directory.\n\
2613 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
2614 : link, chmod will modify the symbolic link itself instead of the file the\n\
2615 : link points to.\n\
2616 : It is an error to use dir_fd or follow_symlinks when specifying path as\n\
2617 : an open file descriptor.\n\
2618 : dir_fd and follow_symlinks may not be implemented on your platform.\n\
2619 : If they are unavailable, using them will raise a NotImplementedError.");
2620 :
2621 : static PyObject *
2622 0 : posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs)
2623 : {
2624 : path_t path;
2625 : int mode;
2626 0 : int dir_fd = DEFAULT_DIR_FD;
2627 0 : int follow_symlinks = 1;
2628 : int result;
2629 0 : PyObject *return_value = NULL;
2630 : static char *keywords[] = {"path", "mode", "dir_fd",
2631 : "follow_symlinks", NULL};
2632 :
2633 : #ifdef MS_WINDOWS
2634 : DWORD attr;
2635 : #endif
2636 :
2637 : #ifdef HAVE_FCHMODAT
2638 0 : int fchmodat_nofollow_unsupported = 0;
2639 : #endif
2640 :
2641 0 : memset(&path, 0, sizeof(path));
2642 : #ifdef HAVE_FCHMOD
2643 0 : path.allow_fd = 1;
2644 : #endif
2645 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", keywords,
2646 : path_converter, &path,
2647 : &mode,
2648 : #ifdef HAVE_FCHMODAT
2649 : dir_fd_converter, &dir_fd,
2650 : #else
2651 : dir_fd_unavailable, &dir_fd,
2652 : #endif
2653 : &follow_symlinks))
2654 0 : return NULL;
2655 :
2656 : #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
2657 : if (follow_symlinks_specified("chmod", follow_symlinks))
2658 : goto exit;
2659 : #endif
2660 :
2661 : #ifdef MS_WINDOWS
2662 : Py_BEGIN_ALLOW_THREADS
2663 : if (path.wide)
2664 : attr = GetFileAttributesW(path.wide);
2665 : else
2666 : attr = GetFileAttributesA(path.narrow);
2667 : if (attr == 0xFFFFFFFF)
2668 : result = 0;
2669 : else {
2670 : if (mode & _S_IWRITE)
2671 : attr &= ~FILE_ATTRIBUTE_READONLY;
2672 : else
2673 : attr |= FILE_ATTRIBUTE_READONLY;
2674 : if (path.wide)
2675 : result = SetFileAttributesW(path.wide, attr);
2676 : else
2677 : result = SetFileAttributesA(path.narrow, attr);
2678 : }
2679 : Py_END_ALLOW_THREADS
2680 :
2681 : if (!result) {
2682 : return_value = win32_error_object("chmod", path.object);
2683 : goto exit;
2684 : }
2685 : #else /* MS_WINDOWS */
2686 0 : Py_BEGIN_ALLOW_THREADS
2687 : #ifdef HAVE_FCHMOD
2688 0 : if (path.fd != -1)
2689 0 : result = fchmod(path.fd, mode);
2690 : else
2691 : #endif
2692 : #ifdef HAVE_LCHMOD
2693 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2694 : result = lchmod(path.narrow, mode);
2695 : else
2696 : #endif
2697 : #ifdef HAVE_FCHMODAT
2698 0 : if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2699 : /*
2700 : * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
2701 : * The documentation specifically shows how to use it,
2702 : * and then says it isn't implemented yet.
2703 : * (true on linux with glibc 2.15, and openindiana 3.x)
2704 : *
2705 : * Once it is supported, os.chmod will automatically
2706 : * support dir_fd and follow_symlinks=False. (Hopefully.)
2707 : * Until then, we need to be careful what exception we raise.
2708 : */
2709 0 : result = fchmodat(dir_fd, path.narrow, mode,
2710 0 : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2711 : /*
2712 : * But wait! We can't throw the exception without allowing threads,
2713 : * and we can't do that in this nested scope. (Macro trickery, sigh.)
2714 : */
2715 0 : fchmodat_nofollow_unsupported =
2716 0 : result &&
2717 0 : ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
2718 0 : !follow_symlinks;
2719 : }
2720 : else
2721 : #endif
2722 0 : result = chmod(path.narrow, mode);
2723 0 : Py_END_ALLOW_THREADS
2724 :
2725 0 : if (result) {
2726 : #ifdef HAVE_FCHMODAT
2727 0 : if (fchmodat_nofollow_unsupported) {
2728 0 : if (dir_fd != DEFAULT_DIR_FD)
2729 0 : dir_fd_and_follow_symlinks_invalid("chmod",
2730 : dir_fd, follow_symlinks);
2731 : else
2732 0 : follow_symlinks_specified("chmod", follow_symlinks);
2733 : }
2734 : else
2735 : #endif
2736 0 : return_value = path_error("chmod", &path);
2737 0 : goto exit;
2738 : }
2739 : #endif
2740 :
2741 0 : Py_INCREF(Py_None);
2742 0 : return_value = Py_None;
2743 : exit:
2744 0 : path_cleanup(&path);
2745 0 : return return_value;
2746 : }
2747 :
2748 :
2749 : #ifdef HAVE_FCHMOD
2750 : PyDoc_STRVAR(posix_fchmod__doc__,
2751 : "fchmod(fd, mode)\n\n\
2752 : Change the access permissions of the file given by file\n\
2753 : descriptor fd. Equivalent to os.chmod(fd, mode).");
2754 :
2755 : static PyObject *
2756 0 : posix_fchmod(PyObject *self, PyObject *args)
2757 : {
2758 : int fd, mode, res;
2759 0 : if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
2760 0 : return NULL;
2761 0 : Py_BEGIN_ALLOW_THREADS
2762 0 : res = fchmod(fd, mode);
2763 0 : Py_END_ALLOW_THREADS
2764 0 : if (res < 0)
2765 0 : return posix_error();
2766 0 : Py_RETURN_NONE;
2767 : }
2768 : #endif /* HAVE_FCHMOD */
2769 :
2770 : #ifdef HAVE_LCHMOD
2771 : PyDoc_STRVAR(posix_lchmod__doc__,
2772 : "lchmod(path, mode)\n\n\
2773 : Change the access permissions of a file. If path is a symlink, this\n\
2774 : affects the link itself rather than the target.\n\
2775 : Equivalent to chmod(path, mode, follow_symlinks=False).");
2776 :
2777 : static PyObject *
2778 : posix_lchmod(PyObject *self, PyObject *args)
2779 : {
2780 : PyObject *opath;
2781 : char *path;
2782 : int i;
2783 : int res;
2784 : if (!PyArg_ParseTuple(args, "O&i:lchmod", PyUnicode_FSConverter,
2785 : &opath, &i))
2786 : return NULL;
2787 : path = PyBytes_AsString(opath);
2788 : Py_BEGIN_ALLOW_THREADS
2789 : res = lchmod(path, i);
2790 : Py_END_ALLOW_THREADS
2791 : if (res < 0)
2792 : return posix_error_with_allocated_filename(opath);
2793 : Py_DECREF(opath);
2794 : Py_RETURN_NONE;
2795 : }
2796 : #endif /* HAVE_LCHMOD */
2797 :
2798 :
2799 : #ifdef HAVE_CHFLAGS
2800 : PyDoc_STRVAR(posix_chflags__doc__,
2801 : "chflags(path, flags, *, follow_symlinks=True)\n\n\
2802 : Set file flags.\n\
2803 : \n\
2804 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
2805 : link, chflags will change flags on the symbolic link itself instead of the\n\
2806 : file the link points to.\n\
2807 : follow_symlinks may not be implemented on your platform. If it is\n\
2808 : unavailable, using it will raise a NotImplementedError.");
2809 :
2810 : static PyObject *
2811 : posix_chflags(PyObject *self, PyObject *args, PyObject *kwargs)
2812 : {
2813 : path_t path;
2814 : unsigned long flags;
2815 : int follow_symlinks = 1;
2816 : int result;
2817 : PyObject *return_value;
2818 : static char *keywords[] = {"path", "flags", "follow_symlinks", NULL};
2819 :
2820 : memset(&path, 0, sizeof(path));
2821 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|$i:chflags", keywords,
2822 : path_converter, &path,
2823 : &flags, &follow_symlinks))
2824 : return NULL;
2825 :
2826 : #ifndef HAVE_LCHFLAGS
2827 : if (follow_symlinks_specified("chflags", follow_symlinks))
2828 : goto exit;
2829 : #endif
2830 :
2831 : Py_BEGIN_ALLOW_THREADS
2832 : #ifdef HAVE_LCHFLAGS
2833 : if (!follow_symlinks)
2834 : result = lchflags(path.narrow, flags);
2835 : else
2836 : #endif
2837 : result = chflags(path.narrow, flags);
2838 : Py_END_ALLOW_THREADS
2839 :
2840 : if (result) {
2841 : return_value = path_posix_error("chflags", &path);
2842 : goto exit;
2843 : }
2844 :
2845 : return_value = Py_None;
2846 : Py_INCREF(Py_None);
2847 :
2848 : exit:
2849 : path_cleanup(&path);
2850 : return return_value;
2851 : }
2852 : #endif /* HAVE_CHFLAGS */
2853 :
2854 : #ifdef HAVE_LCHFLAGS
2855 : PyDoc_STRVAR(posix_lchflags__doc__,
2856 : "lchflags(path, flags)\n\n\
2857 : Set file flags.\n\
2858 : This function will not follow symbolic links.\n\
2859 : Equivalent to chflags(path, flags, follow_symlinks=False).");
2860 :
2861 : static PyObject *
2862 : posix_lchflags(PyObject *self, PyObject *args)
2863 : {
2864 : PyObject *opath;
2865 : char *path;
2866 : unsigned long flags;
2867 : int res;
2868 : if (!PyArg_ParseTuple(args, "O&k:lchflags",
2869 : PyUnicode_FSConverter, &opath, &flags))
2870 : return NULL;
2871 : path = PyBytes_AsString(opath);
2872 : Py_BEGIN_ALLOW_THREADS
2873 : res = lchflags(path, flags);
2874 : Py_END_ALLOW_THREADS
2875 : if (res < 0)
2876 : return posix_error_with_allocated_filename(opath);
2877 : Py_DECREF(opath);
2878 : Py_INCREF(Py_None);
2879 : return Py_None;
2880 : }
2881 : #endif /* HAVE_LCHFLAGS */
2882 :
2883 : #ifdef HAVE_CHROOT
2884 : PyDoc_STRVAR(posix_chroot__doc__,
2885 : "chroot(path)\n\n\
2886 : Change root directory to path.");
2887 :
2888 : static PyObject *
2889 0 : posix_chroot(PyObject *self, PyObject *args)
2890 : {
2891 0 : return posix_1str(args, "O&:chroot", chroot);
2892 : }
2893 : #endif
2894 :
2895 : #ifdef HAVE_FSYNC
2896 : PyDoc_STRVAR(posix_fsync__doc__,
2897 : "fsync(fildes)\n\n\
2898 : force write of file with filedescriptor to disk.");
2899 :
2900 : static PyObject *
2901 0 : posix_fsync(PyObject *self, PyObject *fdobj)
2902 : {
2903 0 : return posix_fildes(fdobj, fsync);
2904 : }
2905 : #endif /* HAVE_FSYNC */
2906 :
2907 : #ifdef HAVE_SYNC
2908 : PyDoc_STRVAR(posix_sync__doc__,
2909 : "sync()\n\n\
2910 : Force write of everything to disk.");
2911 :
2912 : static PyObject *
2913 0 : posix_sync(PyObject *self, PyObject *noargs)
2914 : {
2915 0 : Py_BEGIN_ALLOW_THREADS
2916 0 : sync();
2917 0 : Py_END_ALLOW_THREADS
2918 0 : Py_RETURN_NONE;
2919 : }
2920 : #endif
2921 :
2922 : #ifdef HAVE_FDATASYNC
2923 :
2924 : #ifdef __hpux
2925 : extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
2926 : #endif
2927 :
2928 : PyDoc_STRVAR(posix_fdatasync__doc__,
2929 : "fdatasync(fildes)\n\n\
2930 : force write of file with filedescriptor to disk.\n\
2931 : does not force update of metadata.");
2932 :
2933 : static PyObject *
2934 0 : posix_fdatasync(PyObject *self, PyObject *fdobj)
2935 : {
2936 0 : return posix_fildes(fdobj, fdatasync);
2937 : }
2938 : #endif /* HAVE_FDATASYNC */
2939 :
2940 :
2941 : #ifdef HAVE_CHOWN
2942 : PyDoc_STRVAR(posix_chown__doc__,
2943 : "chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n\n\
2944 : Change the owner and group id of path to the numeric uid and gid.\n\
2945 : \n\
2946 : path may always be specified as a string.\n\
2947 : On some platforms, path may also be specified as an open file descriptor.\n\
2948 : If this functionality is unavailable, using it raises an exception.\n\
2949 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
2950 : and path should be relative; path will then be relative to that directory.\n\
2951 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
2952 : link, chown will modify the symbolic link itself instead of the file the\n\
2953 : link points to.\n\
2954 : It is an error to use dir_fd or follow_symlinks when specifying path as\n\
2955 : an open file descriptor.\n\
2956 : dir_fd and follow_symlinks may not be implemented on your platform.\n\
2957 : If they are unavailable, using them will raise a NotImplementedError.");
2958 :
2959 : static PyObject *
2960 0 : posix_chown(PyObject *self, PyObject *args, PyObject *kwargs)
2961 : {
2962 : path_t path;
2963 : long uid_l, gid_l;
2964 : uid_t uid;
2965 : gid_t gid;
2966 0 : int dir_fd = DEFAULT_DIR_FD;
2967 0 : int follow_symlinks = 1;
2968 : int result;
2969 0 : PyObject *return_value = NULL;
2970 : static char *keywords[] = {"path", "uid", "gid", "dir_fd",
2971 : "follow_symlinks", NULL};
2972 :
2973 0 : memset(&path, 0, sizeof(path));
2974 : #ifdef HAVE_FCHOWN
2975 0 : path.allow_fd = 1;
2976 : #endif
2977 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&ll|$O&p:chown", keywords,
2978 : path_converter, &path,
2979 : &uid_l, &gid_l,
2980 : #ifdef HAVE_FCHOWNAT
2981 : dir_fd_converter, &dir_fd,
2982 : #else
2983 : dir_fd_unavailable, &dir_fd,
2984 : #endif
2985 : &follow_symlinks))
2986 0 : return NULL;
2987 :
2988 : #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
2989 : if (follow_symlinks_specified("chown", follow_symlinks))
2990 : goto exit;
2991 : #endif
2992 0 : if (dir_fd_and_fd_invalid("chown", dir_fd, path.fd) ||
2993 0 : fd_and_follow_symlinks_invalid("chown", path.fd, follow_symlinks))
2994 : goto exit;
2995 :
2996 : #ifdef __APPLE__
2997 : /*
2998 : * This is for Mac OS X 10.3, which doesn't have lchown.
2999 : * (But we still have an lchown symbol because of weak-linking.)
3000 : * It doesn't have fchownat either. So there's no possibility
3001 : * of a graceful failover.
3002 : */
3003 : if ((!follow_symlinks) && (lchown == NULL)) {
3004 : follow_symlinks_specified("chown", follow_symlinks);
3005 : goto exit;
3006 : }
3007 : #endif
3008 :
3009 0 : Py_BEGIN_ALLOW_THREADS
3010 0 : uid = (uid_t)uid_l;
3011 0 : gid = (uid_t)gid_l;
3012 : #ifdef HAVE_FCHOWN
3013 0 : if (path.fd != -1)
3014 0 : result = fchown(path.fd, uid, gid);
3015 : else
3016 : #endif
3017 : #ifdef HAVE_LCHOWN
3018 0 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3019 0 : result = lchown(path.narrow, uid, gid);
3020 : else
3021 : #endif
3022 : #ifdef HAVE_FCHOWNAT
3023 0 : if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
3024 0 : result = fchownat(dir_fd, path.narrow, uid, gid,
3025 0 : follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3026 : else
3027 : #endif
3028 0 : result = chown(path.narrow, uid, gid);
3029 0 : Py_END_ALLOW_THREADS
3030 :
3031 0 : if (result) {
3032 0 : return_value = path_posix_error("chown", &path);
3033 0 : goto exit;
3034 : }
3035 :
3036 0 : return_value = Py_None;
3037 0 : Py_INCREF(Py_None);
3038 :
3039 : exit:
3040 0 : path_cleanup(&path);
3041 0 : return return_value;
3042 : }
3043 : #endif /* HAVE_CHOWN */
3044 :
3045 : #ifdef HAVE_FCHOWN
3046 : PyDoc_STRVAR(posix_fchown__doc__,
3047 : "fchown(fd, uid, gid)\n\n\
3048 : Change the owner and group id of the file given by file descriptor\n\
3049 : fd to the numeric uid and gid. Equivalent to os.chown(fd, uid, gid).");
3050 :
3051 : static PyObject *
3052 0 : posix_fchown(PyObject *self, PyObject *args)
3053 : {
3054 : int fd;
3055 : long uid, gid;
3056 : int res;
3057 0 : if (!PyArg_ParseTuple(args, "ill:fchown", &fd, &uid, &gid))
3058 0 : return NULL;
3059 0 : Py_BEGIN_ALLOW_THREADS
3060 0 : res = fchown(fd, (uid_t) uid, (gid_t) gid);
3061 0 : Py_END_ALLOW_THREADS
3062 0 : if (res < 0)
3063 0 : return posix_error();
3064 0 : Py_RETURN_NONE;
3065 : }
3066 : #endif /* HAVE_FCHOWN */
3067 :
3068 : #ifdef HAVE_LCHOWN
3069 : PyDoc_STRVAR(posix_lchown__doc__,
3070 : "lchown(path, uid, gid)\n\n\
3071 : Change the owner and group id of path to the numeric uid and gid.\n\
3072 : This function will not follow symbolic links.\n\
3073 : Equivalent to os.chown(path, uid, gid, follow_symlinks=False).");
3074 :
3075 : static PyObject *
3076 0 : posix_lchown(PyObject *self, PyObject *args)
3077 : {
3078 : PyObject *opath;
3079 : char *path;
3080 : long uid, gid;
3081 : int res;
3082 0 : if (!PyArg_ParseTuple(args, "O&ll:lchown",
3083 : PyUnicode_FSConverter, &opath,
3084 : &uid, &gid))
3085 0 : return NULL;
3086 0 : path = PyBytes_AsString(opath);
3087 0 : Py_BEGIN_ALLOW_THREADS
3088 0 : res = lchown(path, (uid_t) uid, (gid_t) gid);
3089 0 : Py_END_ALLOW_THREADS
3090 0 : if (res < 0)
3091 0 : return posix_error_with_allocated_filename(opath);
3092 0 : Py_DECREF(opath);
3093 0 : Py_INCREF(Py_None);
3094 0 : return Py_None;
3095 : }
3096 : #endif /* HAVE_LCHOWN */
3097 :
3098 :
3099 : #ifdef HAVE_GETCWD
3100 : static PyObject *
3101 2 : posix_getcwd(int use_bytes)
3102 : {
3103 : char buf[1026];
3104 : char *res;
3105 :
3106 : #ifdef MS_WINDOWS
3107 : if (!use_bytes) {
3108 : wchar_t wbuf[1026];
3109 : wchar_t *wbuf2 = wbuf;
3110 : PyObject *resobj;
3111 : DWORD len;
3112 : Py_BEGIN_ALLOW_THREADS
3113 : len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
3114 : /* If the buffer is large enough, len does not include the
3115 : terminating \0. If the buffer is too small, len includes
3116 : the space needed for the terminator. */
3117 : if (len >= sizeof wbuf/ sizeof wbuf[0]) {
3118 : wbuf2 = malloc(len * sizeof(wchar_t));
3119 : if (wbuf2)
3120 : len = GetCurrentDirectoryW(len, wbuf2);
3121 : }
3122 : Py_END_ALLOW_THREADS
3123 : if (!wbuf2) {
3124 : PyErr_NoMemory();
3125 : return NULL;
3126 : }
3127 : if (!len) {
3128 : if (wbuf2 != wbuf) free(wbuf2);
3129 : return win32_error("getcwdu", NULL);
3130 : }
3131 : resobj = PyUnicode_FromWideChar(wbuf2, len);
3132 : if (wbuf2 != wbuf) free(wbuf2);
3133 : return resobj;
3134 : }
3135 :
3136 : if (win32_warn_bytes_api())
3137 : return NULL;
3138 : #endif
3139 :
3140 2 : Py_BEGIN_ALLOW_THREADS
3141 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
3142 : res = _getcwd2(buf, sizeof buf);
3143 : #else
3144 2 : res = getcwd(buf, sizeof buf);
3145 : #endif
3146 2 : Py_END_ALLOW_THREADS
3147 2 : if (res == NULL)
3148 0 : return posix_error();
3149 2 : if (use_bytes)
3150 0 : return PyBytes_FromStringAndSize(buf, strlen(buf));
3151 2 : return PyUnicode_DecodeFSDefault(buf);
3152 : }
3153 :
3154 : PyDoc_STRVAR(posix_getcwd__doc__,
3155 : "getcwd() -> path\n\n\
3156 : Return a unicode string representing the current working directory.");
3157 :
3158 : static PyObject *
3159 2 : posix_getcwd_unicode(PyObject *self)
3160 : {
3161 2 : return posix_getcwd(0);
3162 : }
3163 :
3164 : PyDoc_STRVAR(posix_getcwdb__doc__,
3165 : "getcwdb() -> path\n\n\
3166 : Return a bytes string representing the current working directory.");
3167 :
3168 : static PyObject *
3169 0 : posix_getcwd_bytes(PyObject *self)
3170 : {
3171 0 : return posix_getcwd(1);
3172 : }
3173 : #endif
3174 :
3175 : #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3176 : #define HAVE_LINK 1
3177 : #endif
3178 :
3179 : #ifdef HAVE_LINK
3180 : PyDoc_STRVAR(posix_link__doc__,
3181 : "link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True)\n\n\
3182 : Create a hard link to a file.\n\
3183 : \n\
3184 : If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
3185 : descriptor open to a directory, and the respective path string (src or dst)\n\
3186 : should be relative; the path will then be relative to that directory.\n\
3187 : If follow_symlinks is False, and the last element of src is a symbolic\n\
3188 : link, link will create a link to the symbolic link itself instead of the\n\
3189 : file the link points to.\n\
3190 : src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n\
3191 : platform. If they are unavailable, using them will raise a\n\
3192 : NotImplementedError.");
3193 :
3194 : static PyObject *
3195 0 : posix_link(PyObject *self, PyObject *args, PyObject *kwargs)
3196 : {
3197 : path_t src, dst;
3198 0 : int src_dir_fd = DEFAULT_DIR_FD;
3199 0 : int dst_dir_fd = DEFAULT_DIR_FD;
3200 0 : int follow_symlinks = 1;
3201 0 : PyObject *return_value = NULL;
3202 : static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd",
3203 : "follow_symlinks", NULL};
3204 : #ifdef MS_WINDOWS
3205 : BOOL result;
3206 : #else
3207 : int result;
3208 : #endif
3209 :
3210 0 : memset(&src, 0, sizeof(src));
3211 0 : memset(&dst, 0, sizeof(dst));
3212 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|O&O&p:link", keywords,
3213 : path_converter, &src,
3214 : path_converter, &dst,
3215 : dir_fd_converter, &src_dir_fd,
3216 : dir_fd_converter, &dst_dir_fd,
3217 : &follow_symlinks))
3218 0 : return NULL;
3219 :
3220 : #ifndef HAVE_LINKAT
3221 : if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3222 : argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3223 : goto exit;
3224 : }
3225 : #endif
3226 :
3227 0 : if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
3228 0 : PyErr_SetString(PyExc_NotImplementedError,
3229 : "link: src and dst must be the same type");
3230 0 : goto exit;
3231 : }
3232 :
3233 : #ifdef MS_WINDOWS
3234 : Py_BEGIN_ALLOW_THREADS
3235 : if (src.wide)
3236 : result = CreateHardLinkW(dst.wide, src.wide, NULL);
3237 : else
3238 : result = CreateHardLinkA(dst.narrow, src.narrow, NULL);
3239 : Py_END_ALLOW_THREADS
3240 :
3241 : if (!result) {
3242 : return_value = win32_error_object("link", dst.object);
3243 : goto exit;
3244 : }
3245 : #else
3246 0 : Py_BEGIN_ALLOW_THREADS
3247 : #ifdef HAVE_LINKAT
3248 0 : if ((src_dir_fd != DEFAULT_DIR_FD) ||
3249 0 : (dst_dir_fd != DEFAULT_DIR_FD) ||
3250 0 : (!follow_symlinks))
3251 0 : result = linkat(src_dir_fd, src.narrow,
3252 0 : dst_dir_fd, dst.narrow,
3253 0 : follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3254 : else
3255 : #endif
3256 0 : result = link(src.narrow, dst.narrow);
3257 0 : Py_END_ALLOW_THREADS
3258 :
3259 0 : if (result) {
3260 0 : return_value = path_error("link", &dst);
3261 0 : goto exit;
3262 : }
3263 : #endif
3264 :
3265 0 : return_value = Py_None;
3266 0 : Py_INCREF(Py_None);
3267 :
3268 : exit:
3269 0 : path_cleanup(&src);
3270 0 : path_cleanup(&dst);
3271 0 : return return_value;
3272 : }
3273 : #endif
3274 :
3275 :
3276 :
3277 : PyDoc_STRVAR(posix_listdir__doc__,
3278 : "listdir(path='.') -> list_of_filenames\n\n\
3279 : Return a list containing the names of the files in the directory.\n\
3280 : The list is in arbitrary order. It does not include the special\n\
3281 : entries '.' and '..' even if they are present in the directory.\n\
3282 : \n\
3283 : path can be specified as either str or bytes. If path is bytes,\n\
3284 : the filenames returned will also be bytes; in all other circumstances\n\
3285 : the filenames returned will be str.\n\
3286 : On some platforms, path may also be specified as an open file descriptor;\n\
3287 : the file descriptor must refer to a directory.\n\
3288 : If this functionality is unavailable, using it raises NotImplementedError.");
3289 :
3290 : static PyObject *
3291 11 : posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs)
3292 : {
3293 : path_t path;
3294 11 : PyObject *list = NULL;
3295 : static char *keywords[] = {"path", NULL};
3296 11 : int fd = -1;
3297 :
3298 : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3299 : PyObject *v;
3300 : HANDLE hFindFile = INVALID_HANDLE_VALUE;
3301 : BOOL result;
3302 : WIN32_FIND_DATA FileData;
3303 : char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
3304 : char *bufptr = namebuf;
3305 : /* only claim to have space for MAX_PATH */
3306 : Py_ssize_t len = sizeof(namebuf)-5;
3307 : PyObject *po = NULL;
3308 : wchar_t *wnamebuf = NULL;
3309 : #elif defined(PYOS_OS2)
3310 : #ifndef MAX_PATH
3311 : #define MAX_PATH CCHMAXPATH
3312 : #endif
3313 : char *pt;
3314 : PyObject *v;
3315 : char namebuf[MAX_PATH+5];
3316 : HDIR hdir = 1;
3317 : ULONG srchcnt = 1;
3318 : FILEFINDBUF3 ep;
3319 : APIRET rc;
3320 : #else
3321 : PyObject *v;
3322 11 : DIR *dirp = NULL;
3323 : struct dirent *ep;
3324 : int return_str; /* if false, return bytes */
3325 : #endif
3326 :
3327 11 : memset(&path, 0, sizeof(path));
3328 11 : path.nullable = 1;
3329 : #ifdef HAVE_FDOPENDIR
3330 11 : path.allow_fd = 1;
3331 11 : path.fd = -1;
3332 : #endif
3333 11 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", keywords,
3334 : path_converter, &path
3335 : ))
3336 0 : return NULL;
3337 :
3338 : /* XXX Should redo this putting the (now four) versions of opendir
3339 : in separate files instead of having them all here... */
3340 : #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
3341 : if (!path.narrow) {
3342 : WIN32_FIND_DATAW wFileData;
3343 : wchar_t *po_wchars;
3344 :
3345 : if (!path.wide) { /* Default arg: "." */
3346 : po_wchars = L".";
3347 : len = 1;
3348 : } else {
3349 : po_wchars = path.wide;
3350 : len = wcslen(path.wide);
3351 : }
3352 : /* The +5 is so we can append "\\*.*\0" */
3353 : wnamebuf = malloc((len + 5) * sizeof(wchar_t));
3354 : if (!wnamebuf) {
3355 : PyErr_NoMemory();
3356 : goto exit;
3357 : }
3358 : wcscpy(wnamebuf, po_wchars);
3359 : if (len > 0) {
3360 : wchar_t wch = wnamebuf[len-1];
3361 : if (wch != L'/' && wch != L'\\' && wch != L':')
3362 : wnamebuf[len++] = L'\\';
3363 : wcscpy(wnamebuf + len, L"*.*");
3364 : }
3365 : if ((list = PyList_New(0)) == NULL) {
3366 : goto exit;
3367 : }
3368 : Py_BEGIN_ALLOW_THREADS
3369 : hFindFile = FindFirstFileW(wnamebuf, &wFileData);
3370 : Py_END_ALLOW_THREADS
3371 : if (hFindFile == INVALID_HANDLE_VALUE) {
3372 : int error = GetLastError();
3373 : if (error == ERROR_FILE_NOT_FOUND)
3374 : goto exit;
3375 : Py_DECREF(list);
3376 : list = NULL;
3377 : win32_error_unicode("FindFirstFileW", wnamebuf);
3378 : goto exit;
3379 : }
3380 : do {
3381 : /* Skip over . and .. */
3382 : if (wcscmp(wFileData.cFileName, L".") != 0 &&
3383 : wcscmp(wFileData.cFileName, L"..") != 0) {
3384 : v = PyUnicode_FromWideChar(wFileData.cFileName,
3385 : wcslen(wFileData.cFileName));
3386 : if (v == NULL) {
3387 : Py_DECREF(list);
3388 : list = NULL;
3389 : break;
3390 : }
3391 : if (PyList_Append(list, v) != 0) {
3392 : Py_DECREF(v);
3393 : Py_DECREF(list);
3394 : list = NULL;
3395 : break;
3396 : }
3397 : Py_DECREF(v);
3398 : }
3399 : Py_BEGIN_ALLOW_THREADS
3400 : result = FindNextFileW(hFindFile, &wFileData);
3401 : Py_END_ALLOW_THREADS
3402 : /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3403 : it got to the end of the directory. */
3404 : if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3405 : Py_DECREF(list);
3406 : list = win32_error_unicode("FindNextFileW", wnamebuf);
3407 : goto exit;
3408 : }
3409 : } while (result == TRUE);
3410 :
3411 : goto exit;
3412 : }
3413 : strcpy(namebuf, path.narrow);
3414 : len = path.length;
3415 : if (len > 0) {
3416 : char ch = namebuf[len-1];
3417 : if (ch != SEP && ch != ALTSEP && ch != ':')
3418 : namebuf[len++] = '/';
3419 : strcpy(namebuf + len, "*.*");
3420 : }
3421 :
3422 : if ((list = PyList_New(0)) == NULL)
3423 : return NULL;
3424 :
3425 : Py_BEGIN_ALLOW_THREADS
3426 : hFindFile = FindFirstFile(namebuf, &FileData);
3427 : Py_END_ALLOW_THREADS
3428 : if (hFindFile == INVALID_HANDLE_VALUE) {
3429 : int error = GetLastError();
3430 : if (error == ERROR_FILE_NOT_FOUND)
3431 : goto exit;
3432 : Py_DECREF(list);
3433 : list = win32_error("FindFirstFile", namebuf);
3434 : goto exit;
3435 : }
3436 : do {
3437 : /* Skip over . and .. */
3438 : if (strcmp(FileData.cFileName, ".") != 0 &&
3439 : strcmp(FileData.cFileName, "..") != 0) {
3440 : v = PyBytes_FromString(FileData.cFileName);
3441 : if (v == NULL) {
3442 : Py_DECREF(list);
3443 : list = NULL;
3444 : break;
3445 : }
3446 : if (PyList_Append(list, v) != 0) {
3447 : Py_DECREF(v);
3448 : Py_DECREF(list);
3449 : list = NULL;
3450 : break;
3451 : }
3452 : Py_DECREF(v);
3453 : }
3454 : Py_BEGIN_ALLOW_THREADS
3455 : result = FindNextFile(hFindFile, &FileData);
3456 : Py_END_ALLOW_THREADS
3457 : /* FindNextFile sets error to ERROR_NO_MORE_FILES if
3458 : it got to the end of the directory. */
3459 : if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
3460 : Py_DECREF(list);
3461 : list = win32_error("FindNextFile", namebuf);
3462 : goto exit;
3463 : }
3464 : } while (result == TRUE);
3465 :
3466 : exit:
3467 : if (hFindFile != INVALID_HANDLE_VALUE) {
3468 : if (FindClose(hFindFile) == FALSE) {
3469 : if (list != NULL) {
3470 : Py_DECREF(list);
3471 : list = win32_error_object("FindClose", path.object);
3472 : }
3473 : }
3474 : }
3475 : if (wnamebuf)
3476 : free(wnamebuf);
3477 : path_cleanup(&path);
3478 :
3479 : return list;
3480 :
3481 : #elif defined(PYOS_OS2)
3482 : if (path.length >= MAX_PATH) {
3483 : PyErr_SetString(PyExc_ValueError, "path too long");
3484 : goto exit;
3485 : }
3486 : strcpy(namebuf, path.narrow);
3487 : for (pt = namebuf; *pt; pt++)
3488 : if (*pt == ALTSEP)
3489 : *pt = SEP;
3490 : if (namebuf[len-1] != SEP)
3491 : namebuf[len++] = SEP;
3492 : strcpy(namebuf + len, "*.*");
3493 :
3494 : if ((list = PyList_New(0)) == NULL) {
3495 : goto exit;
3496 : }
3497 :
3498 : rc = DosFindFirst(namebuf, /* Wildcard Pattern to Match */
3499 : &hdir, /* Handle to Use While Search Directory */
3500 : FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
3501 : &ep, sizeof(ep), /* Structure to Receive Directory Entry */
3502 : &srchcnt, /* Max and Actual Count of Entries Per Iteration */
3503 : FIL_STANDARD); /* Format of Entry (EAs or Not) */
3504 :
3505 : if (rc != NO_ERROR) {
3506 : errno = ENOENT;
3507 : Py_DECREF(list);
3508 : list = posix_error_with_filename(path.narrow);
3509 : goto exit;
3510 : }
3511 :
3512 : if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
3513 : do {
3514 : if (ep.achName[0] == '.'
3515 : && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
3516 : continue; /* Skip Over "." and ".." Names */
3517 :
3518 : strcpy(namebuf, ep.achName);
3519 :
3520 : /* Leave Case of Name Alone -- In Native Form */
3521 : /* (Removed Forced Lowercasing Code) */
3522 :
3523 : v = PyBytes_FromString(namebuf);
3524 : if (v == NULL) {
3525 : Py_DECREF(list);
3526 : list = NULL;
3527 : break;
3528 : }
3529 : if (PyList_Append(list, v) != 0) {
3530 : Py_DECREF(v);
3531 : Py_DECREF(list);
3532 : list = NULL;
3533 : break;
3534 : }
3535 : Py_DECREF(v);
3536 : } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
3537 : }
3538 :
3539 : exit:
3540 : path_cleanup(&path);
3541 :
3542 : return list;
3543 : #else
3544 :
3545 11 : errno = 0;
3546 : #ifdef HAVE_FDOPENDIR
3547 11 : if (path.fd != -1) {
3548 : /* closedir() closes the FD, so we duplicate it */
3549 0 : Py_BEGIN_ALLOW_THREADS
3550 0 : fd = dup(path.fd);
3551 0 : Py_END_ALLOW_THREADS
3552 :
3553 0 : if (fd == -1) {
3554 0 : list = posix_error();
3555 0 : goto exit;
3556 : }
3557 :
3558 0 : return_str = 1;
3559 :
3560 0 : Py_BEGIN_ALLOW_THREADS
3561 0 : dirp = fdopendir(fd);
3562 0 : Py_END_ALLOW_THREADS
3563 : }
3564 : else
3565 : #endif
3566 : {
3567 : char *name;
3568 11 : if (path.narrow) {
3569 11 : name = path.narrow;
3570 : /* only return bytes if they specified a bytes object */
3571 11 : return_str = !(PyBytes_Check(path.object));
3572 : }
3573 : else {
3574 0 : name = ".";
3575 0 : return_str = 1;
3576 : }
3577 :
3578 11 : Py_BEGIN_ALLOW_THREADS
3579 11 : dirp = opendir(name);
3580 11 : Py_END_ALLOW_THREADS
3581 : }
3582 :
3583 11 : if (dirp == NULL) {
3584 0 : list = path_error("listdir", &path);
3585 0 : goto exit;
3586 : }
3587 11 : if ((list = PyList_New(0)) == NULL) {
3588 0 : goto exit;
3589 : }
3590 : for (;;) {
3591 942 : errno = 0;
3592 942 : Py_BEGIN_ALLOW_THREADS
3593 942 : ep = readdir(dirp);
3594 942 : Py_END_ALLOW_THREADS
3595 942 : if (ep == NULL) {
3596 11 : if (errno == 0) {
3597 11 : break;
3598 : } else {
3599 0 : Py_DECREF(list);
3600 0 : list = path_error("listdir", &path);
3601 0 : goto exit;
3602 : }
3603 : }
3604 954 : if (ep->d_name[0] == '.' &&
3605 35 : (NAMLEN(ep) == 1 ||
3606 23 : (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
3607 22 : continue;
3608 909 : if (return_str)
3609 909 : v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
3610 : else
3611 0 : v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
3612 909 : if (v == NULL) {
3613 0 : Py_CLEAR(list);
3614 0 : break;
3615 : }
3616 909 : if (PyList_Append(list, v) != 0) {
3617 0 : Py_DECREF(v);
3618 0 : Py_CLEAR(list);
3619 0 : break;
3620 : }
3621 909 : Py_DECREF(v);
3622 931 : }
3623 :
3624 : exit:
3625 11 : if (dirp != NULL) {
3626 11 : Py_BEGIN_ALLOW_THREADS
3627 11 : if (fd > -1)
3628 0 : rewinddir(dirp);
3629 11 : closedir(dirp);
3630 11 : Py_END_ALLOW_THREADS
3631 : }
3632 :
3633 11 : path_cleanup(&path);
3634 :
3635 11 : return list;
3636 :
3637 : #endif /* which OS */
3638 : } /* end of posix_listdir */
3639 :
3640 : #ifdef MS_WINDOWS
3641 : /* A helper function for abspath on win32 */
3642 : static PyObject *
3643 : posix__getfullpathname(PyObject *self, PyObject *args)
3644 : {
3645 : const char *path;
3646 : char outbuf[MAX_PATH*2];
3647 : char *temp;
3648 : PyObject *po;
3649 :
3650 : if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po))
3651 : {
3652 : wchar_t *wpath;
3653 : wchar_t woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
3654 : wchar_t *wtemp;
3655 : DWORD result;
3656 : PyObject *v;
3657 :
3658 : wpath = PyUnicode_AsUnicode(po);
3659 : if (wpath == NULL)
3660 : return NULL;
3661 : result = GetFullPathNameW(wpath,
3662 : Py_ARRAY_LENGTH(woutbuf),
3663 : woutbuf, &wtemp);
3664 : if (result > Py_ARRAY_LENGTH(woutbuf)) {
3665 : woutbufp = malloc(result * sizeof(wchar_t));
3666 : if (!woutbufp)
3667 : return PyErr_NoMemory();
3668 : result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
3669 : }
3670 : if (result)
3671 : v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp));
3672 : else
3673 : v = win32_error_object("GetFullPathNameW", po);
3674 : if (woutbufp != woutbuf)
3675 : free(woutbufp);
3676 : return v;
3677 : }
3678 : /* Drop the argument parsing error as narrow strings
3679 : are also valid. */
3680 : PyErr_Clear();
3681 :
3682 : if (!PyArg_ParseTuple (args, "y:_getfullpathname",
3683 : &path))
3684 : return NULL;
3685 : if (win32_warn_bytes_api())
3686 : return NULL;
3687 : if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf),
3688 : outbuf, &temp)) {
3689 : win32_error("GetFullPathName", path);
3690 : return NULL;
3691 : }
3692 : if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
3693 : return PyUnicode_Decode(outbuf, strlen(outbuf),
3694 : Py_FileSystemDefaultEncoding, NULL);
3695 : }
3696 : return PyBytes_FromString(outbuf);
3697 : } /* end of posix__getfullpathname */
3698 :
3699 :
3700 :
3701 : /* A helper function for samepath on windows */
3702 : static PyObject *
3703 : posix__getfinalpathname(PyObject *self, PyObject *args)
3704 : {
3705 : HANDLE hFile;
3706 : int buf_size;
3707 : wchar_t *target_path;
3708 : int result_length;
3709 : PyObject *po, *result;
3710 : wchar_t *path;
3711 :
3712 : if (!PyArg_ParseTuple(args, "U|:_getfinalpathname", &po))
3713 : return NULL;
3714 : path = PyUnicode_AsUnicode(po);
3715 : if (path == NULL)
3716 : return NULL;
3717 :
3718 : if(!check_GetFinalPathNameByHandle()) {
3719 : /* If the OS doesn't have GetFinalPathNameByHandle, return a
3720 : NotImplementedError. */
3721 : return PyErr_Format(PyExc_NotImplementedError,
3722 : "GetFinalPathNameByHandle not available on this platform");
3723 : }
3724 :
3725 : hFile = CreateFileW(
3726 : path,
3727 : 0, /* desired access */
3728 : 0, /* share mode */
3729 : NULL, /* security attributes */
3730 : OPEN_EXISTING,
3731 : /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
3732 : FILE_FLAG_BACKUP_SEMANTICS,
3733 : NULL);
3734 :
3735 : if(hFile == INVALID_HANDLE_VALUE)
3736 : return win32_error_object("CreateFileW", po);
3737 :
3738 : /* We have a good handle to the target, use it to determine the
3739 : target path name. */
3740 : buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);
3741 :
3742 : if(!buf_size)
3743 : return win32_error_object("GetFinalPathNameByHandle", po);
3744 :
3745 : target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
3746 : if(!target_path)
3747 : return PyErr_NoMemory();
3748 :
3749 : result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
3750 : buf_size, VOLUME_NAME_DOS);
3751 : if(!result_length)
3752 : return win32_error_object("GetFinalPathNamyByHandle", po);
3753 :
3754 : if(!CloseHandle(hFile))
3755 : return win32_error_object("CloseHandle", po);
3756 :
3757 : target_path[result_length] = 0;
3758 : result = PyUnicode_FromWideChar(target_path, result_length);
3759 : free(target_path);
3760 : return result;
3761 :
3762 : } /* end of posix__getfinalpathname */
3763 :
3764 : static PyObject *
3765 : posix__getfileinformation(PyObject *self, PyObject *args)
3766 : {
3767 : HANDLE hFile;
3768 : BY_HANDLE_FILE_INFORMATION info;
3769 : int fd;
3770 :
3771 : if (!PyArg_ParseTuple(args, "i:_getfileinformation", &fd))
3772 : return NULL;
3773 :
3774 : if (!_PyVerify_fd(fd))
3775 : return posix_error();
3776 :
3777 : hFile = (HANDLE)_get_osfhandle(fd);
3778 : if (hFile == INVALID_HANDLE_VALUE)
3779 : return posix_error();
3780 :
3781 : if (!GetFileInformationByHandle(hFile, &info))
3782 : return win32_error("_getfileinformation", NULL);
3783 :
3784 : return Py_BuildValue("iii", info.dwVolumeSerialNumber,
3785 : info.nFileIndexHigh,
3786 : info.nFileIndexLow);
3787 : }
3788 :
3789 : PyDoc_STRVAR(posix__isdir__doc__,
3790 : "Return true if the pathname refers to an existing directory.");
3791 :
3792 : static PyObject *
3793 : posix__isdir(PyObject *self, PyObject *args)
3794 : {
3795 : const char *path;
3796 : PyObject *po;
3797 : DWORD attributes;
3798 :
3799 : if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
3800 : wchar_t *wpath = PyUnicode_AsUnicode(po);
3801 : if (wpath == NULL)
3802 : return NULL;
3803 :
3804 : attributes = GetFileAttributesW(wpath);
3805 : if (attributes == INVALID_FILE_ATTRIBUTES)
3806 : Py_RETURN_FALSE;
3807 : goto check;
3808 : }
3809 : /* Drop the argument parsing error as narrow strings
3810 : are also valid. */
3811 : PyErr_Clear();
3812 :
3813 : if (!PyArg_ParseTuple(args, "y:_isdir", &path))
3814 : return NULL;
3815 : if (win32_warn_bytes_api())
3816 : return NULL;
3817 : attributes = GetFileAttributesA(path);
3818 : if (attributes == INVALID_FILE_ATTRIBUTES)
3819 : Py_RETURN_FALSE;
3820 :
3821 : check:
3822 : if (attributes & FILE_ATTRIBUTE_DIRECTORY)
3823 : Py_RETURN_TRUE;
3824 : else
3825 : Py_RETURN_FALSE;
3826 : }
3827 : #endif /* MS_WINDOWS */
3828 :
3829 : PyDoc_STRVAR(posix_mkdir__doc__,
3830 : "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
3831 : Create a directory.\n\
3832 : \n\
3833 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
3834 : and path should be relative; path will then be relative to that directory.\n\
3835 : dir_fd may not be implemented on your platform.\n\
3836 : If it is unavailable, using it will raise a NotImplementedError.\n\
3837 : \n\
3838 : The mode argument is ignored on Windows.");
3839 :
3840 : static PyObject *
3841 0 : posix_mkdir(PyObject *self, PyObject *args, PyObject *kwargs)
3842 : {
3843 : path_t path;
3844 0 : int mode = 0777;
3845 0 : int dir_fd = DEFAULT_DIR_FD;
3846 : static char *keywords[] = {"path", "mode", "dir_fd", NULL};
3847 0 : PyObject *return_value = NULL;
3848 : int result;
3849 :
3850 0 : memset(&path, 0, sizeof(path));
3851 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", keywords,
3852 : path_converter, &path, &mode,
3853 : #ifdef HAVE_MKDIRAT
3854 : dir_fd_converter, &dir_fd
3855 : #else
3856 : dir_fd_unavailable, &dir_fd
3857 : #endif
3858 : ))
3859 0 : return NULL;
3860 :
3861 : #ifdef MS_WINDOWS
3862 : Py_BEGIN_ALLOW_THREADS
3863 : if (path.wide)
3864 : result = CreateDirectoryW(path.wide, NULL);
3865 : else
3866 : result = CreateDirectoryA(path.narrow, NULL);
3867 : Py_END_ALLOW_THREADS
3868 :
3869 : if (!result) {
3870 : return_value = win32_error_object("mkdir", path.object);
3871 : goto exit;
3872 : }
3873 : #else
3874 0 : Py_BEGIN_ALLOW_THREADS
3875 : #if HAVE_MKDIRAT
3876 0 : if (dir_fd != DEFAULT_DIR_FD)
3877 0 : result = mkdirat(dir_fd, path.narrow, mode);
3878 : else
3879 : #endif
3880 : #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
3881 : result = mkdir(path.narrow);
3882 : #else
3883 0 : result = mkdir(path.narrow, mode);
3884 : #endif
3885 0 : Py_END_ALLOW_THREADS
3886 0 : if (result < 0) {
3887 0 : return_value = path_error("mkdir", &path);
3888 0 : goto exit;
3889 : }
3890 : #endif
3891 0 : return_value = Py_None;
3892 0 : Py_INCREF(Py_None);
3893 : exit:
3894 0 : path_cleanup(&path);
3895 0 : return return_value;
3896 : }
3897 :
3898 :
3899 : /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
3900 : #if defined(HAVE_SYS_RESOURCE_H)
3901 : #include <sys/resource.h>
3902 : #endif
3903 :
3904 :
3905 : #ifdef HAVE_NICE
3906 : PyDoc_STRVAR(posix_nice__doc__,
3907 : "nice(inc) -> new_priority\n\n\
3908 : Decrease the priority of process by inc and return the new priority.");
3909 :
3910 : static PyObject *
3911 0 : posix_nice(PyObject *self, PyObject *args)
3912 : {
3913 : int increment, value;
3914 :
3915 0 : if (!PyArg_ParseTuple(args, "i:nice", &increment))
3916 0 : return NULL;
3917 :
3918 : /* There are two flavours of 'nice': one that returns the new
3919 : priority (as required by almost all standards out there) and the
3920 : Linux/FreeBSD/BSDI one, which returns '0' on success and advices
3921 : the use of getpriority() to get the new priority.
3922 :
3923 : If we are of the nice family that returns the new priority, we
3924 : need to clear errno before the call, and check if errno is filled
3925 : before calling posix_error() on a returnvalue of -1, because the
3926 : -1 may be the actual new priority! */
3927 :
3928 0 : errno = 0;
3929 0 : value = nice(increment);
3930 : #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
3931 : if (value == 0)
3932 : value = getpriority(PRIO_PROCESS, 0);
3933 : #endif
3934 0 : if (value == -1 && errno != 0)
3935 : /* either nice() or getpriority() returned an error */
3936 0 : return posix_error();
3937 0 : return PyLong_FromLong((long) value);
3938 : }
3939 : #endif /* HAVE_NICE */
3940 :
3941 :
3942 : #ifdef HAVE_GETPRIORITY
3943 : PyDoc_STRVAR(posix_getpriority__doc__,
3944 : "getpriority(which, who) -> current_priority\n\n\
3945 : Get program scheduling priority.");
3946 :
3947 : static PyObject *
3948 0 : posix_getpriority(PyObject *self, PyObject *args)
3949 : {
3950 : int which, who, retval;
3951 :
3952 0 : if (!PyArg_ParseTuple(args, "ii", &which, &who))
3953 0 : return NULL;
3954 0 : errno = 0;
3955 0 : retval = getpriority(which, who);
3956 0 : if (errno != 0)
3957 0 : return posix_error();
3958 0 : return PyLong_FromLong((long)retval);
3959 : }
3960 : #endif /* HAVE_GETPRIORITY */
3961 :
3962 :
3963 : #ifdef HAVE_SETPRIORITY
3964 : PyDoc_STRVAR(posix_setpriority__doc__,
3965 : "setpriority(which, who, prio) -> None\n\n\
3966 : Set program scheduling priority.");
3967 :
3968 : static PyObject *
3969 0 : posix_setpriority(PyObject *self, PyObject *args)
3970 : {
3971 : int which, who, prio, retval;
3972 :
3973 0 : if (!PyArg_ParseTuple(args, "iii", &which, &who, &prio))
3974 0 : return NULL;
3975 0 : retval = setpriority(which, who, prio);
3976 0 : if (retval == -1)
3977 0 : return posix_error();
3978 0 : Py_RETURN_NONE;
3979 : }
3980 : #endif /* HAVE_SETPRIORITY */
3981 :
3982 :
3983 : static PyObject *
3984 0 : internal_rename(PyObject *args, PyObject *kwargs, int is_replace)
3985 : {
3986 0 : char *function_name = is_replace ? "replace" : "rename";
3987 : path_t src;
3988 : path_t dst;
3989 0 : int src_dir_fd = DEFAULT_DIR_FD;
3990 0 : int dst_dir_fd = DEFAULT_DIR_FD;
3991 : int dir_fd_specified;
3992 0 : PyObject *return_value = NULL;
3993 : char format[24];
3994 : static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL};
3995 :
3996 : #ifdef MS_WINDOWS
3997 : BOOL result;
3998 : int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
3999 : #else
4000 : int result;
4001 : #endif
4002 :
4003 0 : memset(&src, 0, sizeof(src));
4004 0 : memset(&dst, 0, sizeof(dst));
4005 0 : strcpy(format, "O&O&|$O&O&:");
4006 0 : strcat(format, function_name);
4007 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, keywords,
4008 : path_converter, &src,
4009 : path_converter, &dst,
4010 : dir_fd_converter, &src_dir_fd,
4011 : dir_fd_converter, &dst_dir_fd))
4012 0 : return NULL;
4013 :
4014 0 : dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4015 0 : (dst_dir_fd != DEFAULT_DIR_FD);
4016 : #ifndef HAVE_RENAMEAT
4017 : if (dir_fd_specified) {
4018 : argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4019 : goto exit;
4020 : }
4021 : #endif
4022 :
4023 0 : if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
4024 0 : PyErr_Format(PyExc_ValueError,
4025 : "%s: src and dst must be the same type", function_name);
4026 0 : goto exit;
4027 : }
4028 :
4029 : #ifdef MS_WINDOWS
4030 : Py_BEGIN_ALLOW_THREADS
4031 : if (src.wide)
4032 : result = MoveFileExW(src.wide, dst.wide, flags);
4033 : else
4034 : result = MoveFileExA(src.narrow, dst.narrow, flags);
4035 : Py_END_ALLOW_THREADS
4036 :
4037 : if (!result) {
4038 : return_value = win32_error_object(function_name, dst.object);
4039 : goto exit;
4040 : }
4041 :
4042 : #else
4043 0 : Py_BEGIN_ALLOW_THREADS
4044 : #ifdef HAVE_RENAMEAT
4045 0 : if (dir_fd_specified)
4046 0 : result = renameat(src_dir_fd, src.narrow, dst_dir_fd, dst.narrow);
4047 : else
4048 : #endif
4049 0 : result = rename(src.narrow, dst.narrow);
4050 0 : Py_END_ALLOW_THREADS
4051 :
4052 0 : if (result) {
4053 0 : return_value = path_error(function_name, &dst);
4054 0 : goto exit;
4055 : }
4056 : #endif
4057 :
4058 0 : Py_INCREF(Py_None);
4059 0 : return_value = Py_None;
4060 : exit:
4061 0 : path_cleanup(&src);
4062 0 : path_cleanup(&dst);
4063 0 : return return_value;
4064 : }
4065 :
4066 : PyDoc_STRVAR(posix_rename__doc__,
4067 : "rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
4068 : Rename a file or directory.\n\
4069 : \n\
4070 : If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
4071 : descriptor open to a directory, and the respective path string (src or dst)\n\
4072 : should be relative; the path will then be relative to that directory.\n\
4073 : src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
4074 : If they are unavailable, using them will raise a NotImplementedError.");
4075 :
4076 : static PyObject *
4077 0 : posix_rename(PyObject *self, PyObject *args, PyObject *kwargs)
4078 : {
4079 0 : return internal_rename(args, kwargs, 0);
4080 : }
4081 :
4082 : PyDoc_STRVAR(posix_replace__doc__,
4083 : "replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n\n\
4084 : Rename a file or directory, overwriting the destination.\n\
4085 : \n\
4086 : If either src_dir_fd or dst_dir_fd is not None, it should be a file\n\
4087 : descriptor open to a directory, and the respective path string (src or dst)\n\
4088 : should be relative; the path will then be relative to that directory.\n\
4089 : src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n\
4090 : If they are unavailable, using them will raise a NotImplementedError.");
4091 :
4092 : static PyObject *
4093 0 : posix_replace(PyObject *self, PyObject *args, PyObject *kwargs)
4094 : {
4095 0 : return internal_rename(args, kwargs, 1);
4096 : }
4097 :
4098 : PyDoc_STRVAR(posix_rmdir__doc__,
4099 : "rmdir(path, *, dir_fd=None)\n\n\
4100 : Remove a directory.\n\
4101 : \n\
4102 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
4103 : and path should be relative; path will then be relative to that directory.\n\
4104 : dir_fd may not be implemented on your platform.\n\
4105 : If it is unavailable, using it will raise a NotImplementedError.");
4106 :
4107 : static PyObject *
4108 0 : posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs)
4109 : {
4110 : path_t path;
4111 0 : int dir_fd = DEFAULT_DIR_FD;
4112 : static char *keywords[] = {"path", "dir_fd", NULL};
4113 : int result;
4114 0 : PyObject *return_value = NULL;
4115 :
4116 0 : memset(&path, 0, sizeof(path));
4117 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords,
4118 : path_converter, &path,
4119 : #ifdef HAVE_UNLINKAT
4120 : dir_fd_converter, &dir_fd
4121 : #else
4122 : dir_fd_unavailable, &dir_fd
4123 : #endif
4124 : ))
4125 0 : return NULL;
4126 :
4127 0 : Py_BEGIN_ALLOW_THREADS
4128 : #ifdef MS_WINDOWS
4129 : if (path.wide)
4130 : result = RemoveDirectoryW(path.wide);
4131 : else
4132 : result = RemoveDirectoryA(path.narrow);
4133 : result = !result; /* Windows, success=1, UNIX, success=0 */
4134 : #else
4135 : #ifdef HAVE_UNLINKAT
4136 0 : if (dir_fd != DEFAULT_DIR_FD)
4137 0 : result = unlinkat(dir_fd, path.narrow, AT_REMOVEDIR);
4138 : else
4139 : #endif
4140 0 : result = rmdir(path.narrow);
4141 : #endif
4142 0 : Py_END_ALLOW_THREADS
4143 :
4144 0 : if (result) {
4145 0 : return_value = path_error("rmdir", &path);
4146 0 : goto exit;
4147 : }
4148 :
4149 0 : return_value = Py_None;
4150 0 : Py_INCREF(Py_None);
4151 :
4152 : exit:
4153 0 : path_cleanup(&path);
4154 0 : return return_value;
4155 : }
4156 :
4157 :
4158 : #ifdef HAVE_SYSTEM
4159 : PyDoc_STRVAR(posix_system__doc__,
4160 : "system(command) -> exit_status\n\n\
4161 : Execute the command (a string) in a subshell.");
4162 :
4163 : static PyObject *
4164 0 : posix_system(PyObject *self, PyObject *args)
4165 : {
4166 : long sts;
4167 : #ifdef MS_WINDOWS
4168 : wchar_t *command;
4169 : if (!PyArg_ParseTuple(args, "u:system", &command))
4170 : return NULL;
4171 :
4172 : Py_BEGIN_ALLOW_THREADS
4173 : sts = _wsystem(command);
4174 : Py_END_ALLOW_THREADS
4175 : #else
4176 : PyObject *command_obj;
4177 : char *command;
4178 0 : if (!PyArg_ParseTuple(args, "O&:system",
4179 : PyUnicode_FSConverter, &command_obj))
4180 0 : return NULL;
4181 :
4182 0 : command = PyBytes_AsString(command_obj);
4183 0 : Py_BEGIN_ALLOW_THREADS
4184 0 : sts = system(command);
4185 0 : Py_END_ALLOW_THREADS
4186 0 : Py_DECREF(command_obj);
4187 : #endif
4188 0 : return PyLong_FromLong(sts);
4189 : }
4190 : #endif
4191 :
4192 :
4193 : PyDoc_STRVAR(posix_umask__doc__,
4194 : "umask(new_mask) -> old_mask\n\n\
4195 : Set the current numeric umask and return the previous umask.");
4196 :
4197 : static PyObject *
4198 0 : posix_umask(PyObject *self, PyObject *args)
4199 : {
4200 : int i;
4201 0 : if (!PyArg_ParseTuple(args, "i:umask", &i))
4202 0 : return NULL;
4203 0 : i = (int)umask(i);
4204 0 : if (i < 0)
4205 0 : return posix_error();
4206 0 : return PyLong_FromLong((long)i);
4207 : }
4208 :
4209 : #ifdef MS_WINDOWS
4210 :
4211 : /* override the default DeleteFileW behavior so that directory
4212 : symlinks can be removed with this function, the same as with
4213 : Unix symlinks */
4214 : BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4215 : {
4216 : WIN32_FILE_ATTRIBUTE_DATA info;
4217 : WIN32_FIND_DATAW find_data;
4218 : HANDLE find_data_handle;
4219 : int is_directory = 0;
4220 : int is_link = 0;
4221 :
4222 : if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4223 : is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4224 :
4225 : /* Get WIN32_FIND_DATA structure for the path to determine if
4226 : it is a symlink */
4227 : if(is_directory &&
4228 : info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4229 : find_data_handle = FindFirstFileW(lpFileName, &find_data);
4230 :
4231 : if(find_data_handle != INVALID_HANDLE_VALUE) {
4232 : is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
4233 : FindClose(find_data_handle);
4234 : }
4235 : }
4236 : }
4237 :
4238 : if (is_directory && is_link)
4239 : return RemoveDirectoryW(lpFileName);
4240 :
4241 : return DeleteFileW(lpFileName);
4242 : }
4243 : #endif /* MS_WINDOWS */
4244 :
4245 : PyDoc_STRVAR(posix_unlink__doc__,
4246 : "unlink(path, *, dir_fd=None)\n\n\
4247 : Remove a file (same as remove()).\n\
4248 : \n\
4249 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
4250 : and path should be relative; path will then be relative to that directory.\n\
4251 : dir_fd may not be implemented on your platform.\n\
4252 : If it is unavailable, using it will raise a NotImplementedError.");
4253 :
4254 : PyDoc_STRVAR(posix_remove__doc__,
4255 : "remove(path, *, dir_fd=None)\n\n\
4256 : Remove a file (same as unlink()).\n\
4257 : \n\
4258 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
4259 : and path should be relative; path will then be relative to that directory.\n\
4260 : dir_fd may not be implemented on your platform.\n\
4261 : If it is unavailable, using it will raise a NotImplementedError.");
4262 :
4263 : static PyObject *
4264 0 : posix_unlink(PyObject *self, PyObject *args, PyObject *kwargs)
4265 : {
4266 : path_t path;
4267 0 : int dir_fd = DEFAULT_DIR_FD;
4268 : static char *keywords[] = {"path", "dir_fd", NULL};
4269 : int result;
4270 0 : PyObject *return_value = NULL;
4271 :
4272 0 : memset(&path, 0, sizeof(path));
4273 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:unlink", keywords,
4274 : path_converter, &path,
4275 : #ifdef HAVE_UNLINKAT
4276 : dir_fd_converter, &dir_fd
4277 : #else
4278 : dir_fd_unavailable, &dir_fd
4279 : #endif
4280 : ))
4281 0 : return NULL;
4282 :
4283 0 : Py_BEGIN_ALLOW_THREADS
4284 : #ifdef MS_WINDOWS
4285 : if (path.wide)
4286 : result = Py_DeleteFileW(path.wide);
4287 : else
4288 : result = DeleteFileA(path.narrow);
4289 : result = !result; /* Windows, success=1, UNIX, success=0 */
4290 : #else
4291 : #ifdef HAVE_UNLINKAT
4292 0 : if (dir_fd != DEFAULT_DIR_FD)
4293 0 : result = unlinkat(dir_fd, path.narrow, 0);
4294 : else
4295 : #endif /* HAVE_UNLINKAT */
4296 0 : result = unlink(path.narrow);
4297 : #endif
4298 0 : Py_END_ALLOW_THREADS
4299 :
4300 0 : if (result) {
4301 0 : return_value = path_error("unlink", &path);
4302 0 : goto exit;
4303 : }
4304 :
4305 0 : return_value = Py_None;
4306 0 : Py_INCREF(Py_None);
4307 :
4308 : exit:
4309 0 : path_cleanup(&path);
4310 0 : return return_value;
4311 : }
4312 :
4313 :
4314 : PyDoc_STRVAR(posix_uname__doc__,
4315 : "uname() -> uname_result\n\n\
4316 : Return an object identifying the current operating system.\n\
4317 : The object behaves like a named tuple with the following fields:\n\
4318 : (sysname, nodename, release, version, machine)");
4319 :
4320 : static PyStructSequence_Field uname_result_fields[] = {
4321 : {"sysname", "operating system name"},
4322 : {"nodename", "name of machine on network (implementation-defined)"},
4323 : {"release", "operating system release"},
4324 : {"version", "operating system version"},
4325 : {"machine", "hardware identifier"},
4326 : {NULL}
4327 : };
4328 :
4329 : PyDoc_STRVAR(uname_result__doc__,
4330 : "uname_result: Result from os.uname().\n\n\
4331 : This object may be accessed either as a tuple of\n\
4332 : (sysname, nodename, release, version, machine),\n\
4333 : or via the attributes sysname, nodename, release, version, and machine.\n\
4334 : \n\
4335 : See os.uname for more information.");
4336 :
4337 : static PyStructSequence_Desc uname_result_desc = {
4338 : "uname_result", /* name */
4339 : uname_result__doc__, /* doc */
4340 : uname_result_fields,
4341 : 5
4342 : };
4343 :
4344 : static PyTypeObject UnameResultType;
4345 :
4346 :
4347 : #ifdef HAVE_UNAME
4348 : static PyObject *
4349 0 : posix_uname(PyObject *self, PyObject *noargs)
4350 : {
4351 : struct utsname u;
4352 : int res;
4353 : PyObject *value;
4354 :
4355 0 : Py_BEGIN_ALLOW_THREADS
4356 0 : res = uname(&u);
4357 0 : Py_END_ALLOW_THREADS
4358 0 : if (res < 0)
4359 0 : return posix_error();
4360 :
4361 0 : value = PyStructSequence_New(&UnameResultType);
4362 0 : if (value == NULL)
4363 0 : return NULL;
4364 :
4365 : #define SET(i, field) \
4366 : { \
4367 : PyObject *o = PyUnicode_DecodeASCII(field, strlen(field), NULL); \
4368 : if (!o) { \
4369 : Py_DECREF(value); \
4370 : return NULL; \
4371 : } \
4372 : PyStructSequence_SET_ITEM(value, i, o); \
4373 : } \
4374 :
4375 0 : SET(0, u.sysname);
4376 0 : SET(1, u.nodename);
4377 0 : SET(2, u.release);
4378 0 : SET(3, u.version);
4379 0 : SET(4, u.machine);
4380 :
4381 : #undef SET
4382 :
4383 0 : return value;
4384 : }
4385 : #endif /* HAVE_UNAME */
4386 :
4387 :
4388 : PyDoc_STRVAR(posix_utime__doc__,
4389 : "utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\
4390 : Set the access and modified time of path.\n\
4391 : \n\
4392 : path may always be specified as a string.\n\
4393 : On some platforms, path may also be specified as an open file descriptor.\n\
4394 : If this functionality is unavailable, using it raises an exception.\n\
4395 : \n\
4396 : If times is not None, it must be a tuple (atime, mtime);\n\
4397 : atime and mtime should be expressed as float seconds since the epoch.\n\
4398 : If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n\
4399 : atime_ns and mtime_ns should be expressed as integer nanoseconds\n\
4400 : since the epoch.\n\
4401 : If both times and ns are None, utime uses the current time.\n\
4402 : Specifying tuples for both times and ns is an error.\n\
4403 : \n\
4404 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
4405 : and path should be relative; path will then be relative to that directory.\n\
4406 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
4407 : link, utime will modify the symbolic link itself instead of the file the\n\
4408 : link points to.\n\
4409 : It is an error to use dir_fd or follow_symlinks when specifying path\n\
4410 : as an open file descriptor.\n\
4411 : dir_fd and follow_symlinks may not be available on your platform.\n\
4412 : If they are unavailable, using them will raise a NotImplementedError.");
4413 :
4414 : typedef struct {
4415 : int now;
4416 : time_t atime_s;
4417 : long atime_ns;
4418 : time_t mtime_s;
4419 : long mtime_ns;
4420 : } utime_t;
4421 :
4422 : /*
4423 : * these macros assume that "utime" is a pointer to a utime_t
4424 : * they also intentionally leak the declaration of a pointer named "time"
4425 : */
4426 : #define UTIME_TO_TIMESPEC \
4427 : struct timespec ts[2]; \
4428 : struct timespec *time; \
4429 : if (utime->now) \
4430 : time = NULL; \
4431 : else { \
4432 : ts[0].tv_sec = utime->atime_s; \
4433 : ts[0].tv_nsec = utime->atime_ns; \
4434 : ts[1].tv_sec = utime->mtime_s; \
4435 : ts[1].tv_nsec = utime->mtime_ns; \
4436 : time = ts; \
4437 : } \
4438 :
4439 : #define UTIME_TO_TIMEVAL \
4440 : struct timeval tv[2]; \
4441 : struct timeval *time; \
4442 : if (utime->now) \
4443 : time = NULL; \
4444 : else { \
4445 : tv[0].tv_sec = utime->atime_s; \
4446 : tv[0].tv_usec = utime->atime_ns / 1000; \
4447 : tv[1].tv_sec = utime->mtime_s; \
4448 : tv[1].tv_usec = utime->mtime_ns / 1000; \
4449 : time = tv; \
4450 : } \
4451 :
4452 : #define UTIME_TO_UTIMBUF \
4453 : struct utimbuf u[2]; \
4454 : struct utimbuf *time; \
4455 : if (utime->now) \
4456 : time = NULL; \
4457 : else { \
4458 : u.actime = utime->atime_s; \
4459 : u.modtime = utime->mtime_s; \
4460 : time = u; \
4461 : }
4462 :
4463 : #define UTIME_TO_TIME_T \
4464 : time_t timet[2]; \
4465 : struct timet time; \
4466 : if (utime->now) \
4467 : time = NULL; \
4468 : else { \
4469 : timet[0] = utime->atime_s; \
4470 : timet[1] = utime->mtime_s; \
4471 : time = &timet; \
4472 : } \
4473 :
4474 :
4475 : #define UTIME_HAVE_DIR_FD (defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT))
4476 :
4477 : #if UTIME_HAVE_DIR_FD
4478 :
4479 : static int
4480 0 : utime_dir_fd(utime_t *utime, int dir_fd, char *path, int follow_symlinks)
4481 : {
4482 : #ifdef HAVE_UTIMENSAT
4483 0 : int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
4484 0 : UTIME_TO_TIMESPEC;
4485 0 : return utimensat(dir_fd, path, time, flags);
4486 : #elif defined(HAVE_FUTIMESAT)
4487 : UTIME_TO_TIMEVAL;
4488 : /*
4489 : * follow_symlinks will never be false here;
4490 : * we only allow !follow_symlinks and dir_fd together
4491 : * if we have utimensat()
4492 : */
4493 : assert(follow_symlinks);
4494 : return futimesat(dir_fd, path, time);
4495 : #endif
4496 : }
4497 :
4498 : #endif
4499 :
4500 : #define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS))
4501 :
4502 : #if UTIME_HAVE_FD
4503 :
4504 : static int
4505 0 : utime_fd(utime_t *utime, int fd)
4506 : {
4507 : #ifdef HAVE_FUTIMENS
4508 0 : UTIME_TO_TIMESPEC;
4509 0 : return futimens(fd, time);
4510 : #else
4511 : UTIME_TO_TIMEVAL;
4512 : return futimes(fd, time);
4513 : #endif
4514 : }
4515 :
4516 : #endif
4517 :
4518 :
4519 : #define UTIME_HAVE_NOFOLLOW_SYMLINKS \
4520 : (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES))
4521 :
4522 : #if UTIME_HAVE_NOFOLLOW_SYMLINKS
4523 :
4524 : static int
4525 0 : utime_nofollow_symlinks(utime_t *utime, char *path)
4526 : {
4527 : #ifdef HAVE_UTIMENSAT
4528 0 : UTIME_TO_TIMESPEC;
4529 0 : return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
4530 : #else
4531 : UTIME_TO_TIMEVAL;
4532 : return lutimes(path, time);
4533 : #endif
4534 : }
4535 :
4536 : #endif
4537 :
4538 : #ifndef MS_WINDOWS
4539 :
4540 : static int
4541 0 : utime_default(utime_t *utime, char *path)
4542 : {
4543 : #ifdef HAVE_UTIMENSAT
4544 0 : UTIME_TO_TIMESPEC;
4545 0 : return utimensat(DEFAULT_DIR_FD, path, time, 0);
4546 : #elif defined(HAVE_UTIMES)
4547 : UTIME_TO_TIMEVAL;
4548 : return utimes(path, time);
4549 : #elif defined(HAVE_UTIME_H)
4550 : UTIME_TO_UTIMBUF;
4551 : return utime(path, time);
4552 : #else
4553 : UTIME_TO_TIME_T;
4554 : return utime(path, time);
4555 : #endif
4556 : }
4557 :
4558 : #endif
4559 :
4560 : static int
4561 0 : split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns)
4562 : {
4563 0 : int result = 0;
4564 : PyObject *divmod;
4565 0 : divmod = PyNumber_Divmod(py_long, billion);
4566 0 : if (!divmod)
4567 0 : goto exit;
4568 0 : *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
4569 0 : if ((*s == -1) && PyErr_Occurred())
4570 0 : goto exit;
4571 0 : *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
4572 0 : if ((*ns == -1) && PyErr_Occurred())
4573 0 : goto exit;
4574 :
4575 0 : result = 1;
4576 : exit:
4577 0 : Py_XDECREF(divmod);
4578 0 : return result;
4579 : }
4580 :
4581 : static PyObject *
4582 0 : posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
4583 : {
4584 : path_t path;
4585 0 : PyObject *times = NULL;
4586 0 : PyObject *ns = NULL;
4587 0 : int dir_fd = DEFAULT_DIR_FD;
4588 0 : int follow_symlinks = 1;
4589 0 : char *keywords[] = {"path", "times", "ns", "dir_fd",
4590 : "follow_symlinks", NULL};
4591 :
4592 : utime_t utime;
4593 :
4594 : #ifdef MS_WINDOWS
4595 : HANDLE hFile;
4596 : FILETIME atime, mtime;
4597 : #else
4598 : int result;
4599 : #endif
4600 :
4601 0 : PyObject *return_value = NULL;
4602 :
4603 0 : memset(&path, 0, sizeof(path));
4604 : #if UTIME_HAVE_FD
4605 0 : path.allow_fd = 1;
4606 : #endif
4607 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs,
4608 : "O&|O$OO&p:utime", keywords,
4609 : path_converter, &path,
4610 : ×, &ns,
4611 : #if UTIME_HAVE_DIR_FD
4612 : dir_fd_converter, &dir_fd,
4613 : #else
4614 : dir_fd_unavailable, &dir_fd,
4615 : #endif
4616 : &follow_symlinks
4617 : ))
4618 0 : return NULL;
4619 :
4620 0 : if (times && (times != Py_None) && ns) {
4621 0 : PyErr_SetString(PyExc_ValueError,
4622 : "utime: you may specify either 'times'"
4623 : " or 'ns' but not both");
4624 0 : goto exit;
4625 : }
4626 :
4627 0 : if (times && (times != Py_None)) {
4628 0 : if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
4629 0 : PyErr_SetString(PyExc_TypeError,
4630 : "utime: 'times' must be either"
4631 : " a tuple of two ints or None");
4632 0 : goto exit;
4633 : }
4634 0 : utime.now = 0;
4635 0 : if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
4636 0 : &utime.atime_s, &utime.atime_ns) == -1 ||
4637 0 : _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
4638 : &utime.mtime_s, &utime.mtime_ns) == -1) {
4639 : goto exit;
4640 : }
4641 : }
4642 0 : else if (ns) {
4643 0 : if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
4644 0 : PyErr_SetString(PyExc_TypeError,
4645 : "utime: 'ns' must be a tuple of two ints");
4646 0 : goto exit;
4647 : }
4648 0 : utime.now = 0;
4649 0 : if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0),
4650 0 : &utime.atime_s, &utime.atime_ns) ||
4651 0 : !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1),
4652 : &utime.mtime_s, &utime.mtime_ns)) {
4653 : goto exit;
4654 : }
4655 : }
4656 : else {
4657 : /* times and ns are both None/unspecified. use "now". */
4658 0 : utime.now = 1;
4659 : }
4660 :
4661 : #if !UTIME_HAVE_NOFOLLOW_SYMLINKS
4662 : if (follow_symlinks_specified("utime", follow_symlinks))
4663 : goto exit;
4664 : #endif
4665 :
4666 0 : if (path_and_dir_fd_invalid("utime", &path, dir_fd) ||
4667 0 : dir_fd_and_fd_invalid("utime", dir_fd, path.fd) ||
4668 0 : fd_and_follow_symlinks_invalid("utime", path.fd, follow_symlinks))
4669 : goto exit;
4670 :
4671 : #if !defined(HAVE_UTIMENSAT)
4672 : if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
4673 : PyErr_SetString(PyExc_ValueError,
4674 : "utime: cannot use dir_fd and follow_symlinks "
4675 : "together on this platform");
4676 : goto exit;
4677 : }
4678 : #endif
4679 :
4680 : #ifdef MS_WINDOWS
4681 : Py_BEGIN_ALLOW_THREADS
4682 : if (path.wide)
4683 : hFile = CreateFileW(path.wide, FILE_WRITE_ATTRIBUTES, 0,
4684 : NULL, OPEN_EXISTING,
4685 : FILE_FLAG_BACKUP_SEMANTICS, NULL);
4686 : else
4687 : hFile = CreateFileA(path.narrow, FILE_WRITE_ATTRIBUTES, 0,
4688 : NULL, OPEN_EXISTING,
4689 : FILE_FLAG_BACKUP_SEMANTICS, NULL);
4690 : Py_END_ALLOW_THREADS
4691 : if (hFile == INVALID_HANDLE_VALUE) {
4692 : win32_error_object("utime", path.object);
4693 : goto exit;
4694 : }
4695 :
4696 : if (utime.now) {
4697 : SYSTEMTIME now;
4698 : GetSystemTime(&now);
4699 : if (!SystemTimeToFileTime(&now, &mtime) ||
4700 : !SystemTimeToFileTime(&now, &atime)) {
4701 : win32_error("utime", NULL);
4702 : goto exit;
4703 : }
4704 : }
4705 : else {
4706 : time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
4707 : time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
4708 : }
4709 : if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
4710 : /* Avoid putting the file name into the error here,
4711 : as that may confuse the user into believing that
4712 : something is wrong with the file, when it also
4713 : could be the time stamp that gives a problem. */
4714 : win32_error("utime", NULL);
4715 : goto exit;
4716 : }
4717 : #else /* MS_WINDOWS */
4718 0 : Py_BEGIN_ALLOW_THREADS
4719 :
4720 : #if UTIME_HAVE_NOFOLLOW_SYMLINKS
4721 0 : if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
4722 0 : result = utime_nofollow_symlinks(&utime, path.narrow);
4723 : else
4724 : #endif
4725 :
4726 : #if UTIME_HAVE_DIR_FD
4727 0 : if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks))
4728 0 : result = utime_dir_fd(&utime, dir_fd, path.narrow, follow_symlinks);
4729 : else
4730 : #endif
4731 :
4732 : #if UTIME_HAVE_FD
4733 0 : if (path.fd != -1)
4734 0 : result = utime_fd(&utime, path.fd);
4735 : else
4736 : #endif
4737 :
4738 0 : result = utime_default(&utime, path.narrow);
4739 :
4740 0 : Py_END_ALLOW_THREADS
4741 :
4742 0 : if (result < 0) {
4743 : /* see previous comment about not putting filename in error here */
4744 0 : return_value = posix_error();
4745 0 : goto exit;
4746 : }
4747 :
4748 : #endif /* MS_WINDOWS */
4749 :
4750 0 : Py_INCREF(Py_None);
4751 0 : return_value = Py_None;
4752 :
4753 : exit:
4754 0 : path_cleanup(&path);
4755 : #ifdef MS_WINDOWS
4756 : if (hFile != INVALID_HANDLE_VALUE)
4757 : CloseHandle(hFile);
4758 : #endif
4759 0 : return return_value;
4760 : }
4761 :
4762 : /* Process operations */
4763 :
4764 : PyDoc_STRVAR(posix__exit__doc__,
4765 : "_exit(status)\n\n\
4766 : Exit to the system with specified status, without normal exit processing.");
4767 :
4768 : static PyObject *
4769 0 : posix__exit(PyObject *self, PyObject *args)
4770 : {
4771 : int sts;
4772 0 : if (!PyArg_ParseTuple(args, "i:_exit", &sts))
4773 0 : return NULL;
4774 0 : _exit(sts);
4775 : return NULL; /* Make gcc -Wall happy */
4776 : }
4777 :
4778 : #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
4779 : static void
4780 0 : free_string_array(char **array, Py_ssize_t count)
4781 : {
4782 : Py_ssize_t i;
4783 0 : for (i = 0; i < count; i++)
4784 0 : PyMem_Free(array[i]);
4785 0 : PyMem_DEL(array);
4786 0 : }
4787 :
4788 : static
4789 0 : int fsconvert_strdup(PyObject *o, char**out)
4790 : {
4791 : PyObject *bytes;
4792 : Py_ssize_t size;
4793 0 : if (!PyUnicode_FSConverter(o, &bytes))
4794 0 : return 0;
4795 0 : size = PyBytes_GET_SIZE(bytes);
4796 0 : *out = PyMem_Malloc(size+1);
4797 0 : if (!*out)
4798 0 : return 0;
4799 0 : memcpy(*out, PyBytes_AsString(bytes), size+1);
4800 0 : Py_DECREF(bytes);
4801 0 : return 1;
4802 : }
4803 : #endif
4804 :
4805 : #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE)
4806 : static char**
4807 0 : parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
4808 : {
4809 : char **envlist;
4810 : Py_ssize_t i, pos, envc;
4811 0 : PyObject *keys=NULL, *vals=NULL;
4812 : PyObject *key, *val, *key2, *val2;
4813 : char *p, *k, *v;
4814 : size_t len;
4815 :
4816 0 : i = PyMapping_Size(env);
4817 0 : if (i < 0)
4818 0 : return NULL;
4819 0 : envlist = PyMem_NEW(char *, i + 1);
4820 0 : if (envlist == NULL) {
4821 0 : PyErr_NoMemory();
4822 0 : return NULL;
4823 : }
4824 0 : envc = 0;
4825 0 : keys = PyMapping_Keys(env);
4826 0 : vals = PyMapping_Values(env);
4827 0 : if (!keys || !vals)
4828 : goto error;
4829 0 : if (!PyList_Check(keys) || !PyList_Check(vals)) {
4830 0 : PyErr_Format(PyExc_TypeError,
4831 : "env.keys() or env.values() is not a list");
4832 0 : goto error;
4833 : }
4834 :
4835 0 : for (pos = 0; pos < i; pos++) {
4836 0 : key = PyList_GetItem(keys, pos);
4837 0 : val = PyList_GetItem(vals, pos);
4838 0 : if (!key || !val)
4839 : goto error;
4840 :
4841 0 : if (PyUnicode_FSConverter(key, &key2) == 0)
4842 0 : goto error;
4843 0 : if (PyUnicode_FSConverter(val, &val2) == 0) {
4844 0 : Py_DECREF(key2);
4845 0 : goto error;
4846 : }
4847 :
4848 : #if defined(PYOS_OS2)
4849 : /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
4850 : if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
4851 : #endif
4852 0 : k = PyBytes_AsString(key2);
4853 0 : v = PyBytes_AsString(val2);
4854 0 : len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2;
4855 :
4856 0 : p = PyMem_NEW(char, len);
4857 0 : if (p == NULL) {
4858 0 : PyErr_NoMemory();
4859 0 : Py_DECREF(key2);
4860 0 : Py_DECREF(val2);
4861 0 : goto error;
4862 : }
4863 0 : PyOS_snprintf(p, len, "%s=%s", k, v);
4864 0 : envlist[envc++] = p;
4865 0 : Py_DECREF(key2);
4866 0 : Py_DECREF(val2);
4867 : #if defined(PYOS_OS2)
4868 : }
4869 : #endif
4870 : }
4871 0 : Py_DECREF(vals);
4872 0 : Py_DECREF(keys);
4873 :
4874 0 : envlist[envc] = 0;
4875 0 : *envc_ptr = envc;
4876 0 : return envlist;
4877 :
4878 : error:
4879 0 : Py_XDECREF(keys);
4880 0 : Py_XDECREF(vals);
4881 0 : while (--envc >= 0)
4882 0 : PyMem_DEL(envlist[envc]);
4883 0 : PyMem_DEL(envlist);
4884 0 : return NULL;
4885 : }
4886 :
4887 : static char**
4888 0 : parse_arglist(PyObject* argv, Py_ssize_t *argc)
4889 : {
4890 : int i;
4891 0 : char **argvlist = PyMem_NEW(char *, *argc+1);
4892 0 : if (argvlist == NULL) {
4893 0 : PyErr_NoMemory();
4894 0 : return NULL;
4895 : }
4896 0 : for (i = 0; i < *argc; i++) {
4897 0 : PyObject* item = PySequence_ITEM(argv, i);
4898 0 : if (item == NULL)
4899 0 : goto fail;
4900 0 : if (!fsconvert_strdup(item, &argvlist[i])) {
4901 0 : Py_DECREF(item);
4902 0 : goto fail;
4903 : }
4904 0 : Py_DECREF(item);
4905 : }
4906 0 : argvlist[*argc] = NULL;
4907 0 : return argvlist;
4908 : fail:
4909 0 : *argc = i;
4910 0 : free_string_array(argvlist, *argc);
4911 0 : return NULL;
4912 : }
4913 : #endif
4914 :
4915 : #ifdef HAVE_EXECV
4916 : PyDoc_STRVAR(posix_execv__doc__,
4917 : "execv(path, args)\n\n\
4918 : Execute an executable path with arguments, replacing current process.\n\
4919 : \n\
4920 : path: path of executable file\n\
4921 : args: tuple or list of strings");
4922 :
4923 : static PyObject *
4924 0 : posix_execv(PyObject *self, PyObject *args)
4925 : {
4926 : PyObject *opath;
4927 : char *path;
4928 : PyObject *argv;
4929 : char **argvlist;
4930 : Py_ssize_t argc;
4931 :
4932 : /* execv has two arguments: (path, argv), where
4933 : argv is a list or tuple of strings. */
4934 :
4935 0 : if (!PyArg_ParseTuple(args, "O&O:execv",
4936 : PyUnicode_FSConverter,
4937 : &opath, &argv))
4938 0 : return NULL;
4939 0 : path = PyBytes_AsString(opath);
4940 0 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
4941 0 : PyErr_SetString(PyExc_TypeError,
4942 : "execv() arg 2 must be a tuple or list");
4943 0 : Py_DECREF(opath);
4944 0 : return NULL;
4945 : }
4946 0 : argc = PySequence_Size(argv);
4947 0 : if (argc < 1) {
4948 0 : PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
4949 0 : Py_DECREF(opath);
4950 0 : return NULL;
4951 : }
4952 :
4953 0 : argvlist = parse_arglist(argv, &argc);
4954 0 : if (argvlist == NULL) {
4955 0 : Py_DECREF(opath);
4956 0 : return NULL;
4957 : }
4958 :
4959 0 : execv(path, argvlist);
4960 :
4961 : /* If we get here it's definitely an error */
4962 :
4963 0 : free_string_array(argvlist, argc);
4964 0 : Py_DECREF(opath);
4965 0 : return posix_error();
4966 : }
4967 :
4968 : PyDoc_STRVAR(posix_execve__doc__,
4969 : "execve(path, args, env)\n\n\
4970 : Execute a path with arguments and environment, replacing current process.\n\
4971 : \n\
4972 : path: path of executable file\n\
4973 : args: tuple or list of arguments\n\
4974 : env: dictionary of strings mapping to strings\n\
4975 : \n\
4976 : On some platforms, you may specify an open file descriptor for path;\n\
4977 : execve will execute the program the file descriptor is open to.\n\
4978 : If this functionality is unavailable, using it raises NotImplementedError.");
4979 :
4980 : static PyObject *
4981 0 : posix_execve(PyObject *self, PyObject *args, PyObject *kwargs)
4982 : {
4983 : path_t path;
4984 : PyObject *argv, *env;
4985 0 : char **argvlist = NULL;
4986 : char **envlist;
4987 : Py_ssize_t argc, envc;
4988 : static char *keywords[] = {"path", "argv", "environment", NULL};
4989 :
4990 : /* execve has three arguments: (path, argv, env), where
4991 : argv is a list or tuple of strings and env is a dictionary
4992 : like posix.environ. */
4993 :
4994 0 : memset(&path, 0, sizeof(path));
4995 : #ifdef HAVE_FEXECVE
4996 0 : path.allow_fd = 1;
4997 : #endif
4998 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&OO:execve", keywords,
4999 : path_converter, &path,
5000 : &argv, &env
5001 : ))
5002 0 : return NULL;
5003 :
5004 0 : if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5005 0 : PyErr_SetString(PyExc_TypeError,
5006 : "execve: argv must be a tuple or list");
5007 0 : goto fail;
5008 : }
5009 0 : argc = PySequence_Size(argv);
5010 0 : if (!PyMapping_Check(env)) {
5011 0 : PyErr_SetString(PyExc_TypeError,
5012 : "execve: environment must be a mapping object");
5013 0 : goto fail;
5014 : }
5015 :
5016 0 : argvlist = parse_arglist(argv, &argc);
5017 0 : if (argvlist == NULL) {
5018 0 : goto fail;
5019 : }
5020 :
5021 0 : envlist = parse_envlist(env, &envc);
5022 0 : if (envlist == NULL)
5023 0 : goto fail;
5024 :
5025 : #ifdef HAVE_FEXECVE
5026 0 : if (path.fd > -1)
5027 0 : fexecve(path.fd, argvlist, envlist);
5028 : else
5029 : #endif
5030 0 : execve(path.narrow, argvlist, envlist);
5031 :
5032 : /* If we get here it's definitely an error */
5033 :
5034 0 : path_posix_error("execve", &path);
5035 :
5036 0 : while (--envc >= 0)
5037 0 : PyMem_DEL(envlist[envc]);
5038 0 : PyMem_DEL(envlist);
5039 : fail:
5040 0 : if (argvlist)
5041 0 : free_string_array(argvlist, argc);
5042 0 : path_cleanup(&path);
5043 0 : return NULL;
5044 : }
5045 : #endif /* HAVE_EXECV */
5046 :
5047 :
5048 : #ifdef HAVE_SPAWNV
5049 : PyDoc_STRVAR(posix_spawnv__doc__,
5050 : "spawnv(mode, path, args)\n\n\
5051 : Execute the program 'path' in a new process.\n\
5052 : \n\
5053 : mode: mode of process creation\n\
5054 : path: path of executable file\n\
5055 : args: tuple or list of strings");
5056 :
5057 : static PyObject *
5058 : posix_spawnv(PyObject *self, PyObject *args)
5059 : {
5060 : PyObject *opath;
5061 : char *path;
5062 : PyObject *argv;
5063 : char **argvlist;
5064 : int mode, i;
5065 : Py_ssize_t argc;
5066 : Py_intptr_t spawnval;
5067 : PyObject *(*getitem)(PyObject *, Py_ssize_t);
5068 :
5069 : /* spawnv has three arguments: (mode, path, argv), where
5070 : argv is a list or tuple of strings. */
5071 :
5072 : if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode,
5073 : PyUnicode_FSConverter,
5074 : &opath, &argv))
5075 : return NULL;
5076 : path = PyBytes_AsString(opath);
5077 : if (PyList_Check(argv)) {
5078 : argc = PyList_Size(argv);
5079 : getitem = PyList_GetItem;
5080 : }
5081 : else if (PyTuple_Check(argv)) {
5082 : argc = PyTuple_Size(argv);
5083 : getitem = PyTuple_GetItem;
5084 : }
5085 : else {
5086 : PyErr_SetString(PyExc_TypeError,
5087 : "spawnv() arg 2 must be a tuple or list");
5088 : Py_DECREF(opath);
5089 : return NULL;
5090 : }
5091 :
5092 : argvlist = PyMem_NEW(char *, argc+1);
5093 : if (argvlist == NULL) {
5094 : Py_DECREF(opath);
5095 : return PyErr_NoMemory();
5096 : }
5097 : for (i = 0; i < argc; i++) {
5098 : if (!fsconvert_strdup((*getitem)(argv, i),
5099 : &argvlist[i])) {
5100 : free_string_array(argvlist, i);
5101 : PyErr_SetString(
5102 : PyExc_TypeError,
5103 : "spawnv() arg 2 must contain only strings");
5104 : Py_DECREF(opath);
5105 : return NULL;
5106 : }
5107 : }
5108 : argvlist[argc] = NULL;
5109 :
5110 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
5111 : Py_BEGIN_ALLOW_THREADS
5112 : spawnval = spawnv(mode, path, argvlist);
5113 : Py_END_ALLOW_THREADS
5114 : #else
5115 : if (mode == _OLD_P_OVERLAY)
5116 : mode = _P_OVERLAY;
5117 :
5118 : Py_BEGIN_ALLOW_THREADS
5119 : spawnval = _spawnv(mode, path, argvlist);
5120 : Py_END_ALLOW_THREADS
5121 : #endif
5122 :
5123 : free_string_array(argvlist, argc);
5124 : Py_DECREF(opath);
5125 :
5126 : if (spawnval == -1)
5127 : return posix_error();
5128 : else
5129 : #if SIZEOF_LONG == SIZEOF_VOID_P
5130 : return Py_BuildValue("l", (long) spawnval);
5131 : #else
5132 : return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
5133 : #endif
5134 : }
5135 :
5136 :
5137 : PyDoc_STRVAR(posix_spawnve__doc__,
5138 : "spawnve(mode, path, args, env)\n\n\
5139 : Execute the program 'path' in a new process.\n\
5140 : \n\
5141 : mode: mode of process creation\n\
5142 : path: path of executable file\n\
5143 : args: tuple or list of arguments\n\
5144 : env: dictionary of strings mapping to strings");
5145 :
5146 : static PyObject *
5147 : posix_spawnve(PyObject *self, PyObject *args)
5148 : {
5149 : PyObject *opath;
5150 : char *path;
5151 : PyObject *argv, *env;
5152 : char **argvlist;
5153 : char **envlist;
5154 : PyObject *res = NULL;
5155 : int mode;
5156 : Py_ssize_t argc, i, envc;
5157 : Py_intptr_t spawnval;
5158 : PyObject *(*getitem)(PyObject *, Py_ssize_t);
5159 : Py_ssize_t lastarg = 0;
5160 :
5161 : /* spawnve has four arguments: (mode, path, argv, env), where
5162 : argv is a list or tuple of strings and env is a dictionary
5163 : like posix.environ. */
5164 :
5165 : if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode,
5166 : PyUnicode_FSConverter,
5167 : &opath, &argv, &env))
5168 : return NULL;
5169 : path = PyBytes_AsString(opath);
5170 : if (PyList_Check(argv)) {
5171 : argc = PyList_Size(argv);
5172 : getitem = PyList_GetItem;
5173 : }
5174 : else if (PyTuple_Check(argv)) {
5175 : argc = PyTuple_Size(argv);
5176 : getitem = PyTuple_GetItem;
5177 : }
5178 : else {
5179 : PyErr_SetString(PyExc_TypeError,
5180 : "spawnve() arg 2 must be a tuple or list");
5181 : goto fail_0;
5182 : }
5183 : if (!PyMapping_Check(env)) {
5184 : PyErr_SetString(PyExc_TypeError,
5185 : "spawnve() arg 3 must be a mapping object");
5186 : goto fail_0;
5187 : }
5188 :
5189 : argvlist = PyMem_NEW(char *, argc+1);
5190 : if (argvlist == NULL) {
5191 : PyErr_NoMemory();
5192 : goto fail_0;
5193 : }
5194 : for (i = 0; i < argc; i++) {
5195 : if (!fsconvert_strdup((*getitem)(argv, i),
5196 : &argvlist[i]))
5197 : {
5198 : lastarg = i;
5199 : goto fail_1;
5200 : }
5201 : }
5202 : lastarg = argc;
5203 : argvlist[argc] = NULL;
5204 :
5205 : envlist = parse_envlist(env, &envc);
5206 : if (envlist == NULL)
5207 : goto fail_1;
5208 :
5209 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
5210 : Py_BEGIN_ALLOW_THREADS
5211 : spawnval = spawnve(mode, path, argvlist, envlist);
5212 : Py_END_ALLOW_THREADS
5213 : #else
5214 : if (mode == _OLD_P_OVERLAY)
5215 : mode = _P_OVERLAY;
5216 :
5217 : Py_BEGIN_ALLOW_THREADS
5218 : spawnval = _spawnve(mode, path, argvlist, envlist);
5219 : Py_END_ALLOW_THREADS
5220 : #endif
5221 :
5222 : if (spawnval == -1)
5223 : (void) posix_error();
5224 : else
5225 : #if SIZEOF_LONG == SIZEOF_VOID_P
5226 : res = Py_BuildValue("l", (long) spawnval);
5227 : #else
5228 : res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
5229 : #endif
5230 :
5231 : while (--envc >= 0)
5232 : PyMem_DEL(envlist[envc]);
5233 : PyMem_DEL(envlist);
5234 : fail_1:
5235 : free_string_array(argvlist, lastarg);
5236 : fail_0:
5237 : Py_DECREF(opath);
5238 : return res;
5239 : }
5240 :
5241 : /* OS/2 supports spawnvp & spawnvpe natively */
5242 : #if defined(PYOS_OS2)
5243 : PyDoc_STRVAR(posix_spawnvp__doc__,
5244 : "spawnvp(mode, file, args)\n\n\
5245 : Execute the program 'file' in a new process, using the environment\n\
5246 : search path to find the file.\n\
5247 : \n\
5248 : mode: mode of process creation\n\
5249 : file: executable file name\n\
5250 : args: tuple or list of strings");
5251 :
5252 : static PyObject *
5253 : posix_spawnvp(PyObject *self, PyObject *args)
5254 : {
5255 : PyObject *opath;
5256 : char *path;
5257 : PyObject *argv;
5258 : char **argvlist;
5259 : int mode, i, argc;
5260 : Py_intptr_t spawnval;
5261 : PyObject *(*getitem)(PyObject *, Py_ssize_t);
5262 :
5263 : /* spawnvp has three arguments: (mode, path, argv), where
5264 : argv is a list or tuple of strings. */
5265 :
5266 : if (!PyArg_ParseTuple(args, "iO&O:spawnvp", &mode,
5267 : PyUnicode_FSConverter,
5268 : &opath, &argv))
5269 : return NULL;
5270 : path = PyBytes_AsString(opath);
5271 : if (PyList_Check(argv)) {
5272 : argc = PyList_Size(argv);
5273 : getitem = PyList_GetItem;
5274 : }
5275 : else if (PyTuple_Check(argv)) {
5276 : argc = PyTuple_Size(argv);
5277 : getitem = PyTuple_GetItem;
5278 : }
5279 : else {
5280 : PyErr_SetString(PyExc_TypeError,
5281 : "spawnvp() arg 2 must be a tuple or list");
5282 : Py_DECREF(opath);
5283 : return NULL;
5284 : }
5285 :
5286 : argvlist = PyMem_NEW(char *, argc+1);
5287 : if (argvlist == NULL) {
5288 : Py_DECREF(opath);
5289 : return PyErr_NoMemory();
5290 : }
5291 : for (i = 0; i < argc; i++) {
5292 : if (!fsconvert_strdup((*getitem)(argv, i),
5293 : &argvlist[i])) {
5294 : free_string_array(argvlist, i);
5295 : PyErr_SetString(
5296 : PyExc_TypeError,
5297 : "spawnvp() arg 2 must contain only strings");
5298 : Py_DECREF(opath);
5299 : return NULL;
5300 : }
5301 : }
5302 : argvlist[argc] = NULL;
5303 :
5304 : Py_BEGIN_ALLOW_THREADS
5305 : #if defined(PYCC_GCC)
5306 : spawnval = spawnvp(mode, path, argvlist);
5307 : #else
5308 : spawnval = _spawnvp(mode, path, argvlist);
5309 : #endif
5310 : Py_END_ALLOW_THREADS
5311 :
5312 : free_string_array(argvlist, argc);
5313 : Py_DECREF(opath);
5314 :
5315 : if (spawnval == -1)
5316 : return posix_error();
5317 : else
5318 : return Py_BuildValue("l", (long) spawnval);
5319 : }
5320 :
5321 :
5322 : PyDoc_STRVAR(posix_spawnvpe__doc__,
5323 : "spawnvpe(mode, file, args, env)\n\n\
5324 : Execute the program 'file' in a new process, using the environment\n\
5325 : search path to find the file.\n\
5326 : \n\
5327 : mode: mode of process creation\n\
5328 : file: executable file name\n\
5329 : args: tuple or list of arguments\n\
5330 : env: dictionary of strings mapping to strings");
5331 :
5332 : static PyObject *
5333 : posix_spawnvpe(PyObject *self, PyObject *args)
5334 : {
5335 : PyObject *opath;
5336 : char *path;
5337 : PyObject *argv, *env;
5338 : char **argvlist;
5339 : char **envlist;
5340 : PyObject *res=NULL;
5341 : int mode;
5342 : Py_ssize_t argc, i, envc;
5343 : Py_intptr_t spawnval;
5344 : PyObject *(*getitem)(PyObject *, Py_ssize_t);
5345 : int lastarg = 0;
5346 :
5347 : /* spawnvpe has four arguments: (mode, path, argv, env), where
5348 : argv is a list or tuple of strings and env is a dictionary
5349 : like posix.environ. */
5350 :
5351 : if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
5352 : PyUnicode_FSConverter,
5353 : &opath, &argv, &env))
5354 : return NULL;
5355 : path = PyBytes_AsString(opath);
5356 : if (PyList_Check(argv)) {
5357 : argc = PyList_Size(argv);
5358 : getitem = PyList_GetItem;
5359 : }
5360 : else if (PyTuple_Check(argv)) {
5361 : argc = PyTuple_Size(argv);
5362 : getitem = PyTuple_GetItem;
5363 : }
5364 : else {
5365 : PyErr_SetString(PyExc_TypeError,
5366 : "spawnvpe() arg 2 must be a tuple or list");
5367 : goto fail_0;
5368 : }
5369 : if (!PyMapping_Check(env)) {
5370 : PyErr_SetString(PyExc_TypeError,
5371 : "spawnvpe() arg 3 must be a mapping object");
5372 : goto fail_0;
5373 : }
5374 :
5375 : argvlist = PyMem_NEW(char *, argc+1);
5376 : if (argvlist == NULL) {
5377 : PyErr_NoMemory();
5378 : goto fail_0;
5379 : }
5380 : for (i = 0; i < argc; i++) {
5381 : if (!fsconvert_strdup((*getitem)(argv, i),
5382 : &argvlist[i]))
5383 : {
5384 : lastarg = i;
5385 : goto fail_1;
5386 : }
5387 : }
5388 : lastarg = argc;
5389 : argvlist[argc] = NULL;
5390 :
5391 : envlist = parse_envlist(env, &envc);
5392 : if (envlist == NULL)
5393 : goto fail_1;
5394 :
5395 : Py_BEGIN_ALLOW_THREADS
5396 : #if defined(PYCC_GCC)
5397 : spawnval = spawnvpe(mode, path, argvlist, envlist);
5398 : #else
5399 : spawnval = _spawnvpe(mode, path, argvlist, envlist);
5400 : #endif
5401 : Py_END_ALLOW_THREADS
5402 :
5403 : if (spawnval == -1)
5404 : (void) posix_error();
5405 : else
5406 : res = Py_BuildValue("l", (long) spawnval);
5407 :
5408 : while (--envc >= 0)
5409 : PyMem_DEL(envlist[envc]);
5410 : PyMem_DEL(envlist);
5411 : fail_1:
5412 : free_string_array(argvlist, lastarg);
5413 : fail_0:
5414 : Py_DECREF(opath);
5415 : return res;
5416 : }
5417 : #endif /* PYOS_OS2 */
5418 : #endif /* HAVE_SPAWNV */
5419 :
5420 :
5421 : #ifdef HAVE_FORK1
5422 : PyDoc_STRVAR(posix_fork1__doc__,
5423 : "fork1() -> pid\n\n\
5424 : Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
5425 : \n\
5426 : Return 0 to child process and PID of child to parent process.");
5427 :
5428 : static PyObject *
5429 : posix_fork1(PyObject *self, PyObject *noargs)
5430 : {
5431 : pid_t pid;
5432 : int result = 0;
5433 : _PyImport_AcquireLock();
5434 : pid = fork1();
5435 : if (pid == 0) {
5436 : /* child: this clobbers and resets the import lock. */
5437 : PyOS_AfterFork();
5438 : } else {
5439 : /* parent: release the import lock. */
5440 : result = _PyImport_ReleaseLock();
5441 : }
5442 : if (pid == -1)
5443 : return posix_error();
5444 : if (result < 0) {
5445 : /* Don't clobber the OSError if the fork failed. */
5446 : PyErr_SetString(PyExc_RuntimeError,
5447 : "not holding the import lock");
5448 : return NULL;
5449 : }
5450 : return PyLong_FromPid(pid);
5451 : }
5452 : #endif
5453 :
5454 :
5455 : #ifdef HAVE_FORK
5456 : PyDoc_STRVAR(posix_fork__doc__,
5457 : "fork() -> pid\n\n\
5458 : Fork a child process.\n\
5459 : Return 0 to child process and PID of child to parent process.");
5460 :
5461 : static PyObject *
5462 0 : posix_fork(PyObject *self, PyObject *noargs)
5463 : {
5464 : pid_t pid;
5465 0 : int result = 0;
5466 0 : _PyImport_AcquireLock();
5467 0 : pid = fork();
5468 0 : if (pid == 0) {
5469 : /* child: this clobbers and resets the import lock. */
5470 0 : PyOS_AfterFork();
5471 : } else {
5472 : /* parent: release the import lock. */
5473 0 : result = _PyImport_ReleaseLock();
5474 : }
5475 0 : if (pid == -1)
5476 0 : return posix_error();
5477 0 : if (result < 0) {
5478 : /* Don't clobber the OSError if the fork failed. */
5479 0 : PyErr_SetString(PyExc_RuntimeError,
5480 : "not holding the import lock");
5481 0 : return NULL;
5482 : }
5483 0 : return PyLong_FromPid(pid);
5484 : }
5485 : #endif
5486 :
5487 : #ifdef HAVE_SCHED_H
5488 :
5489 : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
5490 :
5491 : PyDoc_STRVAR(posix_sched_get_priority_max__doc__,
5492 : "sched_get_priority_max(policy)\n\n\
5493 : Get the maximum scheduling priority for *policy*.");
5494 :
5495 : static PyObject *
5496 0 : posix_sched_get_priority_max(PyObject *self, PyObject *args)
5497 : {
5498 : int policy, max;
5499 :
5500 0 : if (!PyArg_ParseTuple(args, "i:sched_get_priority_max", &policy))
5501 0 : return NULL;
5502 0 : max = sched_get_priority_max(policy);
5503 0 : if (max < 0)
5504 0 : return posix_error();
5505 0 : return PyLong_FromLong(max);
5506 : }
5507 :
5508 : PyDoc_STRVAR(posix_sched_get_priority_min__doc__,
5509 : "sched_get_priority_min(policy)\n\n\
5510 : Get the minimum scheduling priority for *policy*.");
5511 :
5512 : static PyObject *
5513 0 : posix_sched_get_priority_min(PyObject *self, PyObject *args)
5514 : {
5515 : int policy, min;
5516 :
5517 0 : if (!PyArg_ParseTuple(args, "i:sched_get_priority_min", &policy))
5518 0 : return NULL;
5519 0 : min = sched_get_priority_min(policy);
5520 0 : if (min < 0)
5521 0 : return posix_error();
5522 0 : return PyLong_FromLong(min);
5523 : }
5524 :
5525 : #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
5526 :
5527 : #ifdef HAVE_SCHED_SETSCHEDULER
5528 :
5529 : PyDoc_STRVAR(posix_sched_getscheduler__doc__,
5530 : "sched_getscheduler(pid)\n\n\
5531 : Get the scheduling policy for the process with a PID of *pid*.\n\
5532 : Passing a PID of 0 returns the scheduling policy for the calling process.");
5533 :
5534 : static PyObject *
5535 0 : posix_sched_getscheduler(PyObject *self, PyObject *args)
5536 : {
5537 : pid_t pid;
5538 : int policy;
5539 :
5540 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getscheduler", &pid))
5541 0 : return NULL;
5542 0 : policy = sched_getscheduler(pid);
5543 0 : if (policy < 0)
5544 0 : return posix_error();
5545 0 : return PyLong_FromLong(policy);
5546 : }
5547 :
5548 : #endif
5549 :
5550 : #if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM)
5551 :
5552 : static PyObject *
5553 0 : sched_param_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
5554 : {
5555 : PyObject *res, *priority;
5556 : static char *kwlist[] = {"sched_priority", NULL};
5557 :
5558 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:sched_param", kwlist, &priority))
5559 0 : return NULL;
5560 0 : res = PyStructSequence_New(type);
5561 0 : if (!res)
5562 0 : return NULL;
5563 0 : Py_INCREF(priority);
5564 0 : PyStructSequence_SET_ITEM(res, 0, priority);
5565 0 : return res;
5566 : }
5567 :
5568 : PyDoc_STRVAR(sched_param__doc__,
5569 : "sched_param(sched_priority): A scheduling parameter.\n\n\
5570 : Current has only one field: sched_priority");
5571 :
5572 : static PyStructSequence_Field sched_param_fields[] = {
5573 : {"sched_priority", "the scheduling priority"},
5574 : {0}
5575 : };
5576 :
5577 : static PyStructSequence_Desc sched_param_desc = {
5578 : "sched_param", /* name */
5579 : sched_param__doc__, /* doc */
5580 : sched_param_fields,
5581 : 1
5582 : };
5583 :
5584 : static int
5585 0 : convert_sched_param(PyObject *param, struct sched_param *res)
5586 : {
5587 : long priority;
5588 :
5589 0 : if (Py_TYPE(param) != &SchedParamType) {
5590 0 : PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
5591 0 : return 0;
5592 : }
5593 0 : priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
5594 0 : if (priority == -1 && PyErr_Occurred())
5595 0 : return 0;
5596 : if (priority > INT_MAX || priority < INT_MIN) {
5597 : PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
5598 : return 0;
5599 : }
5600 0 : res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
5601 0 : return 1;
5602 : }
5603 :
5604 : #endif
5605 :
5606 : #ifdef HAVE_SCHED_SETSCHEDULER
5607 :
5608 : PyDoc_STRVAR(posix_sched_setscheduler__doc__,
5609 : "sched_setscheduler(pid, policy, param)\n\n\
5610 : Set the scheduling policy, *policy*, for *pid*.\n\
5611 : If *pid* is 0, the calling process is changed.\n\
5612 : *param* is an instance of sched_param.");
5613 :
5614 : static PyObject *
5615 0 : posix_sched_setscheduler(PyObject *self, PyObject *args)
5616 : {
5617 : pid_t pid;
5618 : int policy;
5619 : struct sched_param param;
5620 :
5621 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "iO&:sched_setscheduler",
5622 : &pid, &policy, &convert_sched_param, ¶m))
5623 0 : return NULL;
5624 :
5625 : /*
5626 : ** sched_setscheduler() returns 0 in Linux, but the previous
5627 : ** scheduling policy under Solaris/Illumos, and others.
5628 : ** On error, -1 is returned in all Operating Systems.
5629 : */
5630 0 : if (sched_setscheduler(pid, policy, ¶m) == -1)
5631 0 : return posix_error();
5632 0 : Py_RETURN_NONE;
5633 : }
5634 :
5635 : #endif
5636 :
5637 : #ifdef HAVE_SCHED_SETPARAM
5638 :
5639 : PyDoc_STRVAR(posix_sched_getparam__doc__,
5640 : "sched_getparam(pid) -> sched_param\n\n\
5641 : Returns scheduling parameters for the process with *pid* as an instance of the\n\
5642 : sched_param class. A PID of 0 means the calling process.");
5643 :
5644 : static PyObject *
5645 0 : posix_sched_getparam(PyObject *self, PyObject *args)
5646 : {
5647 : pid_t pid;
5648 : struct sched_param param;
5649 : PyObject *res, *priority;
5650 :
5651 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getparam", &pid))
5652 0 : return NULL;
5653 0 : if (sched_getparam(pid, ¶m))
5654 0 : return posix_error();
5655 0 : res = PyStructSequence_New(&SchedParamType);
5656 0 : if (!res)
5657 0 : return NULL;
5658 0 : priority = PyLong_FromLong(param.sched_priority);
5659 0 : if (!priority) {
5660 0 : Py_DECREF(res);
5661 0 : return NULL;
5662 : }
5663 0 : PyStructSequence_SET_ITEM(res, 0, priority);
5664 0 : return res;
5665 : }
5666 :
5667 : PyDoc_STRVAR(posix_sched_setparam__doc__,
5668 : "sched_setparam(pid, param)\n\n\
5669 : Set scheduling parameters for a process with PID *pid*.\n\
5670 : A PID of 0 means the calling process.");
5671 :
5672 : static PyObject *
5673 0 : posix_sched_setparam(PyObject *self, PyObject *args)
5674 : {
5675 : pid_t pid;
5676 : struct sched_param param;
5677 :
5678 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O&:sched_setparam",
5679 : &pid, &convert_sched_param, ¶m))
5680 0 : return NULL;
5681 0 : if (sched_setparam(pid, ¶m))
5682 0 : return posix_error();
5683 0 : Py_RETURN_NONE;
5684 : }
5685 :
5686 : #endif
5687 :
5688 : #ifdef HAVE_SCHED_RR_GET_INTERVAL
5689 :
5690 : PyDoc_STRVAR(posix_sched_rr_get_interval__doc__,
5691 : "sched_rr_get_interval(pid) -> float\n\n\
5692 : Return the round-robin quantum for the process with PID *pid* in seconds.");
5693 :
5694 : static PyObject *
5695 0 : posix_sched_rr_get_interval(PyObject *self, PyObject *args)
5696 : {
5697 : pid_t pid;
5698 : struct timespec interval;
5699 :
5700 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_rr_get_interval", &pid))
5701 0 : return NULL;
5702 0 : if (sched_rr_get_interval(pid, &interval))
5703 0 : return posix_error();
5704 0 : return PyFloat_FromDouble((double)interval.tv_sec + 1e-9*interval.tv_nsec);
5705 : }
5706 :
5707 : #endif
5708 :
5709 : PyDoc_STRVAR(posix_sched_yield__doc__,
5710 : "sched_yield()\n\n\
5711 : Voluntarily relinquish the CPU.");
5712 :
5713 : static PyObject *
5714 0 : posix_sched_yield(PyObject *self, PyObject *noargs)
5715 : {
5716 0 : if (sched_yield())
5717 0 : return posix_error();
5718 0 : Py_RETURN_NONE;
5719 : }
5720 :
5721 : #ifdef HAVE_SCHED_SETAFFINITY
5722 :
5723 : /* The minimum number of CPUs allocated in a cpu_set_t */
5724 : static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
5725 :
5726 : PyDoc_STRVAR(posix_sched_setaffinity__doc__,
5727 : "sched_setaffinity(pid, cpu_set)\n\n\
5728 : Set the affinity of the process with PID *pid* to *cpu_set*.");
5729 :
5730 : static PyObject *
5731 0 : posix_sched_setaffinity(PyObject *self, PyObject *args)
5732 : {
5733 : pid_t pid;
5734 : int ncpus;
5735 : size_t setsize;
5736 0 : cpu_set_t *mask = NULL;
5737 0 : PyObject *iterable, *iterator = NULL, *item;
5738 :
5739 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity",
5740 : &pid, &iterable))
5741 0 : return NULL;
5742 :
5743 0 : iterator = PyObject_GetIter(iterable);
5744 0 : if (iterator == NULL)
5745 0 : return NULL;
5746 :
5747 0 : ncpus = NCPUS_START;
5748 0 : setsize = CPU_ALLOC_SIZE(ncpus);
5749 0 : mask = CPU_ALLOC(ncpus);
5750 0 : if (mask == NULL) {
5751 0 : PyErr_NoMemory();
5752 0 : goto error;
5753 : }
5754 0 : CPU_ZERO_S(setsize, mask);
5755 :
5756 0 : while ((item = PyIter_Next(iterator))) {
5757 : long cpu;
5758 0 : if (!PyLong_Check(item)) {
5759 0 : PyErr_Format(PyExc_TypeError,
5760 : "expected an iterator of ints, "
5761 : "but iterator yielded %R",
5762 : Py_TYPE(item));
5763 0 : Py_DECREF(item);
5764 0 : goto error;
5765 : }
5766 0 : cpu = PyLong_AsLong(item);
5767 0 : Py_DECREF(item);
5768 0 : if (cpu < 0) {
5769 0 : if (!PyErr_Occurred())
5770 0 : PyErr_SetString(PyExc_ValueError, "negative CPU number");
5771 0 : goto error;
5772 : }
5773 0 : if (cpu > INT_MAX - 1) {
5774 0 : PyErr_SetString(PyExc_OverflowError, "CPU number too large");
5775 0 : goto error;
5776 : }
5777 0 : if (cpu >= ncpus) {
5778 : /* Grow CPU mask to fit the CPU number */
5779 0 : int newncpus = ncpus;
5780 : cpu_set_t *newmask;
5781 : size_t newsetsize;
5782 0 : while (newncpus <= cpu) {
5783 0 : if (newncpus > INT_MAX / 2)
5784 0 : newncpus = cpu + 1;
5785 : else
5786 0 : newncpus = newncpus * 2;
5787 : }
5788 0 : newmask = CPU_ALLOC(newncpus);
5789 0 : if (newmask == NULL) {
5790 0 : PyErr_NoMemory();
5791 0 : goto error;
5792 : }
5793 0 : newsetsize = CPU_ALLOC_SIZE(newncpus);
5794 0 : CPU_ZERO_S(newsetsize, newmask);
5795 0 : memcpy(newmask, mask, setsize);
5796 0 : CPU_FREE(mask);
5797 0 : setsize = newsetsize;
5798 0 : mask = newmask;
5799 0 : ncpus = newncpus;
5800 : }
5801 0 : CPU_SET_S(cpu, setsize, mask);
5802 : }
5803 0 : Py_CLEAR(iterator);
5804 :
5805 0 : if (sched_setaffinity(pid, setsize, mask)) {
5806 0 : posix_error();
5807 0 : goto error;
5808 : }
5809 0 : CPU_FREE(mask);
5810 0 : Py_RETURN_NONE;
5811 :
5812 : error:
5813 0 : if (mask)
5814 0 : CPU_FREE(mask);
5815 0 : Py_XDECREF(iterator);
5816 0 : return NULL;
5817 : }
5818 :
5819 : PyDoc_STRVAR(posix_sched_getaffinity__doc__,
5820 : "sched_getaffinity(pid, ncpus) -> cpu_set\n\n\
5821 : Return the affinity of the process with PID *pid*.\n\
5822 : The returned cpu_set will be of size *ncpus*.");
5823 :
5824 : static PyObject *
5825 0 : posix_sched_getaffinity(PyObject *self, PyObject *args)
5826 : {
5827 : pid_t pid;
5828 : int cpu, ncpus, count;
5829 : size_t setsize;
5830 0 : cpu_set_t *mask = NULL;
5831 0 : PyObject *res = NULL;
5832 :
5833 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity",
5834 : &pid))
5835 0 : return NULL;
5836 :
5837 0 : ncpus = NCPUS_START;
5838 : while (1) {
5839 0 : setsize = CPU_ALLOC_SIZE(ncpus);
5840 0 : mask = CPU_ALLOC(ncpus);
5841 0 : if (mask == NULL)
5842 0 : return PyErr_NoMemory();
5843 0 : if (sched_getaffinity(pid, setsize, mask) == 0)
5844 0 : break;
5845 0 : CPU_FREE(mask);
5846 0 : if (errno != EINVAL)
5847 0 : return posix_error();
5848 0 : if (ncpus > INT_MAX / 2) {
5849 0 : PyErr_SetString(PyExc_OverflowError, "could not allocate "
5850 : "a large enough CPU set");
5851 0 : return NULL;
5852 : }
5853 0 : ncpus = ncpus * 2;
5854 0 : }
5855 :
5856 0 : res = PySet_New(NULL);
5857 0 : if (res == NULL)
5858 0 : goto error;
5859 0 : for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
5860 0 : if (CPU_ISSET_S(cpu, setsize, mask)) {
5861 0 : PyObject *cpu_num = PyLong_FromLong(cpu);
5862 0 : --count;
5863 0 : if (cpu_num == NULL)
5864 0 : goto error;
5865 0 : if (PySet_Add(res, cpu_num)) {
5866 0 : Py_DECREF(cpu_num);
5867 0 : goto error;
5868 : }
5869 0 : Py_DECREF(cpu_num);
5870 : }
5871 : }
5872 0 : CPU_FREE(mask);
5873 0 : return res;
5874 :
5875 : error:
5876 0 : if (mask)
5877 0 : CPU_FREE(mask);
5878 0 : Py_XDECREF(res);
5879 0 : return NULL;
5880 : }
5881 :
5882 : #endif /* HAVE_SCHED_SETAFFINITY */
5883 :
5884 : #endif /* HAVE_SCHED_H */
5885 :
5886 : /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
5887 : /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
5888 : #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
5889 : #define DEV_PTY_FILE "/dev/ptc"
5890 : #define HAVE_DEV_PTMX
5891 : #else
5892 : #define DEV_PTY_FILE "/dev/ptmx"
5893 : #endif
5894 :
5895 : #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
5896 : #ifdef HAVE_PTY_H
5897 : #include <pty.h>
5898 : #else
5899 : #ifdef HAVE_LIBUTIL_H
5900 : #include <libutil.h>
5901 : #else
5902 : #ifdef HAVE_UTIL_H
5903 : #include <util.h>
5904 : #endif /* HAVE_UTIL_H */
5905 : #endif /* HAVE_LIBUTIL_H */
5906 : #endif /* HAVE_PTY_H */
5907 : #ifdef HAVE_STROPTS_H
5908 : #include <stropts.h>
5909 : #endif
5910 : #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
5911 :
5912 : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
5913 : PyDoc_STRVAR(posix_openpty__doc__,
5914 : "openpty() -> (master_fd, slave_fd)\n\n\
5915 : Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
5916 :
5917 : static PyObject *
5918 0 : posix_openpty(PyObject *self, PyObject *noargs)
5919 : {
5920 : int master_fd, slave_fd;
5921 : #ifndef HAVE_OPENPTY
5922 : char * slave_name;
5923 : #endif
5924 : #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
5925 : PyOS_sighandler_t sig_saved;
5926 : #ifdef sun
5927 : extern char *ptsname(int fildes);
5928 : #endif
5929 : #endif
5930 :
5931 : #ifdef HAVE_OPENPTY
5932 0 : if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
5933 0 : return posix_error();
5934 : #elif defined(HAVE__GETPTY)
5935 : slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
5936 : if (slave_name == NULL)
5937 : return posix_error();
5938 :
5939 : slave_fd = open(slave_name, O_RDWR);
5940 : if (slave_fd < 0)
5941 : return posix_error();
5942 : #else
5943 : master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
5944 : if (master_fd < 0)
5945 : return posix_error();
5946 : sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
5947 : /* change permission of slave */
5948 : if (grantpt(master_fd) < 0) {
5949 : PyOS_setsig(SIGCHLD, sig_saved);
5950 : return posix_error();
5951 : }
5952 : /* unlock slave */
5953 : if (unlockpt(master_fd) < 0) {
5954 : PyOS_setsig(SIGCHLD, sig_saved);
5955 : return posix_error();
5956 : }
5957 : PyOS_setsig(SIGCHLD, sig_saved);
5958 : slave_name = ptsname(master_fd); /* get name of slave */
5959 : if (slave_name == NULL)
5960 : return posix_error();
5961 : slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
5962 : if (slave_fd < 0)
5963 : return posix_error();
5964 : #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
5965 : ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
5966 : ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
5967 : #ifndef __hpux
5968 : ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
5969 : #endif /* __hpux */
5970 : #endif /* HAVE_CYGWIN */
5971 : #endif /* HAVE_OPENPTY */
5972 :
5973 0 : return Py_BuildValue("(ii)", master_fd, slave_fd);
5974 :
5975 : }
5976 : #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
5977 :
5978 : #ifdef HAVE_FORKPTY
5979 : PyDoc_STRVAR(posix_forkpty__doc__,
5980 : "forkpty() -> (pid, master_fd)\n\n\
5981 : Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
5982 : Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
5983 : To both, return fd of newly opened pseudo-terminal.\n");
5984 :
5985 : static PyObject *
5986 0 : posix_forkpty(PyObject *self, PyObject *noargs)
5987 : {
5988 0 : int master_fd = -1, result = 0;
5989 : pid_t pid;
5990 :
5991 0 : _PyImport_AcquireLock();
5992 0 : pid = forkpty(&master_fd, NULL, NULL, NULL);
5993 0 : if (pid == 0) {
5994 : /* child: this clobbers and resets the import lock. */
5995 0 : PyOS_AfterFork();
5996 : } else {
5997 : /* parent: release the import lock. */
5998 0 : result = _PyImport_ReleaseLock();
5999 : }
6000 0 : if (pid == -1)
6001 0 : return posix_error();
6002 0 : if (result < 0) {
6003 : /* Don't clobber the OSError if the fork failed. */
6004 0 : PyErr_SetString(PyExc_RuntimeError,
6005 : "not holding the import lock");
6006 0 : return NULL;
6007 : }
6008 0 : return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
6009 : }
6010 : #endif
6011 :
6012 :
6013 : #ifdef HAVE_GETEGID
6014 : PyDoc_STRVAR(posix_getegid__doc__,
6015 : "getegid() -> egid\n\n\
6016 : Return the current process's effective group id.");
6017 :
6018 : static PyObject *
6019 1 : posix_getegid(PyObject *self, PyObject *noargs)
6020 : {
6021 1 : return PyLong_FromLong((long)getegid());
6022 : }
6023 : #endif
6024 :
6025 :
6026 : #ifdef HAVE_GETEUID
6027 : PyDoc_STRVAR(posix_geteuid__doc__,
6028 : "geteuid() -> euid\n\n\
6029 : Return the current process's effective user id.");
6030 :
6031 : static PyObject *
6032 1 : posix_geteuid(PyObject *self, PyObject *noargs)
6033 : {
6034 1 : return PyLong_FromLong((long)geteuid());
6035 : }
6036 : #endif
6037 :
6038 :
6039 : #ifdef HAVE_GETGID
6040 : PyDoc_STRVAR(posix_getgid__doc__,
6041 : "getgid() -> gid\n\n\
6042 : Return the current process's group id.");
6043 :
6044 : static PyObject *
6045 1 : posix_getgid(PyObject *self, PyObject *noargs)
6046 : {
6047 1 : return PyLong_FromLong((long)getgid());
6048 : }
6049 : #endif
6050 :
6051 :
6052 : PyDoc_STRVAR(posix_getpid__doc__,
6053 : "getpid() -> pid\n\n\
6054 : Return the current process id");
6055 :
6056 : static PyObject *
6057 0 : posix_getpid(PyObject *self, PyObject *noargs)
6058 : {
6059 0 : return PyLong_FromPid(getpid());
6060 : }
6061 :
6062 : #ifdef HAVE_GETGROUPLIST
6063 : PyDoc_STRVAR(posix_getgrouplist__doc__,
6064 : "getgrouplist(user, group) -> list of groups to which a user belongs\n\n\
6065 : Returns a list of groups to which a user belongs.\n\n\
6066 : user: username to lookup\n\
6067 : group: base group id of the user");
6068 :
6069 : static PyObject *
6070 0 : posix_getgrouplist(PyObject *self, PyObject *args)
6071 : {
6072 : #ifdef NGROUPS_MAX
6073 : #define MAX_GROUPS NGROUPS_MAX
6074 : #else
6075 : /* defined to be 16 on Solaris7, so this should be a small number */
6076 : #define MAX_GROUPS 64
6077 : #endif
6078 :
6079 : const char *user;
6080 : int i, ngroups;
6081 : PyObject *list;
6082 : #ifdef __APPLE__
6083 : int *groups, basegid;
6084 : #else
6085 : gid_t *groups, basegid;
6086 : #endif
6087 0 : ngroups = MAX_GROUPS;
6088 :
6089 0 : if (!PyArg_ParseTuple(args, "si", &user, &basegid))
6090 0 : return NULL;
6091 :
6092 : #ifdef __APPLE__
6093 : groups = PyMem_Malloc(ngroups * sizeof(int));
6094 : #else
6095 0 : groups = PyMem_Malloc(ngroups * sizeof(gid_t));
6096 : #endif
6097 0 : if (groups == NULL)
6098 0 : return PyErr_NoMemory();
6099 :
6100 0 : if (getgrouplist(user, basegid, groups, &ngroups) == -1) {
6101 0 : PyMem_Del(groups);
6102 0 : return posix_error();
6103 : }
6104 :
6105 0 : list = PyList_New(ngroups);
6106 0 : if (list == NULL) {
6107 0 : PyMem_Del(groups);
6108 0 : return NULL;
6109 : }
6110 :
6111 0 : for (i = 0; i < ngroups; i++) {
6112 0 : PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
6113 0 : if (o == NULL) {
6114 0 : Py_DECREF(list);
6115 0 : PyMem_Del(groups);
6116 0 : return NULL;
6117 : }
6118 0 : PyList_SET_ITEM(list, i, o);
6119 : }
6120 :
6121 0 : PyMem_Del(groups);
6122 :
6123 0 : return list;
6124 : }
6125 : #endif
6126 :
6127 : #ifdef HAVE_GETGROUPS
6128 : PyDoc_STRVAR(posix_getgroups__doc__,
6129 : "getgroups() -> list of group IDs\n\n\
6130 : Return list of supplemental group IDs for the process.");
6131 :
6132 : static PyObject *
6133 0 : posix_getgroups(PyObject *self, PyObject *noargs)
6134 : {
6135 0 : PyObject *result = NULL;
6136 :
6137 : #ifdef NGROUPS_MAX
6138 : #define MAX_GROUPS NGROUPS_MAX
6139 : #else
6140 : /* defined to be 16 on Solaris7, so this should be a small number */
6141 : #define MAX_GROUPS 64
6142 : #endif
6143 : gid_t grouplist[MAX_GROUPS];
6144 :
6145 : /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
6146 : * This is a helper variable to store the intermediate result when
6147 : * that happens.
6148 : *
6149 : * To keep the code readable the OSX behaviour is unconditional,
6150 : * according to the POSIX spec this should be safe on all unix-y
6151 : * systems.
6152 : */
6153 0 : gid_t* alt_grouplist = grouplist;
6154 : int n;
6155 :
6156 0 : n = getgroups(MAX_GROUPS, grouplist);
6157 0 : if (n < 0) {
6158 0 : if (errno == EINVAL) {
6159 0 : n = getgroups(0, NULL);
6160 0 : if (n == -1) {
6161 0 : return posix_error();
6162 : }
6163 0 : if (n == 0) {
6164 : /* Avoid malloc(0) */
6165 0 : alt_grouplist = grouplist;
6166 : } else {
6167 0 : alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
6168 0 : if (alt_grouplist == NULL) {
6169 0 : errno = EINVAL;
6170 0 : return posix_error();
6171 : }
6172 0 : n = getgroups(n, alt_grouplist);
6173 0 : if (n == -1) {
6174 0 : PyMem_Free(alt_grouplist);
6175 0 : return posix_error();
6176 : }
6177 : }
6178 : } else {
6179 0 : return posix_error();
6180 : }
6181 : }
6182 0 : result = PyList_New(n);
6183 0 : if (result != NULL) {
6184 : int i;
6185 0 : for (i = 0; i < n; ++i) {
6186 0 : PyObject *o = PyLong_FromLong((long)alt_grouplist[i]);
6187 0 : if (o == NULL) {
6188 0 : Py_DECREF(result);
6189 0 : result = NULL;
6190 0 : break;
6191 : }
6192 0 : PyList_SET_ITEM(result, i, o);
6193 : }
6194 : }
6195 :
6196 0 : if (alt_grouplist != grouplist) {
6197 0 : PyMem_Free(alt_grouplist);
6198 : }
6199 :
6200 0 : return result;
6201 : }
6202 : #endif
6203 :
6204 : #ifdef HAVE_INITGROUPS
6205 : PyDoc_STRVAR(posix_initgroups__doc__,
6206 : "initgroups(username, gid) -> None\n\n\
6207 : Call the system initgroups() to initialize the group access list with all of\n\
6208 : the groups of which the specified username is a member, plus the specified\n\
6209 : group id.");
6210 :
6211 : static PyObject *
6212 0 : posix_initgroups(PyObject *self, PyObject *args)
6213 : {
6214 : PyObject *oname;
6215 : char *username;
6216 : int res;
6217 : long gid;
6218 :
6219 0 : if (!PyArg_ParseTuple(args, "O&l:initgroups",
6220 : PyUnicode_FSConverter, &oname, &gid))
6221 0 : return NULL;
6222 0 : username = PyBytes_AS_STRING(oname);
6223 :
6224 0 : res = initgroups(username, (gid_t) gid);
6225 0 : Py_DECREF(oname);
6226 0 : if (res == -1)
6227 0 : return PyErr_SetFromErrno(PyExc_OSError);
6228 :
6229 0 : Py_INCREF(Py_None);
6230 0 : return Py_None;
6231 : }
6232 : #endif
6233 :
6234 : #ifdef HAVE_GETPGID
6235 : PyDoc_STRVAR(posix_getpgid__doc__,
6236 : "getpgid(pid) -> pgid\n\n\
6237 : Call the system call getpgid().");
6238 :
6239 : static PyObject *
6240 0 : posix_getpgid(PyObject *self, PyObject *args)
6241 : {
6242 : pid_t pid, pgid;
6243 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getpgid", &pid))
6244 0 : return NULL;
6245 0 : pgid = getpgid(pid);
6246 0 : if (pgid < 0)
6247 0 : return posix_error();
6248 0 : return PyLong_FromPid(pgid);
6249 : }
6250 : #endif /* HAVE_GETPGID */
6251 :
6252 :
6253 : #ifdef HAVE_GETPGRP
6254 : PyDoc_STRVAR(posix_getpgrp__doc__,
6255 : "getpgrp() -> pgrp\n\n\
6256 : Return the current process group id.");
6257 :
6258 : static PyObject *
6259 0 : posix_getpgrp(PyObject *self, PyObject *noargs)
6260 : {
6261 : #ifdef GETPGRP_HAVE_ARG
6262 : return PyLong_FromPid(getpgrp(0));
6263 : #else /* GETPGRP_HAVE_ARG */
6264 0 : return PyLong_FromPid(getpgrp());
6265 : #endif /* GETPGRP_HAVE_ARG */
6266 : }
6267 : #endif /* HAVE_GETPGRP */
6268 :
6269 :
6270 : #ifdef HAVE_SETPGRP
6271 : PyDoc_STRVAR(posix_setpgrp__doc__,
6272 : "setpgrp()\n\n\
6273 : Make this process the process group leader.");
6274 :
6275 : static PyObject *
6276 0 : posix_setpgrp(PyObject *self, PyObject *noargs)
6277 : {
6278 : #ifdef SETPGRP_HAVE_ARG
6279 : if (setpgrp(0, 0) < 0)
6280 : #else /* SETPGRP_HAVE_ARG */
6281 0 : if (setpgrp() < 0)
6282 : #endif /* SETPGRP_HAVE_ARG */
6283 0 : return posix_error();
6284 0 : Py_INCREF(Py_None);
6285 0 : return Py_None;
6286 : }
6287 :
6288 : #endif /* HAVE_SETPGRP */
6289 :
6290 : #ifdef HAVE_GETPPID
6291 :
6292 : #ifdef MS_WINDOWS
6293 : #include <tlhelp32.h>
6294 :
6295 : static PyObject*
6296 : win32_getppid()
6297 : {
6298 : HANDLE snapshot;
6299 : pid_t mypid;
6300 : PyObject* result = NULL;
6301 : BOOL have_record;
6302 : PROCESSENTRY32 pe;
6303 :
6304 : mypid = getpid(); /* This function never fails */
6305 :
6306 : snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
6307 : if (snapshot == INVALID_HANDLE_VALUE)
6308 : return PyErr_SetFromWindowsErr(GetLastError());
6309 :
6310 : pe.dwSize = sizeof(pe);
6311 : have_record = Process32First(snapshot, &pe);
6312 : while (have_record) {
6313 : if (mypid == (pid_t)pe.th32ProcessID) {
6314 : /* We could cache the ulong value in a static variable. */
6315 : result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
6316 : break;
6317 : }
6318 :
6319 : have_record = Process32Next(snapshot, &pe);
6320 : }
6321 :
6322 : /* If our loop exits and our pid was not found (result will be NULL)
6323 : * then GetLastError will return ERROR_NO_MORE_FILES. This is an
6324 : * error anyway, so let's raise it. */
6325 : if (!result)
6326 : result = PyErr_SetFromWindowsErr(GetLastError());
6327 :
6328 : CloseHandle(snapshot);
6329 :
6330 : return result;
6331 : }
6332 : #endif /*MS_WINDOWS*/
6333 :
6334 : PyDoc_STRVAR(posix_getppid__doc__,
6335 : "getppid() -> ppid\n\n\
6336 : Return the parent's process id. If the parent process has already exited,\n\
6337 : Windows machines will still return its id; others systems will return the id\n\
6338 : of the 'init' process (1).");
6339 :
6340 : static PyObject *
6341 0 : posix_getppid(PyObject *self, PyObject *noargs)
6342 : {
6343 : #ifdef MS_WINDOWS
6344 : return win32_getppid();
6345 : #else
6346 0 : return PyLong_FromPid(getppid());
6347 : #endif
6348 : }
6349 : #endif /* HAVE_GETPPID */
6350 :
6351 :
6352 : #ifdef HAVE_GETLOGIN
6353 : PyDoc_STRVAR(posix_getlogin__doc__,
6354 : "getlogin() -> string\n\n\
6355 : Return the actual login name.");
6356 :
6357 : static PyObject *
6358 0 : posix_getlogin(PyObject *self, PyObject *noargs)
6359 : {
6360 0 : PyObject *result = NULL;
6361 : #ifdef MS_WINDOWS
6362 : wchar_t user_name[UNLEN + 1];
6363 : DWORD num_chars = Py_ARRAY_LENGTH(user_name);
6364 :
6365 : if (GetUserNameW(user_name, &num_chars)) {
6366 : /* num_chars is the number of unicode chars plus null terminator */
6367 : result = PyUnicode_FromWideChar(user_name, num_chars - 1);
6368 : }
6369 : else
6370 : result = PyErr_SetFromWindowsErr(GetLastError());
6371 : #else
6372 : char *name;
6373 0 : int old_errno = errno;
6374 :
6375 0 : errno = 0;
6376 0 : name = getlogin();
6377 0 : if (name == NULL) {
6378 0 : if (errno)
6379 0 : posix_error();
6380 : else
6381 0 : PyErr_SetString(PyExc_OSError, "unable to determine login name");
6382 : }
6383 : else
6384 0 : result = PyUnicode_DecodeFSDefault(name);
6385 0 : errno = old_errno;
6386 : #endif
6387 0 : return result;
6388 : }
6389 : #endif /* HAVE_GETLOGIN */
6390 :
6391 : #ifdef HAVE_GETUID
6392 : PyDoc_STRVAR(posix_getuid__doc__,
6393 : "getuid() -> uid\n\n\
6394 : Return the current process's user id.");
6395 :
6396 : static PyObject *
6397 1 : posix_getuid(PyObject *self, PyObject *noargs)
6398 : {
6399 1 : return PyLong_FromLong((long)getuid());
6400 : }
6401 : #endif
6402 :
6403 :
6404 : #ifdef HAVE_KILL
6405 : PyDoc_STRVAR(posix_kill__doc__,
6406 : "kill(pid, sig)\n\n\
6407 : Kill a process with a signal.");
6408 :
6409 : static PyObject *
6410 0 : posix_kill(PyObject *self, PyObject *args)
6411 : {
6412 : pid_t pid;
6413 : int sig;
6414 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:kill", &pid, &sig))
6415 0 : return NULL;
6416 : #if defined(PYOS_OS2) && !defined(PYCC_GCC)
6417 : if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
6418 : APIRET rc;
6419 : if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
6420 : return os2_error(rc);
6421 :
6422 : } else if (sig == XCPT_SIGNAL_KILLPROC) {
6423 : APIRET rc;
6424 : if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
6425 : return os2_error(rc);
6426 :
6427 : } else
6428 : return NULL; /* Unrecognized Signal Requested */
6429 : #else
6430 0 : if (kill(pid, sig) == -1)
6431 0 : return posix_error();
6432 : #endif
6433 0 : Py_INCREF(Py_None);
6434 0 : return Py_None;
6435 : }
6436 : #endif
6437 :
6438 : #ifdef HAVE_KILLPG
6439 : PyDoc_STRVAR(posix_killpg__doc__,
6440 : "killpg(pgid, sig)\n\n\
6441 : Kill a process group with a signal.");
6442 :
6443 : static PyObject *
6444 0 : posix_killpg(PyObject *self, PyObject *args)
6445 : {
6446 : int sig;
6447 : pid_t pgid;
6448 : /* XXX some man pages make the `pgid` parameter an int, others
6449 : a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
6450 : take the same type. Moreover, pid_t is always at least as wide as
6451 : int (else compilation of this module fails), which is safe. */
6452 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:killpg", &pgid, &sig))
6453 0 : return NULL;
6454 0 : if (killpg(pgid, sig) == -1)
6455 0 : return posix_error();
6456 0 : Py_INCREF(Py_None);
6457 0 : return Py_None;
6458 : }
6459 : #endif
6460 :
6461 : #ifdef MS_WINDOWS
6462 : PyDoc_STRVAR(win32_kill__doc__,
6463 : "kill(pid, sig)\n\n\
6464 : Kill a process with a signal.");
6465 :
6466 : static PyObject *
6467 : win32_kill(PyObject *self, PyObject *args)
6468 : {
6469 : PyObject *result;
6470 : DWORD pid, sig, err;
6471 : HANDLE handle;
6472 :
6473 : if (!PyArg_ParseTuple(args, "kk:kill", &pid, &sig))
6474 : return NULL;
6475 :
6476 : /* Console processes which share a common console can be sent CTRL+C or
6477 : CTRL+BREAK events, provided they handle said events. */
6478 : if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
6479 : if (GenerateConsoleCtrlEvent(sig, pid) == 0) {
6480 : err = GetLastError();
6481 : PyErr_SetFromWindowsErr(err);
6482 : }
6483 : else
6484 : Py_RETURN_NONE;
6485 : }
6486 :
6487 : /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
6488 : attempt to open and terminate the process. */
6489 : handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
6490 : if (handle == NULL) {
6491 : err = GetLastError();
6492 : return PyErr_SetFromWindowsErr(err);
6493 : }
6494 :
6495 : if (TerminateProcess(handle, sig) == 0) {
6496 : err = GetLastError();
6497 : result = PyErr_SetFromWindowsErr(err);
6498 : } else {
6499 : Py_INCREF(Py_None);
6500 : result = Py_None;
6501 : }
6502 :
6503 : CloseHandle(handle);
6504 : return result;
6505 : }
6506 : #endif /* MS_WINDOWS */
6507 :
6508 : #ifdef HAVE_PLOCK
6509 :
6510 : #ifdef HAVE_SYS_LOCK_H
6511 : #include <sys/lock.h>
6512 : #endif
6513 :
6514 : PyDoc_STRVAR(posix_plock__doc__,
6515 : "plock(op)\n\n\
6516 : Lock program segments into memory.");
6517 :
6518 : static PyObject *
6519 : posix_plock(PyObject *self, PyObject *args)
6520 : {
6521 : int op;
6522 : if (!PyArg_ParseTuple(args, "i:plock", &op))
6523 : return NULL;
6524 : if (plock(op) == -1)
6525 : return posix_error();
6526 : Py_INCREF(Py_None);
6527 : return Py_None;
6528 : }
6529 : #endif
6530 :
6531 : #ifdef HAVE_SETUID
6532 : PyDoc_STRVAR(posix_setuid__doc__,
6533 : "setuid(uid)\n\n\
6534 : Set the current process's user id.");
6535 :
6536 : static PyObject *
6537 0 : posix_setuid(PyObject *self, PyObject *args)
6538 : {
6539 : long uid_arg;
6540 : uid_t uid;
6541 0 : if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
6542 0 : return NULL;
6543 0 : uid = uid_arg;
6544 0 : if (uid != uid_arg) {
6545 0 : PyErr_SetString(PyExc_OverflowError, "user id too big");
6546 0 : return NULL;
6547 : }
6548 0 : if (setuid(uid) < 0)
6549 0 : return posix_error();
6550 0 : Py_INCREF(Py_None);
6551 0 : return Py_None;
6552 : }
6553 : #endif /* HAVE_SETUID */
6554 :
6555 :
6556 : #ifdef HAVE_SETEUID
6557 : PyDoc_STRVAR(posix_seteuid__doc__,
6558 : "seteuid(uid)\n\n\
6559 : Set the current process's effective user id.");
6560 :
6561 : static PyObject *
6562 0 : posix_seteuid (PyObject *self, PyObject *args)
6563 : {
6564 : long euid_arg;
6565 : uid_t euid;
6566 0 : if (!PyArg_ParseTuple(args, "l", &euid_arg))
6567 0 : return NULL;
6568 0 : euid = euid_arg;
6569 0 : if (euid != euid_arg) {
6570 0 : PyErr_SetString(PyExc_OverflowError, "user id too big");
6571 0 : return NULL;
6572 : }
6573 0 : if (seteuid(euid) < 0) {
6574 0 : return posix_error();
6575 : } else {
6576 0 : Py_INCREF(Py_None);
6577 0 : return Py_None;
6578 : }
6579 : }
6580 : #endif /* HAVE_SETEUID */
6581 :
6582 : #ifdef HAVE_SETEGID
6583 : PyDoc_STRVAR(posix_setegid__doc__,
6584 : "setegid(gid)\n\n\
6585 : Set the current process's effective group id.");
6586 :
6587 : static PyObject *
6588 0 : posix_setegid (PyObject *self, PyObject *args)
6589 : {
6590 : long egid_arg;
6591 : gid_t egid;
6592 0 : if (!PyArg_ParseTuple(args, "l", &egid_arg))
6593 0 : return NULL;
6594 0 : egid = egid_arg;
6595 0 : if (egid != egid_arg) {
6596 0 : PyErr_SetString(PyExc_OverflowError, "group id too big");
6597 0 : return NULL;
6598 : }
6599 0 : if (setegid(egid) < 0) {
6600 0 : return posix_error();
6601 : } else {
6602 0 : Py_INCREF(Py_None);
6603 0 : return Py_None;
6604 : }
6605 : }
6606 : #endif /* HAVE_SETEGID */
6607 :
6608 : #ifdef HAVE_SETREUID
6609 : PyDoc_STRVAR(posix_setreuid__doc__,
6610 : "setreuid(ruid, euid)\n\n\
6611 : Set the current process's real and effective user ids.");
6612 :
6613 : static PyObject *
6614 0 : posix_setreuid (PyObject *self, PyObject *args)
6615 : {
6616 : long ruid_arg, euid_arg;
6617 : uid_t ruid, euid;
6618 0 : if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
6619 0 : return NULL;
6620 0 : if (ruid_arg == -1)
6621 0 : ruid = (uid_t)-1; /* let the compiler choose how -1 fits */
6622 : else
6623 0 : ruid = ruid_arg; /* otherwise, assign from our long */
6624 0 : if (euid_arg == -1)
6625 0 : euid = (uid_t)-1;
6626 : else
6627 0 : euid = euid_arg;
6628 0 : if ((euid_arg != -1 && euid != euid_arg) ||
6629 0 : (ruid_arg != -1 && ruid != ruid_arg)) {
6630 0 : PyErr_SetString(PyExc_OverflowError, "user id too big");
6631 0 : return NULL;
6632 : }
6633 0 : if (setreuid(ruid, euid) < 0) {
6634 0 : return posix_error();
6635 : } else {
6636 0 : Py_INCREF(Py_None);
6637 0 : return Py_None;
6638 : }
6639 : }
6640 : #endif /* HAVE_SETREUID */
6641 :
6642 : #ifdef HAVE_SETREGID
6643 : PyDoc_STRVAR(posix_setregid__doc__,
6644 : "setregid(rgid, egid)\n\n\
6645 : Set the current process's real and effective group ids.");
6646 :
6647 : static PyObject *
6648 0 : posix_setregid (PyObject *self, PyObject *args)
6649 : {
6650 : long rgid_arg, egid_arg;
6651 : gid_t rgid, egid;
6652 0 : if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
6653 0 : return NULL;
6654 0 : if (rgid_arg == -1)
6655 0 : rgid = (gid_t)-1; /* let the compiler choose how -1 fits */
6656 : else
6657 0 : rgid = rgid_arg; /* otherwise, assign from our long */
6658 0 : if (egid_arg == -1)
6659 0 : egid = (gid_t)-1;
6660 : else
6661 0 : egid = egid_arg;
6662 0 : if ((egid_arg != -1 && egid != egid_arg) ||
6663 0 : (rgid_arg != -1 && rgid != rgid_arg)) {
6664 0 : PyErr_SetString(PyExc_OverflowError, "group id too big");
6665 0 : return NULL;
6666 : }
6667 0 : if (setregid(rgid, egid) < 0) {
6668 0 : return posix_error();
6669 : } else {
6670 0 : Py_INCREF(Py_None);
6671 0 : return Py_None;
6672 : }
6673 : }
6674 : #endif /* HAVE_SETREGID */
6675 :
6676 : #ifdef HAVE_SETGID
6677 : PyDoc_STRVAR(posix_setgid__doc__,
6678 : "setgid(gid)\n\n\
6679 : Set the current process's group id.");
6680 :
6681 : static PyObject *
6682 0 : posix_setgid(PyObject *self, PyObject *args)
6683 : {
6684 : long gid_arg;
6685 : gid_t gid;
6686 0 : if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
6687 0 : return NULL;
6688 0 : gid = gid_arg;
6689 0 : if (gid != gid_arg) {
6690 0 : PyErr_SetString(PyExc_OverflowError, "group id too big");
6691 0 : return NULL;
6692 : }
6693 0 : if (setgid(gid) < 0)
6694 0 : return posix_error();
6695 0 : Py_INCREF(Py_None);
6696 0 : return Py_None;
6697 : }
6698 : #endif /* HAVE_SETGID */
6699 :
6700 : #ifdef HAVE_SETGROUPS
6701 : PyDoc_STRVAR(posix_setgroups__doc__,
6702 : "setgroups(list)\n\n\
6703 : Set the groups of the current process to list.");
6704 :
6705 : static PyObject *
6706 0 : posix_setgroups(PyObject *self, PyObject *groups)
6707 : {
6708 : int i, len;
6709 : gid_t grouplist[MAX_GROUPS];
6710 :
6711 0 : if (!PySequence_Check(groups)) {
6712 0 : PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
6713 0 : return NULL;
6714 : }
6715 0 : len = PySequence_Size(groups);
6716 0 : if (len > MAX_GROUPS) {
6717 0 : PyErr_SetString(PyExc_ValueError, "too many groups");
6718 0 : return NULL;
6719 : }
6720 0 : for(i = 0; i < len; i++) {
6721 : PyObject *elem;
6722 0 : elem = PySequence_GetItem(groups, i);
6723 0 : if (!elem)
6724 0 : return NULL;
6725 0 : if (!PyLong_Check(elem)) {
6726 0 : PyErr_SetString(PyExc_TypeError,
6727 : "groups must be integers");
6728 0 : Py_DECREF(elem);
6729 0 : return NULL;
6730 : } else {
6731 0 : unsigned long x = PyLong_AsUnsignedLong(elem);
6732 0 : if (PyErr_Occurred()) {
6733 0 : PyErr_SetString(PyExc_TypeError,
6734 : "group id too big");
6735 0 : Py_DECREF(elem);
6736 0 : return NULL;
6737 : }
6738 0 : grouplist[i] = x;
6739 : /* read back the value to see if it fitted in gid_t */
6740 0 : if (grouplist[i] != x) {
6741 0 : PyErr_SetString(PyExc_TypeError,
6742 : "group id too big");
6743 0 : Py_DECREF(elem);
6744 0 : return NULL;
6745 : }
6746 : }
6747 0 : Py_DECREF(elem);
6748 : }
6749 :
6750 0 : if (setgroups(len, grouplist) < 0)
6751 0 : return posix_error();
6752 0 : Py_INCREF(Py_None);
6753 0 : return Py_None;
6754 : }
6755 : #endif /* HAVE_SETGROUPS */
6756 :
6757 : #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
6758 : static PyObject *
6759 0 : wait_helper(pid_t pid, int status, struct rusage *ru)
6760 : {
6761 : PyObject *result;
6762 : static PyObject *struct_rusage;
6763 : _Py_IDENTIFIER(struct_rusage);
6764 :
6765 0 : if (pid == -1)
6766 0 : return posix_error();
6767 :
6768 0 : if (struct_rusage == NULL) {
6769 0 : PyObject *m = PyImport_ImportModuleNoBlock("resource");
6770 0 : if (m == NULL)
6771 0 : return NULL;
6772 0 : struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage);
6773 0 : Py_DECREF(m);
6774 0 : if (struct_rusage == NULL)
6775 0 : return NULL;
6776 : }
6777 :
6778 : /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
6779 0 : result = PyStructSequence_New((PyTypeObject*) struct_rusage);
6780 0 : if (!result)
6781 0 : return NULL;
6782 :
6783 : #ifndef doubletime
6784 : #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
6785 : #endif
6786 :
6787 0 : PyStructSequence_SET_ITEM(result, 0,
6788 : PyFloat_FromDouble(doubletime(ru->ru_utime)));
6789 0 : PyStructSequence_SET_ITEM(result, 1,
6790 : PyFloat_FromDouble(doubletime(ru->ru_stime)));
6791 : #define SET_INT(result, index, value)\
6792 : PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
6793 0 : SET_INT(result, 2, ru->ru_maxrss);
6794 0 : SET_INT(result, 3, ru->ru_ixrss);
6795 0 : SET_INT(result, 4, ru->ru_idrss);
6796 0 : SET_INT(result, 5, ru->ru_isrss);
6797 0 : SET_INT(result, 6, ru->ru_minflt);
6798 0 : SET_INT(result, 7, ru->ru_majflt);
6799 0 : SET_INT(result, 8, ru->ru_nswap);
6800 0 : SET_INT(result, 9, ru->ru_inblock);
6801 0 : SET_INT(result, 10, ru->ru_oublock);
6802 0 : SET_INT(result, 11, ru->ru_msgsnd);
6803 0 : SET_INT(result, 12, ru->ru_msgrcv);
6804 0 : SET_INT(result, 13, ru->ru_nsignals);
6805 0 : SET_INT(result, 14, ru->ru_nvcsw);
6806 0 : SET_INT(result, 15, ru->ru_nivcsw);
6807 : #undef SET_INT
6808 :
6809 0 : if (PyErr_Occurred()) {
6810 0 : Py_DECREF(result);
6811 0 : return NULL;
6812 : }
6813 :
6814 0 : return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
6815 : }
6816 : #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
6817 :
6818 : #ifdef HAVE_WAIT3
6819 : PyDoc_STRVAR(posix_wait3__doc__,
6820 : "wait3(options) -> (pid, status, rusage)\n\n\
6821 : Wait for completion of a child process.");
6822 :
6823 : static PyObject *
6824 0 : posix_wait3(PyObject *self, PyObject *args)
6825 : {
6826 : pid_t pid;
6827 : int options;
6828 : struct rusage ru;
6829 : WAIT_TYPE status;
6830 0 : WAIT_STATUS_INT(status) = 0;
6831 :
6832 0 : if (!PyArg_ParseTuple(args, "i:wait3", &options))
6833 0 : return NULL;
6834 :
6835 0 : Py_BEGIN_ALLOW_THREADS
6836 0 : pid = wait3(&status, options, &ru);
6837 0 : Py_END_ALLOW_THREADS
6838 :
6839 0 : return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
6840 : }
6841 : #endif /* HAVE_WAIT3 */
6842 :
6843 : #ifdef HAVE_WAIT4
6844 : PyDoc_STRVAR(posix_wait4__doc__,
6845 : "wait4(pid, options) -> (pid, status, rusage)\n\n\
6846 : Wait for completion of a given child process.");
6847 :
6848 : static PyObject *
6849 0 : posix_wait4(PyObject *self, PyObject *args)
6850 : {
6851 : pid_t pid;
6852 : int options;
6853 : struct rusage ru;
6854 : WAIT_TYPE status;
6855 0 : WAIT_STATUS_INT(status) = 0;
6856 :
6857 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
6858 0 : return NULL;
6859 :
6860 0 : Py_BEGIN_ALLOW_THREADS
6861 0 : pid = wait4(pid, &status, options, &ru);
6862 0 : Py_END_ALLOW_THREADS
6863 :
6864 0 : return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
6865 : }
6866 : #endif /* HAVE_WAIT4 */
6867 :
6868 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
6869 : PyDoc_STRVAR(posix_waitid__doc__,
6870 : "waitid(idtype, id, options) -> waitid_result\n\n\
6871 : Wait for the completion of one or more child processes.\n\n\
6872 : idtype can be P_PID, P_PGID or P_ALL.\n\
6873 : id specifies the pid to wait on.\n\
6874 : options is constructed from the ORing of one or more of WEXITED, WSTOPPED\n\
6875 : or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n\
6876 : Returns either waitid_result or None if WNOHANG is specified and there are\n\
6877 : no children in a waitable state.");
6878 :
6879 : static PyObject *
6880 0 : posix_waitid(PyObject *self, PyObject *args)
6881 : {
6882 : PyObject *result;
6883 : idtype_t idtype;
6884 : id_t id;
6885 : int options, res;
6886 : siginfo_t si;
6887 0 : si.si_pid = 0;
6888 0 : if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID "i:waitid", &idtype, &id, &options))
6889 0 : return NULL;
6890 0 : Py_BEGIN_ALLOW_THREADS
6891 0 : res = waitid(idtype, id, &si, options);
6892 0 : Py_END_ALLOW_THREADS
6893 0 : if (res == -1)
6894 0 : return posix_error();
6895 :
6896 0 : if (si.si_pid == 0)
6897 0 : Py_RETURN_NONE;
6898 :
6899 0 : result = PyStructSequence_New(&WaitidResultType);
6900 0 : if (!result)
6901 0 : return NULL;
6902 :
6903 0 : PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
6904 0 : PyStructSequence_SET_ITEM(result, 1, PyLong_FromPid(si.si_uid));
6905 0 : PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
6906 0 : PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
6907 0 : PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
6908 0 : if (PyErr_Occurred()) {
6909 0 : Py_DECREF(result);
6910 0 : return NULL;
6911 : }
6912 :
6913 0 : return result;
6914 : }
6915 : #endif
6916 :
6917 : #ifdef HAVE_WAITPID
6918 : PyDoc_STRVAR(posix_waitpid__doc__,
6919 : "waitpid(pid, options) -> (pid, status)\n\n\
6920 : Wait for completion of a given child process.");
6921 :
6922 : static PyObject *
6923 0 : posix_waitpid(PyObject *self, PyObject *args)
6924 : {
6925 : pid_t pid;
6926 : int options;
6927 : WAIT_TYPE status;
6928 0 : WAIT_STATUS_INT(status) = 0;
6929 :
6930 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
6931 0 : return NULL;
6932 0 : Py_BEGIN_ALLOW_THREADS
6933 0 : pid = waitpid(pid, &status, options);
6934 0 : Py_END_ALLOW_THREADS
6935 0 : if (pid == -1)
6936 0 : return posix_error();
6937 :
6938 0 : return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
6939 : }
6940 :
6941 : #elif defined(HAVE_CWAIT)
6942 :
6943 : /* MS C has a variant of waitpid() that's usable for most purposes. */
6944 : PyDoc_STRVAR(posix_waitpid__doc__,
6945 : "waitpid(pid, options) -> (pid, status << 8)\n\n"
6946 : "Wait for completion of a given process. options is ignored on Windows.");
6947 :
6948 : static PyObject *
6949 : posix_waitpid(PyObject *self, PyObject *args)
6950 : {
6951 : Py_intptr_t pid;
6952 : int status, options;
6953 :
6954 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
6955 : return NULL;
6956 : Py_BEGIN_ALLOW_THREADS
6957 : pid = _cwait(&status, pid, options);
6958 : Py_END_ALLOW_THREADS
6959 : if (pid == -1)
6960 : return posix_error();
6961 :
6962 : /* shift the status left a byte so this is more like the POSIX waitpid */
6963 : return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
6964 : }
6965 : #endif /* HAVE_WAITPID || HAVE_CWAIT */
6966 :
6967 : #ifdef HAVE_WAIT
6968 : PyDoc_STRVAR(posix_wait__doc__,
6969 : "wait() -> (pid, status)\n\n\
6970 : Wait for completion of a child process.");
6971 :
6972 : static PyObject *
6973 0 : posix_wait(PyObject *self, PyObject *noargs)
6974 : {
6975 : pid_t pid;
6976 : WAIT_TYPE status;
6977 0 : WAIT_STATUS_INT(status) = 0;
6978 :
6979 0 : Py_BEGIN_ALLOW_THREADS
6980 0 : pid = wait(&status);
6981 0 : Py_END_ALLOW_THREADS
6982 0 : if (pid == -1)
6983 0 : return posix_error();
6984 :
6985 0 : return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
6986 : }
6987 : #endif
6988 :
6989 :
6990 : #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
6991 : PyDoc_STRVAR(readlink__doc__,
6992 : "readlink(path, *, dir_fd=None) -> path\n\n\
6993 : Return a string representing the path to which the symbolic link points.\n\
6994 : \n\
6995 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
6996 : and path should be relative; path will then be relative to that directory.\n\
6997 : dir_fd may not be implemented on your platform.\n\
6998 : If it is unavailable, using it will raise a NotImplementedError.");
6999 : #endif
7000 :
7001 : #ifdef HAVE_READLINK
7002 :
7003 : static PyObject *
7004 0 : posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
7005 : {
7006 : path_t path;
7007 0 : int dir_fd = DEFAULT_DIR_FD;
7008 : char buffer[MAXPATHLEN];
7009 : ssize_t length;
7010 0 : PyObject *return_value = NULL;
7011 : static char *keywords[] = {"path", "dir_fd", NULL};
7012 :
7013 0 : memset(&path, 0, sizeof(path));
7014 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords,
7015 : path_converter, &path,
7016 : #ifdef HAVE_READLINKAT
7017 : dir_fd_converter, &dir_fd
7018 : #else
7019 : dir_fd_unavailable, &dir_fd
7020 : #endif
7021 : ))
7022 0 : return NULL;
7023 :
7024 0 : Py_BEGIN_ALLOW_THREADS
7025 : #ifdef HAVE_READLINKAT
7026 0 : if (dir_fd != DEFAULT_DIR_FD)
7027 0 : length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer));
7028 : else
7029 : #endif
7030 0 : length = readlink(path.narrow, buffer, sizeof(buffer));
7031 0 : Py_END_ALLOW_THREADS
7032 :
7033 0 : if (length < 0) {
7034 0 : return_value = path_posix_error("readlink", &path);
7035 0 : goto exit;
7036 : }
7037 :
7038 0 : if (PyUnicode_Check(path.object))
7039 0 : return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length);
7040 : else
7041 0 : return_value = PyBytes_FromStringAndSize(buffer, length);
7042 : exit:
7043 0 : path_cleanup(&path);
7044 0 : return return_value;
7045 : }
7046 :
7047 :
7048 : #endif /* HAVE_READLINK */
7049 :
7050 :
7051 : #ifdef HAVE_SYMLINK
7052 : PyDoc_STRVAR(posix_symlink__doc__,
7053 : "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
7054 : Create a symbolic link pointing to src named dst.\n\n\
7055 : target_is_directory is required on Windows if the target is to be\n\
7056 : interpreted as a directory. (On Windows, symlink requires\n\
7057 : Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n\
7058 : target_is_directory is ignored on non-Windows platforms.\n\
7059 : \n\
7060 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
7061 : and path should be relative; path will then be relative to that directory.\n\
7062 : dir_fd may not be implemented on your platform.\n\
7063 : If it is unavailable, using it will raise a NotImplementedError.");
7064 :
7065 : #if defined(MS_WINDOWS)
7066 :
7067 : /* Grab CreateSymbolicLinkW dynamically from kernel32 */
7068 : static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL;
7069 : static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL;
7070 : static int
7071 : check_CreateSymbolicLink()
7072 : {
7073 : HINSTANCE hKernel32;
7074 : /* only recheck */
7075 : if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA)
7076 : return 1;
7077 : hKernel32 = GetModuleHandleW(L"KERNEL32");
7078 : *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
7079 : "CreateSymbolicLinkW");
7080 : *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32,
7081 : "CreateSymbolicLinkA");
7082 : return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA);
7083 : }
7084 :
7085 : #endif
7086 :
7087 : static PyObject *
7088 0 : posix_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
7089 : {
7090 : path_t src;
7091 : path_t dst;
7092 0 : int dir_fd = DEFAULT_DIR_FD;
7093 0 : int target_is_directory = 0;
7094 : static char *keywords[] = {"src", "dst", "target_is_directory",
7095 : "dir_fd", NULL};
7096 : PyObject *return_value;
7097 : #ifdef MS_WINDOWS
7098 : DWORD result;
7099 : #else
7100 : int result;
7101 : #endif
7102 :
7103 0 : memset(&src, 0, sizeof(src));
7104 0 : src.argument_name = "src";
7105 0 : memset(&dst, 0, sizeof(dst));
7106 0 : dst.argument_name = "dst";
7107 :
7108 : #ifdef MS_WINDOWS
7109 : if (!check_CreateSymbolicLink()) {
7110 : PyErr_SetString(PyExc_NotImplementedError,
7111 : "CreateSymbolicLink functions not found");
7112 : return NULL;
7113 : }
7114 : if (!win32_can_symlink) {
7115 : PyErr_SetString(PyExc_OSError, "symbolic link privilege not held");
7116 : return NULL;
7117 : }
7118 : #endif
7119 :
7120 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|i$O&:symlink",
7121 : keywords,
7122 : path_converter, &src,
7123 : path_converter, &dst,
7124 : &target_is_directory,
7125 : #ifdef HAVE_SYMLINKAT
7126 : dir_fd_converter, &dir_fd
7127 : #else
7128 : dir_fd_unavailable, &dir_fd
7129 : #endif
7130 : ))
7131 0 : return NULL;
7132 :
7133 0 : if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) {
7134 0 : PyErr_SetString(PyExc_ValueError,
7135 : "symlink: src and dst must be the same type");
7136 0 : return_value = NULL;
7137 0 : goto exit;
7138 : }
7139 :
7140 : #ifdef MS_WINDOWS
7141 : Py_BEGIN_ALLOW_THREADS
7142 : if (dst.wide)
7143 : result = Py_CreateSymbolicLinkW(dst.wide, src.wide,
7144 : target_is_directory);
7145 : else
7146 : result = Py_CreateSymbolicLinkA(dst.narrow, src.narrow,
7147 : target_is_directory);
7148 : Py_END_ALLOW_THREADS
7149 :
7150 : if (!result) {
7151 : return_value = win32_error_object("symlink", src.object);
7152 : goto exit;
7153 : }
7154 :
7155 : #else
7156 :
7157 0 : Py_BEGIN_ALLOW_THREADS
7158 : #if HAVE_SYMLINKAT
7159 0 : if (dir_fd != DEFAULT_DIR_FD)
7160 0 : result = symlinkat(src.narrow, dir_fd, dst.narrow);
7161 : else
7162 : #endif
7163 0 : result = symlink(src.narrow, dst.narrow);
7164 0 : Py_END_ALLOW_THREADS
7165 :
7166 0 : if (result) {
7167 0 : return_value = path_error("symlink", &dst);
7168 0 : goto exit;
7169 : }
7170 : #endif
7171 :
7172 0 : return_value = Py_None;
7173 0 : Py_INCREF(Py_None);
7174 0 : goto exit; /* silence "unused label" warning */
7175 : exit:
7176 0 : path_cleanup(&src);
7177 0 : path_cleanup(&dst);
7178 0 : return return_value;
7179 : }
7180 :
7181 : #endif /* HAVE_SYMLINK */
7182 :
7183 :
7184 : #if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
7185 :
7186 : static PyObject *
7187 : win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
7188 : {
7189 : wchar_t *path;
7190 : DWORD n_bytes_returned;
7191 : DWORD io_result;
7192 : PyObject *po, *result;
7193 : int dir_fd;
7194 : HANDLE reparse_point_handle;
7195 :
7196 : char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
7197 : REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
7198 : wchar_t *print_name;
7199 :
7200 : static char *keywords[] = {"path", "dir_fd", NULL};
7201 :
7202 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords,
7203 : &po,
7204 : dir_fd_unavailable, &dir_fd
7205 : ))
7206 : return NULL;
7207 :
7208 : path = PyUnicode_AsUnicode(po);
7209 : if (path == NULL)
7210 : return NULL;
7211 :
7212 : /* First get a handle to the reparse point */
7213 : Py_BEGIN_ALLOW_THREADS
7214 : reparse_point_handle = CreateFileW(
7215 : path,
7216 : 0,
7217 : 0,
7218 : 0,
7219 : OPEN_EXISTING,
7220 : FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
7221 : 0);
7222 : Py_END_ALLOW_THREADS
7223 :
7224 : if (reparse_point_handle==INVALID_HANDLE_VALUE)
7225 : return win32_error_object("readlink", po);
7226 :
7227 : Py_BEGIN_ALLOW_THREADS
7228 : /* New call DeviceIoControl to read the reparse point */
7229 : io_result = DeviceIoControl(
7230 : reparse_point_handle,
7231 : FSCTL_GET_REPARSE_POINT,
7232 : 0, 0, /* in buffer */
7233 : target_buffer, sizeof(target_buffer),
7234 : &n_bytes_returned,
7235 : 0 /* we're not using OVERLAPPED_IO */
7236 : );
7237 : CloseHandle(reparse_point_handle);
7238 : Py_END_ALLOW_THREADS
7239 :
7240 : if (io_result==0)
7241 : return win32_error_object("readlink", po);
7242 :
7243 : if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
7244 : {
7245 : PyErr_SetString(PyExc_ValueError,
7246 : "not a symbolic link");
7247 : return NULL;
7248 : }
7249 : print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
7250 : rdb->SymbolicLinkReparseBuffer.PrintNameOffset;
7251 :
7252 : result = PyUnicode_FromWideChar(print_name,
7253 : rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
7254 : return result;
7255 : }
7256 :
7257 : #endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
7258 :
7259 :
7260 : static PyStructSequence_Field times_result_fields[] = {
7261 : {"user", "user time"},
7262 : {"system", "system time"},
7263 : {"children_user", "user time of children"},
7264 : {"children_system", "system time of children"},
7265 : {"elapsed", "elapsed time since an arbitrary point in the past"},
7266 : {NULL}
7267 : };
7268 :
7269 : PyDoc_STRVAR(times_result__doc__,
7270 : "times_result: Result from os.times().\n\n\
7271 : This object may be accessed either as a tuple of\n\
7272 : (user, system, children_user, children_system, elapsed),\n\
7273 : or via the attributes user, system, children_user, children_system,\n\
7274 : and elapsed.\n\
7275 : \n\
7276 : See os.times for more information.");
7277 :
7278 : static PyStructSequence_Desc times_result_desc = {
7279 : "times_result", /* name */
7280 : times_result__doc__, /* doc */
7281 : times_result_fields,
7282 : 5
7283 : };
7284 :
7285 : static PyTypeObject TimesResultType;
7286 :
7287 : #ifdef MS_WINDOWS
7288 : #define HAVE_TIMES /* mandatory, for the method table */
7289 : #endif
7290 :
7291 : #ifdef HAVE_TIMES
7292 :
7293 : static PyObject *
7294 0 : build_times_result(double user, double system,
7295 : double children_user, double children_system,
7296 : double elapsed)
7297 : {
7298 0 : PyObject *value = PyStructSequence_New(&TimesResultType);
7299 0 : if (value == NULL)
7300 0 : return NULL;
7301 :
7302 : #define SET(i, field) \
7303 : { \
7304 : PyObject *o = PyFloat_FromDouble(field); \
7305 : if (!o) { \
7306 : Py_DECREF(value); \
7307 : return NULL; \
7308 : } \
7309 : PyStructSequence_SET_ITEM(value, i, o); \
7310 : } \
7311 :
7312 0 : SET(0, user);
7313 0 : SET(1, system);
7314 0 : SET(2, children_user);
7315 0 : SET(3, children_system);
7316 0 : SET(4, elapsed);
7317 :
7318 : #undef SET
7319 :
7320 0 : return value;
7321 : }
7322 :
7323 : PyDoc_STRVAR(posix_times__doc__,
7324 : "times() -> times_result\n\n\
7325 : Return an object containing floating point numbers indicating process\n\
7326 : times. The object behaves like a named tuple with these fields:\n\
7327 : (utime, stime, cutime, cstime, elapsed_time)");
7328 :
7329 : #if defined(PYCC_VACPP) && defined(PYOS_OS2)
7330 : static long
7331 : system_uptime(void)
7332 : {
7333 : ULONG value = 0;
7334 :
7335 : Py_BEGIN_ALLOW_THREADS
7336 : DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
7337 : Py_END_ALLOW_THREADS
7338 :
7339 : return value;
7340 : }
7341 :
7342 : static PyObject *
7343 : posix_times(PyObject *self, PyObject *noargs)
7344 : {
7345 : /* Currently Only Uptime is Provided -- Others Later */
7346 : return build_times_result(
7347 : (double)0 /* t.tms_utime / HZ */,
7348 : (double)0 /* t.tms_stime / HZ */,
7349 : (double)0 /* t.tms_cutime / HZ */,
7350 : (double)0 /* t.tms_cstime / HZ */,
7351 : (double)system_uptime() / 1000);
7352 : }
7353 : #elif defined(MS_WINDOWS)
7354 : static PyObject *
7355 : posix_times(PyObject *self, PyObject *noargs)
7356 : {
7357 : FILETIME create, exit, kernel, user;
7358 : HANDLE hProc;
7359 : hProc = GetCurrentProcess();
7360 : GetProcessTimes(hProc, &create, &exit, &kernel, &user);
7361 : /* The fields of a FILETIME structure are the hi and lo part
7362 : of a 64-bit value expressed in 100 nanosecond units.
7363 : 1e7 is one second in such units; 1e-7 the inverse.
7364 : 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
7365 : */
7366 : return build_times_result(
7367 : (double)(user.dwHighDateTime*429.4967296 +
7368 : user.dwLowDateTime*1e-7),
7369 : (double)(kernel.dwHighDateTime*429.4967296 +
7370 : kernel.dwLowDateTime*1e-7),
7371 : (double)0,
7372 : (double)0,
7373 : (double)0);
7374 : }
7375 : #else /* Neither Windows nor OS/2 */
7376 : #define NEED_TICKS_PER_SECOND
7377 : static long ticks_per_second = -1;
7378 : static PyObject *
7379 0 : posix_times(PyObject *self, PyObject *noargs)
7380 : {
7381 : struct tms t;
7382 : clock_t c;
7383 0 : errno = 0;
7384 0 : c = times(&t);
7385 0 : if (c == (clock_t) -1)
7386 0 : return posix_error();
7387 0 : return build_times_result(
7388 0 : (double)t.tms_utime / ticks_per_second,
7389 0 : (double)t.tms_stime / ticks_per_second,
7390 0 : (double)t.tms_cutime / ticks_per_second,
7391 0 : (double)t.tms_cstime / ticks_per_second,
7392 0 : (double)c / ticks_per_second);
7393 : }
7394 : #endif
7395 :
7396 : #endif /* HAVE_TIMES */
7397 :
7398 :
7399 : #ifdef HAVE_GETSID
7400 : PyDoc_STRVAR(posix_getsid__doc__,
7401 : "getsid(pid) -> sid\n\n\
7402 : Call the system call getsid().");
7403 :
7404 : static PyObject *
7405 0 : posix_getsid(PyObject *self, PyObject *args)
7406 : {
7407 : pid_t pid;
7408 : int sid;
7409 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getsid", &pid))
7410 0 : return NULL;
7411 0 : sid = getsid(pid);
7412 0 : if (sid < 0)
7413 0 : return posix_error();
7414 0 : return PyLong_FromLong((long)sid);
7415 : }
7416 : #endif /* HAVE_GETSID */
7417 :
7418 :
7419 : #ifdef HAVE_SETSID
7420 : PyDoc_STRVAR(posix_setsid__doc__,
7421 : "setsid()\n\n\
7422 : Call the system call setsid().");
7423 :
7424 : static PyObject *
7425 0 : posix_setsid(PyObject *self, PyObject *noargs)
7426 : {
7427 0 : if (setsid() < 0)
7428 0 : return posix_error();
7429 0 : Py_INCREF(Py_None);
7430 0 : return Py_None;
7431 : }
7432 : #endif /* HAVE_SETSID */
7433 :
7434 : #ifdef HAVE_SETPGID
7435 : PyDoc_STRVAR(posix_setpgid__doc__,
7436 : "setpgid(pid, pgrp)\n\n\
7437 : Call the system call setpgid().");
7438 :
7439 : static PyObject *
7440 0 : posix_setpgid(PyObject *self, PyObject *args)
7441 : {
7442 : pid_t pid;
7443 : int pgrp;
7444 0 : if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:setpgid", &pid, &pgrp))
7445 0 : return NULL;
7446 0 : if (setpgid(pid, pgrp) < 0)
7447 0 : return posix_error();
7448 0 : Py_INCREF(Py_None);
7449 0 : return Py_None;
7450 : }
7451 : #endif /* HAVE_SETPGID */
7452 :
7453 :
7454 : #ifdef HAVE_TCGETPGRP
7455 : PyDoc_STRVAR(posix_tcgetpgrp__doc__,
7456 : "tcgetpgrp(fd) -> pgid\n\n\
7457 : Return the process group associated with the terminal given by a fd.");
7458 :
7459 : static PyObject *
7460 0 : posix_tcgetpgrp(PyObject *self, PyObject *args)
7461 : {
7462 : int fd;
7463 : pid_t pgid;
7464 0 : if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
7465 0 : return NULL;
7466 0 : pgid = tcgetpgrp(fd);
7467 0 : if (pgid < 0)
7468 0 : return posix_error();
7469 0 : return PyLong_FromPid(pgid);
7470 : }
7471 : #endif /* HAVE_TCGETPGRP */
7472 :
7473 :
7474 : #ifdef HAVE_TCSETPGRP
7475 : PyDoc_STRVAR(posix_tcsetpgrp__doc__,
7476 : "tcsetpgrp(fd, pgid)\n\n\
7477 : Set the process group associated with the terminal given by a fd.");
7478 :
7479 : static PyObject *
7480 0 : posix_tcsetpgrp(PyObject *self, PyObject *args)
7481 : {
7482 : int fd;
7483 : pid_t pgid;
7484 0 : if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid))
7485 0 : return NULL;
7486 0 : if (tcsetpgrp(fd, pgid) < 0)
7487 0 : return posix_error();
7488 0 : Py_INCREF(Py_None);
7489 0 : return Py_None;
7490 : }
7491 : #endif /* HAVE_TCSETPGRP */
7492 :
7493 : /* Functions acting on file descriptors */
7494 :
7495 : PyDoc_STRVAR(posix_open__doc__,
7496 : "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
7497 : Open a file for low level IO. Returns a file handle (integer).\n\
7498 : \n\
7499 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
7500 : and path should be relative; path will then be relative to that directory.\n\
7501 : dir_fd may not be implemented on your platform.\n\
7502 : If it is unavailable, using it will raise a NotImplementedError.");
7503 :
7504 : static PyObject *
7505 0 : posix_open(PyObject *self, PyObject *args, PyObject *kwargs)
7506 : {
7507 : path_t path;
7508 : int flags;
7509 0 : int mode = 0777;
7510 0 : int dir_fd = DEFAULT_DIR_FD;
7511 : int fd;
7512 0 : PyObject *return_value = NULL;
7513 : static char *keywords[] = {"path", "flags", "mode", "dir_fd", NULL};
7514 :
7515 0 : memset(&path, 0, sizeof(path));
7516 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|i$O&:open", keywords,
7517 : path_converter, &path,
7518 : &flags, &mode,
7519 : #ifdef HAVE_OPENAT
7520 : dir_fd_converter, &dir_fd
7521 : #else
7522 : dir_fd_unavailable, &dir_fd
7523 : #endif
7524 : ))
7525 0 : return NULL;
7526 :
7527 0 : Py_BEGIN_ALLOW_THREADS
7528 : #ifdef MS_WINDOWS
7529 : if (path.wide)
7530 : fd = _wopen(path.wide, flags, mode);
7531 : else
7532 : #endif
7533 : #ifdef HAVE_OPENAT
7534 0 : if (dir_fd != DEFAULT_DIR_FD)
7535 0 : fd = openat(dir_fd, path.narrow, flags, mode);
7536 : else
7537 : #endif
7538 0 : fd = open(path.narrow, flags, mode);
7539 0 : Py_END_ALLOW_THREADS
7540 :
7541 0 : if (fd == -1) {
7542 : #ifdef MS_WINDOWS
7543 : /* force use of posix_error here for exact backwards compatibility */
7544 : if (path.wide)
7545 : return_value = posix_error();
7546 : else
7547 : #endif
7548 0 : return_value = path_error("open", &path);
7549 0 : goto exit;
7550 : }
7551 :
7552 0 : return_value = PyLong_FromLong((long)fd);
7553 :
7554 : exit:
7555 0 : path_cleanup(&path);
7556 0 : return return_value;
7557 : }
7558 :
7559 : PyDoc_STRVAR(posix_close__doc__,
7560 : "close(fd)\n\n\
7561 : Close a file descriptor (for low level IO).");
7562 :
7563 : static PyObject *
7564 0 : posix_close(PyObject *self, PyObject *args)
7565 : {
7566 : int fd, res;
7567 0 : if (!PyArg_ParseTuple(args, "i:close", &fd))
7568 0 : return NULL;
7569 : if (!_PyVerify_fd(fd))
7570 : return posix_error();
7571 0 : Py_BEGIN_ALLOW_THREADS
7572 0 : res = close(fd);
7573 0 : Py_END_ALLOW_THREADS
7574 0 : if (res < 0)
7575 0 : return posix_error();
7576 0 : Py_INCREF(Py_None);
7577 0 : return Py_None;
7578 : }
7579 :
7580 :
7581 : PyDoc_STRVAR(posix_closerange__doc__,
7582 : "closerange(fd_low, fd_high)\n\n\
7583 : Closes all file descriptors in [fd_low, fd_high), ignoring errors.");
7584 :
7585 : static PyObject *
7586 0 : posix_closerange(PyObject *self, PyObject *args)
7587 : {
7588 : int fd_from, fd_to, i;
7589 0 : if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
7590 0 : return NULL;
7591 0 : Py_BEGIN_ALLOW_THREADS
7592 0 : for (i = fd_from; i < fd_to; i++)
7593 : if (_PyVerify_fd(i))
7594 0 : close(i);
7595 0 : Py_END_ALLOW_THREADS
7596 0 : Py_RETURN_NONE;
7597 : }
7598 :
7599 :
7600 : PyDoc_STRVAR(posix_dup__doc__,
7601 : "dup(fd) -> fd2\n\n\
7602 : Return a duplicate of a file descriptor.");
7603 :
7604 : static PyObject *
7605 0 : posix_dup(PyObject *self, PyObject *args)
7606 : {
7607 : int fd;
7608 0 : if (!PyArg_ParseTuple(args, "i:dup", &fd))
7609 0 : return NULL;
7610 : if (!_PyVerify_fd(fd))
7611 : return posix_error();
7612 0 : fd = dup(fd);
7613 0 : if (fd < 0)
7614 0 : return posix_error();
7615 0 : return PyLong_FromLong((long)fd);
7616 : }
7617 :
7618 :
7619 : PyDoc_STRVAR(posix_dup2__doc__,
7620 : "dup2(old_fd, new_fd)\n\n\
7621 : Duplicate file descriptor.");
7622 :
7623 : static PyObject *
7624 0 : posix_dup2(PyObject *self, PyObject *args)
7625 : {
7626 : int fd, fd2, res;
7627 0 : if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
7628 0 : return NULL;
7629 : if (!_PyVerify_fd_dup2(fd, fd2))
7630 : return posix_error();
7631 0 : res = dup2(fd, fd2);
7632 0 : if (res < 0)
7633 0 : return posix_error();
7634 0 : Py_INCREF(Py_None);
7635 0 : return Py_None;
7636 : }
7637 :
7638 : #ifdef HAVE_LOCKF
7639 : PyDoc_STRVAR(posix_lockf__doc__,
7640 : "lockf(fd, cmd, len)\n\n\
7641 : Apply, test or remove a POSIX lock on an open file descriptor.\n\n\
7642 : fd is an open file descriptor.\n\
7643 : cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\
7644 : F_TEST.\n\
7645 : len specifies the section of the file to lock.");
7646 :
7647 : static PyObject *
7648 0 : posix_lockf(PyObject *self, PyObject *args)
7649 : {
7650 : int fd, cmd, res;
7651 : off_t len;
7652 0 : if (!PyArg_ParseTuple(args, "iiO&:lockf",
7653 : &fd, &cmd, _parse_off_t, &len))
7654 0 : return NULL;
7655 :
7656 0 : Py_BEGIN_ALLOW_THREADS
7657 0 : res = lockf(fd, cmd, len);
7658 0 : Py_END_ALLOW_THREADS
7659 :
7660 0 : if (res < 0)
7661 0 : return posix_error();
7662 :
7663 0 : Py_RETURN_NONE;
7664 : }
7665 : #endif
7666 :
7667 :
7668 : PyDoc_STRVAR(posix_lseek__doc__,
7669 : "lseek(fd, pos, how) -> newpos\n\n\
7670 : Set the current position of a file descriptor.\n\
7671 : Return the new cursor position in bytes, starting from the beginning.");
7672 :
7673 : static PyObject *
7674 0 : posix_lseek(PyObject *self, PyObject *args)
7675 : {
7676 : int fd, how;
7677 : #if defined(MS_WIN64) || defined(MS_WINDOWS)
7678 : PY_LONG_LONG pos, res;
7679 : #else
7680 : off_t pos, res;
7681 : #endif
7682 : PyObject *posobj;
7683 0 : if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
7684 0 : return NULL;
7685 : #ifdef SEEK_SET
7686 : /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
7687 0 : switch (how) {
7688 0 : case 0: how = SEEK_SET; break;
7689 0 : case 1: how = SEEK_CUR; break;
7690 0 : case 2: how = SEEK_END; break;
7691 : }
7692 : #endif /* SEEK_END */
7693 :
7694 : #if !defined(HAVE_LARGEFILE_SUPPORT)
7695 : pos = PyLong_AsLong(posobj);
7696 : #else
7697 0 : pos = PyLong_AsLongLong(posobj);
7698 : #endif
7699 0 : if (PyErr_Occurred())
7700 0 : return NULL;
7701 :
7702 : if (!_PyVerify_fd(fd))
7703 : return posix_error();
7704 0 : Py_BEGIN_ALLOW_THREADS
7705 : #if defined(MS_WIN64) || defined(MS_WINDOWS)
7706 : res = _lseeki64(fd, pos, how);
7707 : #else
7708 0 : res = lseek(fd, pos, how);
7709 : #endif
7710 0 : Py_END_ALLOW_THREADS
7711 0 : if (res < 0)
7712 0 : return posix_error();
7713 :
7714 : #if !defined(HAVE_LARGEFILE_SUPPORT)
7715 : return PyLong_FromLong(res);
7716 : #else
7717 0 : return PyLong_FromLongLong(res);
7718 : #endif
7719 : }
7720 :
7721 :
7722 : PyDoc_STRVAR(posix_read__doc__,
7723 : "read(fd, buffersize) -> string\n\n\
7724 : Read a file descriptor.");
7725 :
7726 : static PyObject *
7727 0 : posix_read(PyObject *self, PyObject *args)
7728 : {
7729 : int fd, size;
7730 : Py_ssize_t n;
7731 : PyObject *buffer;
7732 0 : if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
7733 0 : return NULL;
7734 0 : if (size < 0) {
7735 0 : errno = EINVAL;
7736 0 : return posix_error();
7737 : }
7738 0 : buffer = PyBytes_FromStringAndSize((char *)NULL, size);
7739 0 : if (buffer == NULL)
7740 0 : return NULL;
7741 : if (!_PyVerify_fd(fd)) {
7742 : Py_DECREF(buffer);
7743 : return posix_error();
7744 : }
7745 0 : Py_BEGIN_ALLOW_THREADS
7746 0 : n = read(fd, PyBytes_AS_STRING(buffer), size);
7747 0 : Py_END_ALLOW_THREADS
7748 0 : if (n < 0) {
7749 0 : Py_DECREF(buffer);
7750 0 : return posix_error();
7751 : }
7752 0 : if (n != size)
7753 0 : _PyBytes_Resize(&buffer, n);
7754 0 : return buffer;
7755 : }
7756 :
7757 : #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
7758 : || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV)
7759 : static Py_ssize_t
7760 0 : iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type)
7761 : {
7762 : int i, j;
7763 0 : Py_ssize_t blen, total = 0;
7764 :
7765 0 : *iov = PyMem_New(struct iovec, cnt);
7766 0 : if (*iov == NULL) {
7767 0 : PyErr_NoMemory();
7768 0 : return total;
7769 : }
7770 :
7771 0 : *buf = PyMem_New(Py_buffer, cnt);
7772 0 : if (*buf == NULL) {
7773 0 : PyMem_Del(*iov);
7774 0 : PyErr_NoMemory();
7775 0 : return total;
7776 : }
7777 :
7778 0 : for (i = 0; i < cnt; i++) {
7779 0 : PyObject *item = PySequence_GetItem(seq, i);
7780 0 : if (item == NULL)
7781 0 : goto fail;
7782 0 : if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
7783 0 : Py_DECREF(item);
7784 0 : goto fail;
7785 : }
7786 0 : Py_DECREF(item);
7787 0 : (*iov)[i].iov_base = (*buf)[i].buf;
7788 0 : blen = (*buf)[i].len;
7789 0 : (*iov)[i].iov_len = blen;
7790 0 : total += blen;
7791 : }
7792 0 : return total;
7793 :
7794 : fail:
7795 0 : PyMem_Del(*iov);
7796 0 : for (j = 0; j < i; j++) {
7797 0 : PyBuffer_Release(&(*buf)[j]);
7798 : }
7799 0 : PyMem_Del(*buf);
7800 0 : return 0;
7801 : }
7802 :
7803 : static void
7804 0 : iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
7805 : {
7806 : int i;
7807 0 : PyMem_Del(iov);
7808 0 : for (i = 0; i < cnt; i++) {
7809 0 : PyBuffer_Release(&buf[i]);
7810 : }
7811 0 : PyMem_Del(buf);
7812 0 : }
7813 : #endif
7814 :
7815 : #ifdef HAVE_READV
7816 : PyDoc_STRVAR(posix_readv__doc__,
7817 : "readv(fd, buffers) -> bytesread\n\n\
7818 : Read from a file descriptor into a number of writable buffers. buffers\n\
7819 : is an arbitrary sequence of writable buffers.\n\
7820 : Returns the total number of bytes read.");
7821 :
7822 : static PyObject *
7823 0 : posix_readv(PyObject *self, PyObject *args)
7824 : {
7825 : int fd, cnt;
7826 : Py_ssize_t n;
7827 : PyObject *seq;
7828 : struct iovec *iov;
7829 : Py_buffer *buf;
7830 :
7831 0 : if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq))
7832 0 : return NULL;
7833 0 : if (!PySequence_Check(seq)) {
7834 0 : PyErr_SetString(PyExc_TypeError,
7835 : "readv() arg 2 must be a sequence");
7836 0 : return NULL;
7837 : }
7838 0 : cnt = PySequence_Size(seq);
7839 :
7840 0 : if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE))
7841 0 : return NULL;
7842 :
7843 0 : Py_BEGIN_ALLOW_THREADS
7844 0 : n = readv(fd, iov, cnt);
7845 0 : Py_END_ALLOW_THREADS
7846 :
7847 0 : iov_cleanup(iov, buf, cnt);
7848 0 : return PyLong_FromSsize_t(n);
7849 : }
7850 : #endif
7851 :
7852 : #ifdef HAVE_PREAD
7853 : PyDoc_STRVAR(posix_pread__doc__,
7854 : "pread(fd, buffersize, offset) -> string\n\n\
7855 : Read from a file descriptor, fd, at a position of offset. It will read up\n\
7856 : to buffersize number of bytes. The file offset remains unchanged.");
7857 :
7858 : static PyObject *
7859 0 : posix_pread(PyObject *self, PyObject *args)
7860 : {
7861 : int fd, size;
7862 : off_t offset;
7863 : Py_ssize_t n;
7864 : PyObject *buffer;
7865 0 : if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset))
7866 0 : return NULL;
7867 :
7868 0 : if (size < 0) {
7869 0 : errno = EINVAL;
7870 0 : return posix_error();
7871 : }
7872 0 : buffer = PyBytes_FromStringAndSize((char *)NULL, size);
7873 0 : if (buffer == NULL)
7874 0 : return NULL;
7875 : if (!_PyVerify_fd(fd)) {
7876 : Py_DECREF(buffer);
7877 : return posix_error();
7878 : }
7879 0 : Py_BEGIN_ALLOW_THREADS
7880 0 : n = pread(fd, PyBytes_AS_STRING(buffer), size, offset);
7881 0 : Py_END_ALLOW_THREADS
7882 0 : if (n < 0) {
7883 0 : Py_DECREF(buffer);
7884 0 : return posix_error();
7885 : }
7886 0 : if (n != size)
7887 0 : _PyBytes_Resize(&buffer, n);
7888 0 : return buffer;
7889 : }
7890 : #endif
7891 :
7892 : PyDoc_STRVAR(posix_write__doc__,
7893 : "write(fd, string) -> byteswritten\n\n\
7894 : Write a string to a file descriptor.");
7895 :
7896 : static PyObject *
7897 0 : posix_write(PyObject *self, PyObject *args)
7898 : {
7899 : Py_buffer pbuf;
7900 : int fd;
7901 : Py_ssize_t size, len;
7902 :
7903 0 : if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
7904 0 : return NULL;
7905 : if (!_PyVerify_fd(fd)) {
7906 : PyBuffer_Release(&pbuf);
7907 : return posix_error();
7908 : }
7909 0 : len = pbuf.len;
7910 0 : Py_BEGIN_ALLOW_THREADS
7911 : #if defined(MS_WIN64) || defined(MS_WINDOWS)
7912 : if (len > INT_MAX)
7913 : len = INT_MAX;
7914 : size = write(fd, pbuf.buf, (int)len);
7915 : #else
7916 0 : size = write(fd, pbuf.buf, len);
7917 : #endif
7918 0 : Py_END_ALLOW_THREADS
7919 0 : PyBuffer_Release(&pbuf);
7920 0 : if (size < 0)
7921 0 : return posix_error();
7922 0 : return PyLong_FromSsize_t(size);
7923 : }
7924 :
7925 : #ifdef HAVE_SENDFILE
7926 : PyDoc_STRVAR(posix_sendfile__doc__,
7927 : "sendfile(out, in, offset, nbytes) -> byteswritten\n\
7928 : sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\
7929 : -> byteswritten\n\
7930 : Copy nbytes bytes from file descriptor in to file descriptor out.");
7931 :
7932 : static PyObject *
7933 0 : posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict)
7934 : {
7935 : int in, out;
7936 : Py_ssize_t ret;
7937 : off_t offset;
7938 :
7939 : #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
7940 : #ifndef __APPLE__
7941 : Py_ssize_t len;
7942 : #endif
7943 : PyObject *headers = NULL, *trailers = NULL;
7944 : Py_buffer *hbuf, *tbuf;
7945 : off_t sbytes;
7946 : struct sf_hdtr sf;
7947 : int flags = 0;
7948 : sf.headers = NULL;
7949 : sf.trailers = NULL;
7950 : static char *keywords[] = {"out", "in",
7951 : "offset", "count",
7952 : "headers", "trailers", "flags", NULL};
7953 :
7954 : #ifdef __APPLE__
7955 : if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile",
7956 : keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes,
7957 : #else
7958 : if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile",
7959 : keywords, &out, &in, _parse_off_t, &offset, &len,
7960 : #endif
7961 : &headers, &trailers, &flags))
7962 : return NULL;
7963 : if (headers != NULL) {
7964 : if (!PySequence_Check(headers)) {
7965 : PyErr_SetString(PyExc_TypeError,
7966 : "sendfile() headers must be a sequence or None");
7967 : return NULL;
7968 : } else {
7969 : Py_ssize_t i = 0; /* Avoid uninitialized warning */
7970 : sf.hdr_cnt = PySequence_Size(headers);
7971 : if (sf.hdr_cnt > 0 &&
7972 : !(i = iov_setup(&(sf.headers), &hbuf,
7973 : headers, sf.hdr_cnt, PyBUF_SIMPLE)))
7974 : return NULL;
7975 : #ifdef __APPLE__
7976 : sbytes += i;
7977 : #endif
7978 : }
7979 : }
7980 : if (trailers != NULL) {
7981 : if (!PySequence_Check(trailers)) {
7982 : PyErr_SetString(PyExc_TypeError,
7983 : "sendfile() trailers must be a sequence or None");
7984 : return NULL;
7985 : } else {
7986 : Py_ssize_t i = 0; /* Avoid uninitialized warning */
7987 : sf.trl_cnt = PySequence_Size(trailers);
7988 : if (sf.trl_cnt > 0 &&
7989 : !(i = iov_setup(&(sf.trailers), &tbuf,
7990 : trailers, sf.trl_cnt, PyBUF_SIMPLE)))
7991 : return NULL;
7992 : #ifdef __APPLE__
7993 : sbytes += i;
7994 : #endif
7995 : }
7996 : }
7997 :
7998 : Py_BEGIN_ALLOW_THREADS
7999 : #ifdef __APPLE__
8000 : ret = sendfile(in, out, offset, &sbytes, &sf, flags);
8001 : #else
8002 : ret = sendfile(in, out, offset, len, &sf, &sbytes, flags);
8003 : #endif
8004 : Py_END_ALLOW_THREADS
8005 :
8006 : if (sf.headers != NULL)
8007 : iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
8008 : if (sf.trailers != NULL)
8009 : iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
8010 :
8011 : if (ret < 0) {
8012 : if ((errno == EAGAIN) || (errno == EBUSY)) {
8013 : if (sbytes != 0) {
8014 : // some data has been sent
8015 : goto done;
8016 : }
8017 : else {
8018 : // no data has been sent; upper application is supposed
8019 : // to retry on EAGAIN or EBUSY
8020 : return posix_error();
8021 : }
8022 : }
8023 : return posix_error();
8024 : }
8025 : goto done;
8026 :
8027 : done:
8028 : #if !defined(HAVE_LARGEFILE_SUPPORT)
8029 : return Py_BuildValue("l", sbytes);
8030 : #else
8031 : return Py_BuildValue("L", sbytes);
8032 : #endif
8033 :
8034 : #else
8035 : Py_ssize_t count;
8036 : PyObject *offobj;
8037 : static char *keywords[] = {"out", "in",
8038 : "offset", "count", NULL};
8039 0 : if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
8040 : keywords, &out, &in, &offobj, &count))
8041 0 : return NULL;
8042 : #ifdef linux
8043 0 : if (offobj == Py_None) {
8044 0 : Py_BEGIN_ALLOW_THREADS
8045 0 : ret = sendfile(out, in, NULL, count);
8046 0 : Py_END_ALLOW_THREADS
8047 0 : if (ret < 0)
8048 0 : return posix_error();
8049 0 : return Py_BuildValue("n", ret);
8050 : }
8051 : #endif
8052 0 : if (!_parse_off_t(offobj, &offset))
8053 0 : return NULL;
8054 0 : Py_BEGIN_ALLOW_THREADS
8055 0 : ret = sendfile(out, in, &offset, count);
8056 0 : Py_END_ALLOW_THREADS
8057 0 : if (ret < 0)
8058 0 : return posix_error();
8059 0 : return Py_BuildValue("n", ret);
8060 : #endif
8061 : }
8062 : #endif
8063 :
8064 : PyDoc_STRVAR(posix_fstat__doc__,
8065 : "fstat(fd) -> stat result\n\n\
8066 : Like stat(), but for an open file descriptor.\n\
8067 : Equivalent to stat(fd=fd).");
8068 :
8069 : static PyObject *
8070 0 : posix_fstat(PyObject *self, PyObject *args)
8071 : {
8072 : int fd;
8073 : STRUCT_STAT st;
8074 : int res;
8075 0 : if (!PyArg_ParseTuple(args, "i:fstat", &fd))
8076 0 : return NULL;
8077 : #ifdef __VMS
8078 : /* on OpenVMS we must ensure that all bytes are written to the file */
8079 : fsync(fd);
8080 : #endif
8081 0 : Py_BEGIN_ALLOW_THREADS
8082 0 : res = FSTAT(fd, &st);
8083 0 : Py_END_ALLOW_THREADS
8084 0 : if (res != 0) {
8085 : #ifdef MS_WINDOWS
8086 : return win32_error("fstat", NULL);
8087 : #else
8088 0 : return posix_error();
8089 : #endif
8090 : }
8091 :
8092 0 : return _pystat_fromstructstat(&st);
8093 : }
8094 :
8095 : PyDoc_STRVAR(posix_isatty__doc__,
8096 : "isatty(fd) -> bool\n\n\
8097 : Return True if the file descriptor 'fd' is an open file descriptor\n\
8098 : connected to the slave end of a terminal.");
8099 :
8100 : static PyObject *
8101 0 : posix_isatty(PyObject *self, PyObject *args)
8102 : {
8103 : int fd;
8104 0 : if (!PyArg_ParseTuple(args, "i:isatty", &fd))
8105 0 : return NULL;
8106 : if (!_PyVerify_fd(fd))
8107 : return PyBool_FromLong(0);
8108 0 : return PyBool_FromLong(isatty(fd));
8109 : }
8110 :
8111 : #ifdef HAVE_PIPE
8112 : PyDoc_STRVAR(posix_pipe__doc__,
8113 : "pipe() -> (read_end, write_end)\n\n\
8114 : Create a pipe.");
8115 :
8116 : static PyObject *
8117 0 : posix_pipe(PyObject *self, PyObject *noargs)
8118 : {
8119 : #if defined(PYOS_OS2)
8120 : HFILE read, write;
8121 : APIRET rc;
8122 :
8123 : rc = DosCreatePipe( &read, &write, 4096);
8124 : if (rc != NO_ERROR)
8125 : return os2_error(rc);
8126 :
8127 : return Py_BuildValue("(ii)", read, write);
8128 : #else
8129 : #if !defined(MS_WINDOWS)
8130 : int fds[2];
8131 : int res;
8132 0 : res = pipe(fds);
8133 0 : if (res != 0)
8134 0 : return posix_error();
8135 0 : return Py_BuildValue("(ii)", fds[0], fds[1]);
8136 : #else /* MS_WINDOWS */
8137 : HANDLE read, write;
8138 : int read_fd, write_fd;
8139 : BOOL ok;
8140 : ok = CreatePipe(&read, &write, NULL, 0);
8141 : if (!ok)
8142 : return win32_error("CreatePipe", NULL);
8143 : read_fd = _open_osfhandle((Py_intptr_t)read, 0);
8144 : write_fd = _open_osfhandle((Py_intptr_t)write, 1);
8145 : return Py_BuildValue("(ii)", read_fd, write_fd);
8146 : #endif /* MS_WINDOWS */
8147 : #endif
8148 : }
8149 : #endif /* HAVE_PIPE */
8150 :
8151 : #ifdef HAVE_PIPE2
8152 : PyDoc_STRVAR(posix_pipe2__doc__,
8153 : "pipe2(flags) -> (read_end, write_end)\n\n\
8154 : Create a pipe with flags set atomically.\n\
8155 : flags can be constructed by ORing together one or more of these values:\n\
8156 : O_NONBLOCK, O_CLOEXEC.\n\
8157 : ");
8158 :
8159 : static PyObject *
8160 0 : posix_pipe2(PyObject *self, PyObject *arg)
8161 : {
8162 : int flags;
8163 : int fds[2];
8164 : int res;
8165 :
8166 0 : flags = PyLong_AsLong(arg);
8167 0 : if (flags == -1 && PyErr_Occurred())
8168 0 : return NULL;
8169 :
8170 0 : res = pipe2(fds, flags);
8171 0 : if (res != 0)
8172 0 : return posix_error();
8173 0 : return Py_BuildValue("(ii)", fds[0], fds[1]);
8174 : }
8175 : #endif /* HAVE_PIPE2 */
8176 :
8177 : #ifdef HAVE_WRITEV
8178 : PyDoc_STRVAR(posix_writev__doc__,
8179 : "writev(fd, buffers) -> byteswritten\n\n\
8180 : Write the contents of buffers to a file descriptor, where buffers is an\n\
8181 : arbitrary sequence of buffers.\n\
8182 : Returns the total bytes written.");
8183 :
8184 : static PyObject *
8185 0 : posix_writev(PyObject *self, PyObject *args)
8186 : {
8187 : int fd, cnt;
8188 : Py_ssize_t res;
8189 : PyObject *seq;
8190 : struct iovec *iov;
8191 : Py_buffer *buf;
8192 0 : if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq))
8193 0 : return NULL;
8194 0 : if (!PySequence_Check(seq)) {
8195 0 : PyErr_SetString(PyExc_TypeError,
8196 : "writev() arg 2 must be a sequence");
8197 0 : return NULL;
8198 : }
8199 0 : cnt = PySequence_Size(seq);
8200 :
8201 0 : if (!iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE)) {
8202 0 : return NULL;
8203 : }
8204 :
8205 0 : Py_BEGIN_ALLOW_THREADS
8206 0 : res = writev(fd, iov, cnt);
8207 0 : Py_END_ALLOW_THREADS
8208 :
8209 0 : iov_cleanup(iov, buf, cnt);
8210 0 : return PyLong_FromSsize_t(res);
8211 : }
8212 : #endif
8213 :
8214 : #ifdef HAVE_PWRITE
8215 : PyDoc_STRVAR(posix_pwrite__doc__,
8216 : "pwrite(fd, string, offset) -> byteswritten\n\n\
8217 : Write string to a file descriptor, fd, from offset, leaving the file\n\
8218 : offset unchanged.");
8219 :
8220 : static PyObject *
8221 0 : posix_pwrite(PyObject *self, PyObject *args)
8222 : {
8223 : Py_buffer pbuf;
8224 : int fd;
8225 : off_t offset;
8226 : Py_ssize_t size;
8227 :
8228 0 : if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset))
8229 0 : return NULL;
8230 :
8231 : if (!_PyVerify_fd(fd)) {
8232 : PyBuffer_Release(&pbuf);
8233 : return posix_error();
8234 : }
8235 0 : Py_BEGIN_ALLOW_THREADS
8236 0 : size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset);
8237 0 : Py_END_ALLOW_THREADS
8238 0 : PyBuffer_Release(&pbuf);
8239 0 : if (size < 0)
8240 0 : return posix_error();
8241 0 : return PyLong_FromSsize_t(size);
8242 : }
8243 : #endif
8244 :
8245 : #ifdef HAVE_MKFIFO
8246 : PyDoc_STRVAR(posix_mkfifo__doc__,
8247 : "mkfifo(path, mode=0o666, *, dir_fd=None)\n\n\
8248 : Create a FIFO (a POSIX named pipe).\n\
8249 : \n\
8250 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
8251 : and path should be relative; path will then be relative to that directory.\n\
8252 : dir_fd may not be implemented on your platform.\n\
8253 : If it is unavailable, using it will raise a NotImplementedError.");
8254 :
8255 : static PyObject *
8256 0 : posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs)
8257 : {
8258 : path_t path;
8259 0 : int mode = 0666;
8260 0 : int dir_fd = DEFAULT_DIR_FD;
8261 : int result;
8262 0 : PyObject *return_value = NULL;
8263 : static char *keywords[] = {"path", "mode", "dir_fd", NULL};
8264 :
8265 0 : memset(&path, 0, sizeof(path));
8266 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords,
8267 : path_converter, &path,
8268 : &mode,
8269 : #ifdef HAVE_MKFIFOAT
8270 : dir_fd_converter, &dir_fd
8271 : #else
8272 : dir_fd_unavailable, &dir_fd
8273 : #endif
8274 : ))
8275 0 : return NULL;
8276 :
8277 0 : Py_BEGIN_ALLOW_THREADS
8278 : #ifdef HAVE_MKFIFOAT
8279 0 : if (dir_fd != DEFAULT_DIR_FD)
8280 0 : result = mkfifoat(dir_fd, path.narrow, mode);
8281 : else
8282 : #endif
8283 0 : result = mkfifo(path.narrow, mode);
8284 0 : Py_END_ALLOW_THREADS
8285 :
8286 0 : if (result < 0) {
8287 0 : return_value = posix_error();
8288 0 : goto exit;
8289 : }
8290 :
8291 0 : return_value = Py_None;
8292 0 : Py_INCREF(Py_None);
8293 :
8294 : exit:
8295 0 : path_cleanup(&path);
8296 0 : return return_value;
8297 : }
8298 : #endif
8299 :
8300 : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
8301 : PyDoc_STRVAR(posix_mknod__doc__,
8302 : "mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\
8303 : Create a filesystem node (file, device special file or named pipe)\n\
8304 : named filename. mode specifies both the permissions to use and the\n\
8305 : type of node to be created, being combined (bitwise OR) with one of\n\
8306 : S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
8307 : device defines the newly created device special file (probably using\n\
8308 : os.makedev()), otherwise it is ignored.\n\
8309 : \n\
8310 : If dir_fd is not None, it should be a file descriptor open to a directory,\n\
8311 : and path should be relative; path will then be relative to that directory.\n\
8312 : dir_fd may not be implemented on your platform.\n\
8313 : If it is unavailable, using it will raise a NotImplementedError.");
8314 :
8315 :
8316 : static PyObject *
8317 0 : posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs)
8318 : {
8319 : path_t path;
8320 0 : int mode = 0666;
8321 0 : int device = 0;
8322 0 : int dir_fd = DEFAULT_DIR_FD;
8323 : int result;
8324 0 : PyObject *return_value = NULL;
8325 : static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL};
8326 :
8327 0 : memset(&path, 0, sizeof(path));
8328 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|ii$O&:mknod", keywords,
8329 : path_converter, &path,
8330 : &mode, &device,
8331 : #ifdef HAVE_MKNODAT
8332 : dir_fd_converter, &dir_fd
8333 : #else
8334 : dir_fd_unavailable, &dir_fd
8335 : #endif
8336 : ))
8337 0 : return NULL;
8338 :
8339 0 : Py_BEGIN_ALLOW_THREADS
8340 : #ifdef HAVE_MKNODAT
8341 0 : if (dir_fd != DEFAULT_DIR_FD)
8342 0 : result = mknodat(dir_fd, path.narrow, mode, device);
8343 : else
8344 : #endif
8345 0 : result = mknod(path.narrow, mode, device);
8346 0 : Py_END_ALLOW_THREADS
8347 :
8348 0 : if (result < 0) {
8349 0 : return_value = posix_error();
8350 0 : goto exit;
8351 : }
8352 :
8353 0 : return_value = Py_None;
8354 0 : Py_INCREF(Py_None);
8355 :
8356 : exit:
8357 0 : path_cleanup(&path);
8358 0 : return return_value;
8359 : }
8360 : #endif
8361 :
8362 : #ifdef HAVE_DEVICE_MACROS
8363 : PyDoc_STRVAR(posix_major__doc__,
8364 : "major(device) -> major number\n\
8365 : Extracts a device major number from a raw device number.");
8366 :
8367 : static PyObject *
8368 0 : posix_major(PyObject *self, PyObject *args)
8369 : {
8370 : int device;
8371 0 : if (!PyArg_ParseTuple(args, "i:major", &device))
8372 0 : return NULL;
8373 0 : return PyLong_FromLong((long)major(device));
8374 : }
8375 :
8376 : PyDoc_STRVAR(posix_minor__doc__,
8377 : "minor(device) -> minor number\n\
8378 : Extracts a device minor number from a raw device number.");
8379 :
8380 : static PyObject *
8381 0 : posix_minor(PyObject *self, PyObject *args)
8382 : {
8383 : int device;
8384 0 : if (!PyArg_ParseTuple(args, "i:minor", &device))
8385 0 : return NULL;
8386 0 : return PyLong_FromLong((long)minor(device));
8387 : }
8388 :
8389 : PyDoc_STRVAR(posix_makedev__doc__,
8390 : "makedev(major, minor) -> device number\n\
8391 : Composes a raw device number from the major and minor device numbers.");
8392 :
8393 : static PyObject *
8394 0 : posix_makedev(PyObject *self, PyObject *args)
8395 : {
8396 : int major, minor;
8397 0 : if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
8398 0 : return NULL;
8399 0 : return PyLong_FromLong((long)makedev(major, minor));
8400 : }
8401 : #endif /* device macros */
8402 :
8403 :
8404 : #ifdef HAVE_FTRUNCATE
8405 : PyDoc_STRVAR(posix_ftruncate__doc__,
8406 : "ftruncate(fd, length)\n\n\
8407 : Truncate a file to a specified length.");
8408 :
8409 : static PyObject *
8410 0 : posix_ftruncate(PyObject *self, PyObject *args)
8411 : {
8412 : int fd;
8413 : off_t length;
8414 : int res;
8415 :
8416 0 : if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length))
8417 0 : return NULL;
8418 :
8419 0 : Py_BEGIN_ALLOW_THREADS
8420 0 : res = ftruncate(fd, length);
8421 0 : Py_END_ALLOW_THREADS
8422 0 : if (res < 0)
8423 0 : return posix_error();
8424 0 : Py_INCREF(Py_None);
8425 0 : return Py_None;
8426 : }
8427 : #endif
8428 :
8429 : #ifdef HAVE_TRUNCATE
8430 : PyDoc_STRVAR(posix_truncate__doc__,
8431 : "truncate(path, length)\n\n\
8432 : Truncate the file given by path to length bytes.\n\
8433 : On some platforms, path may also be specified as an open file descriptor.\n\
8434 : If this functionality is unavailable, using it raises an exception.");
8435 :
8436 : static PyObject *
8437 0 : posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs)
8438 : {
8439 : path_t path;
8440 : off_t length;
8441 : int res;
8442 0 : PyObject *result = NULL;
8443 : static char *keywords[] = {"path", "length", NULL};
8444 :
8445 0 : memset(&path, 0, sizeof(path));
8446 : #ifdef HAVE_FTRUNCATE
8447 0 : path.allow_fd = 1;
8448 : #endif
8449 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords,
8450 : path_converter, &path,
8451 : _parse_off_t, &length))
8452 0 : return NULL;
8453 :
8454 0 : Py_BEGIN_ALLOW_THREADS
8455 : #ifdef HAVE_FTRUNCATE
8456 0 : if (path.fd != -1)
8457 0 : res = ftruncate(path.fd, length);
8458 : else
8459 : #endif
8460 0 : res = truncate(path.narrow, length);
8461 0 : Py_END_ALLOW_THREADS
8462 0 : if (res < 0)
8463 0 : result = path_posix_error("truncate", &path);
8464 : else {
8465 0 : Py_INCREF(Py_None);
8466 0 : result = Py_None;
8467 : }
8468 0 : path_cleanup(&path);
8469 0 : return result;
8470 : }
8471 : #endif
8472 :
8473 : #ifdef HAVE_POSIX_FALLOCATE
8474 : PyDoc_STRVAR(posix_posix_fallocate__doc__,
8475 : "posix_fallocate(fd, offset, len)\n\n\
8476 : Ensures that enough disk space is allocated for the file specified by fd\n\
8477 : starting from offset and continuing for len bytes.");
8478 :
8479 : static PyObject *
8480 0 : posix_posix_fallocate(PyObject *self, PyObject *args)
8481 : {
8482 : off_t len, offset;
8483 : int res, fd;
8484 :
8485 0 : if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate",
8486 : &fd, _parse_off_t, &offset, _parse_off_t, &len))
8487 0 : return NULL;
8488 :
8489 0 : Py_BEGIN_ALLOW_THREADS
8490 0 : res = posix_fallocate(fd, offset, len);
8491 0 : Py_END_ALLOW_THREADS
8492 0 : if (res != 0) {
8493 0 : errno = res;
8494 0 : return posix_error();
8495 : }
8496 0 : Py_RETURN_NONE;
8497 : }
8498 : #endif
8499 :
8500 : #ifdef HAVE_POSIX_FADVISE
8501 : PyDoc_STRVAR(posix_posix_fadvise__doc__,
8502 : "posix_fadvise(fd, offset, len, advice)\n\n\
8503 : Announces an intention to access data in a specific pattern thus allowing\n\
8504 : the kernel to make optimizations.\n\
8505 : The advice applies to the region of the file specified by fd starting at\n\
8506 : offset and continuing for len bytes.\n\
8507 : advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n\
8508 : POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED or\n\
8509 : POSIX_FADV_DONTNEED.");
8510 :
8511 : static PyObject *
8512 0 : posix_posix_fadvise(PyObject *self, PyObject *args)
8513 : {
8514 : off_t len, offset;
8515 : int res, fd, advice;
8516 :
8517 0 : if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise",
8518 : &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice))
8519 0 : return NULL;
8520 :
8521 0 : Py_BEGIN_ALLOW_THREADS
8522 0 : res = posix_fadvise(fd, offset, len, advice);
8523 0 : Py_END_ALLOW_THREADS
8524 0 : if (res != 0) {
8525 0 : errno = res;
8526 0 : return posix_error();
8527 : }
8528 0 : Py_RETURN_NONE;
8529 : }
8530 : #endif
8531 :
8532 : #ifdef HAVE_PUTENV
8533 : PyDoc_STRVAR(posix_putenv__doc__,
8534 : "putenv(key, value)\n\n\
8535 : Change or add an environment variable.");
8536 :
8537 : /* Save putenv() parameters as values here, so we can collect them when they
8538 : * get re-set with another call for the same key. */
8539 : static PyObject *posix_putenv_garbage;
8540 :
8541 : static PyObject *
8542 0 : posix_putenv(PyObject *self, PyObject *args)
8543 : {
8544 0 : PyObject *newstr = NULL;
8545 : #ifdef MS_WINDOWS
8546 : PyObject *os1, *os2;
8547 : wchar_t *newenv;
8548 :
8549 : if (!PyArg_ParseTuple(args,
8550 : "UU:putenv",
8551 : &os1, &os2))
8552 : return NULL;
8553 :
8554 : newstr = PyUnicode_FromFormat("%U=%U", os1, os2);
8555 : if (newstr == NULL) {
8556 : PyErr_NoMemory();
8557 : goto error;
8558 : }
8559 : if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) {
8560 : PyErr_Format(PyExc_ValueError,
8561 : "the environment variable is longer than %u characters",
8562 : _MAX_ENV);
8563 : goto error;
8564 : }
8565 :
8566 : newenv = PyUnicode_AsUnicode(newstr);
8567 : if (newenv == NULL)
8568 : goto error;
8569 : if (_wputenv(newenv)) {
8570 : posix_error();
8571 : goto error;
8572 : }
8573 : #else
8574 : PyObject *os1, *os2;
8575 : char *s1, *s2;
8576 : char *newenv;
8577 :
8578 0 : if (!PyArg_ParseTuple(args,
8579 : "O&O&:putenv",
8580 : PyUnicode_FSConverter, &os1,
8581 : PyUnicode_FSConverter, &os2))
8582 0 : return NULL;
8583 0 : s1 = PyBytes_AsString(os1);
8584 0 : s2 = PyBytes_AsString(os2);
8585 :
8586 0 : newstr = PyBytes_FromFormat("%s=%s", s1, s2);
8587 0 : if (newstr == NULL) {
8588 0 : PyErr_NoMemory();
8589 0 : goto error;
8590 : }
8591 :
8592 0 : newenv = PyBytes_AS_STRING(newstr);
8593 0 : if (putenv(newenv)) {
8594 0 : posix_error();
8595 0 : goto error;
8596 : }
8597 : #endif
8598 :
8599 : /* Install the first arg and newstr in posix_putenv_garbage;
8600 : * this will cause previous value to be collected. This has to
8601 : * happen after the real putenv() call because the old value
8602 : * was still accessible until then. */
8603 0 : if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) {
8604 : /* really not much we can do; just leak */
8605 0 : PyErr_Clear();
8606 : }
8607 : else {
8608 0 : Py_DECREF(newstr);
8609 : }
8610 :
8611 : #ifndef MS_WINDOWS
8612 0 : Py_DECREF(os1);
8613 0 : Py_DECREF(os2);
8614 : #endif
8615 0 : Py_RETURN_NONE;
8616 :
8617 : error:
8618 : #ifndef MS_WINDOWS
8619 0 : Py_DECREF(os1);
8620 0 : Py_DECREF(os2);
8621 : #endif
8622 0 : Py_XDECREF(newstr);
8623 0 : return NULL;
8624 : }
8625 : #endif /* putenv */
8626 :
8627 : #ifdef HAVE_UNSETENV
8628 : PyDoc_STRVAR(posix_unsetenv__doc__,
8629 : "unsetenv(key)\n\n\
8630 : Delete an environment variable.");
8631 :
8632 : static PyObject *
8633 0 : posix_unsetenv(PyObject *self, PyObject *args)
8634 : {
8635 : PyObject *name;
8636 : #ifndef HAVE_BROKEN_UNSETENV
8637 : int err;
8638 : #endif
8639 :
8640 0 : if (!PyArg_ParseTuple(args, "O&:unsetenv",
8641 :
8642 : PyUnicode_FSConverter, &name))
8643 0 : return NULL;
8644 :
8645 : #ifdef HAVE_BROKEN_UNSETENV
8646 : unsetenv(PyBytes_AS_STRING(name));
8647 : #else
8648 0 : err = unsetenv(PyBytes_AS_STRING(name));
8649 0 : if (err) {
8650 0 : Py_DECREF(name);
8651 0 : return posix_error();
8652 : }
8653 : #endif
8654 :
8655 : /* Remove the key from posix_putenv_garbage;
8656 : * this will cause it to be collected. This has to
8657 : * happen after the real unsetenv() call because the
8658 : * old value was still accessible until then.
8659 : */
8660 0 : if (PyDict_DelItem(posix_putenv_garbage, name)) {
8661 : /* really not much we can do; just leak */
8662 0 : PyErr_Clear();
8663 : }
8664 0 : Py_DECREF(name);
8665 0 : Py_RETURN_NONE;
8666 : }
8667 : #endif /* unsetenv */
8668 :
8669 : PyDoc_STRVAR(posix_strerror__doc__,
8670 : "strerror(code) -> string\n\n\
8671 : Translate an error code to a message string.");
8672 :
8673 : static PyObject *
8674 0 : posix_strerror(PyObject *self, PyObject *args)
8675 : {
8676 : int code;
8677 : char *message;
8678 0 : if (!PyArg_ParseTuple(args, "i:strerror", &code))
8679 0 : return NULL;
8680 0 : message = strerror(code);
8681 0 : if (message == NULL) {
8682 0 : PyErr_SetString(PyExc_ValueError,
8683 : "strerror() argument out of range");
8684 0 : return NULL;
8685 : }
8686 0 : return PyUnicode_DecodeLocale(message, "surrogateescape");
8687 : }
8688 :
8689 :
8690 : #ifdef HAVE_SYS_WAIT_H
8691 :
8692 : #ifdef WCOREDUMP
8693 : PyDoc_STRVAR(posix_WCOREDUMP__doc__,
8694 : "WCOREDUMP(status) -> bool\n\n\
8695 : Return True if the process returning 'status' was dumped to a core file.");
8696 :
8697 : static PyObject *
8698 0 : posix_WCOREDUMP(PyObject *self, PyObject *args)
8699 : {
8700 : WAIT_TYPE status;
8701 0 : WAIT_STATUS_INT(status) = 0;
8702 :
8703 0 : if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
8704 0 : return NULL;
8705 :
8706 0 : return PyBool_FromLong(WCOREDUMP(status));
8707 : }
8708 : #endif /* WCOREDUMP */
8709 :
8710 : #ifdef WIFCONTINUED
8711 : PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
8712 : "WIFCONTINUED(status) -> bool\n\n\
8713 : Return True if the process returning 'status' was continued from a\n\
8714 : job control stop.");
8715 :
8716 : static PyObject *
8717 0 : posix_WIFCONTINUED(PyObject *self, PyObject *args)
8718 : {
8719 : WAIT_TYPE status;
8720 0 : WAIT_STATUS_INT(status) = 0;
8721 :
8722 0 : if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
8723 0 : return NULL;
8724 :
8725 0 : return PyBool_FromLong(WIFCONTINUED(status));
8726 : }
8727 : #endif /* WIFCONTINUED */
8728 :
8729 : #ifdef WIFSTOPPED
8730 : PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
8731 : "WIFSTOPPED(status) -> bool\n\n\
8732 : Return True if the process returning 'status' was stopped.");
8733 :
8734 : static PyObject *
8735 0 : posix_WIFSTOPPED(PyObject *self, PyObject *args)
8736 : {
8737 : WAIT_TYPE status;
8738 0 : WAIT_STATUS_INT(status) = 0;
8739 :
8740 0 : if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
8741 0 : return NULL;
8742 :
8743 0 : return PyBool_FromLong(WIFSTOPPED(status));
8744 : }
8745 : #endif /* WIFSTOPPED */
8746 :
8747 : #ifdef WIFSIGNALED
8748 : PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
8749 : "WIFSIGNALED(status) -> bool\n\n\
8750 : Return True if the process returning 'status' was terminated by a signal.");
8751 :
8752 : static PyObject *
8753 0 : posix_WIFSIGNALED(PyObject *self, PyObject *args)
8754 : {
8755 : WAIT_TYPE status;
8756 0 : WAIT_STATUS_INT(status) = 0;
8757 :
8758 0 : if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
8759 0 : return NULL;
8760 :
8761 0 : return PyBool_FromLong(WIFSIGNALED(status));
8762 : }
8763 : #endif /* WIFSIGNALED */
8764 :
8765 : #ifdef WIFEXITED
8766 : PyDoc_STRVAR(posix_WIFEXITED__doc__,
8767 : "WIFEXITED(status) -> bool\n\n\
8768 : Return true if the process returning 'status' exited using the exit()\n\
8769 : system call.");
8770 :
8771 : static PyObject *
8772 0 : posix_WIFEXITED(PyObject *self, PyObject *args)
8773 : {
8774 : WAIT_TYPE status;
8775 0 : WAIT_STATUS_INT(status) = 0;
8776 :
8777 0 : if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
8778 0 : return NULL;
8779 :
8780 0 : return PyBool_FromLong(WIFEXITED(status));
8781 : }
8782 : #endif /* WIFEXITED */
8783 :
8784 : #ifdef WEXITSTATUS
8785 : PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
8786 : "WEXITSTATUS(status) -> integer\n\n\
8787 : Return the process return code from 'status'.");
8788 :
8789 : static PyObject *
8790 0 : posix_WEXITSTATUS(PyObject *self, PyObject *args)
8791 : {
8792 : WAIT_TYPE status;
8793 0 : WAIT_STATUS_INT(status) = 0;
8794 :
8795 0 : if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
8796 0 : return NULL;
8797 :
8798 0 : return Py_BuildValue("i", WEXITSTATUS(status));
8799 : }
8800 : #endif /* WEXITSTATUS */
8801 :
8802 : #ifdef WTERMSIG
8803 : PyDoc_STRVAR(posix_WTERMSIG__doc__,
8804 : "WTERMSIG(status) -> integer\n\n\
8805 : Return the signal that terminated the process that provided the 'status'\n\
8806 : value.");
8807 :
8808 : static PyObject *
8809 0 : posix_WTERMSIG(PyObject *self, PyObject *args)
8810 : {
8811 : WAIT_TYPE status;
8812 0 : WAIT_STATUS_INT(status) = 0;
8813 :
8814 0 : if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
8815 0 : return NULL;
8816 :
8817 0 : return Py_BuildValue("i", WTERMSIG(status));
8818 : }
8819 : #endif /* WTERMSIG */
8820 :
8821 : #ifdef WSTOPSIG
8822 : PyDoc_STRVAR(posix_WSTOPSIG__doc__,
8823 : "WSTOPSIG(status) -> integer\n\n\
8824 : Return the signal that stopped the process that provided\n\
8825 : the 'status' value.");
8826 :
8827 : static PyObject *
8828 0 : posix_WSTOPSIG(PyObject *self, PyObject *args)
8829 : {
8830 : WAIT_TYPE status;
8831 0 : WAIT_STATUS_INT(status) = 0;
8832 :
8833 0 : if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
8834 0 : return NULL;
8835 :
8836 0 : return Py_BuildValue("i", WSTOPSIG(status));
8837 : }
8838 : #endif /* WSTOPSIG */
8839 :
8840 : #endif /* HAVE_SYS_WAIT_H */
8841 :
8842 :
8843 : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
8844 : #ifdef _SCO_DS
8845 : /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
8846 : needed definitions in sys/statvfs.h */
8847 : #define _SVID3
8848 : #endif
8849 : #include <sys/statvfs.h>
8850 :
8851 : static PyObject*
8852 0 : _pystatvfs_fromstructstatvfs(struct statvfs st) {
8853 0 : PyObject *v = PyStructSequence_New(&StatVFSResultType);
8854 0 : if (v == NULL)
8855 0 : return NULL;
8856 :
8857 : #if !defined(HAVE_LARGEFILE_SUPPORT)
8858 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
8859 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
8860 : PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
8861 : PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
8862 : PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
8863 : PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
8864 : PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
8865 : PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
8866 : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
8867 : PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
8868 : #else
8869 0 : PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
8870 0 : PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
8871 0 : PyStructSequence_SET_ITEM(v, 2,
8872 : PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
8873 0 : PyStructSequence_SET_ITEM(v, 3,
8874 : PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
8875 0 : PyStructSequence_SET_ITEM(v, 4,
8876 : PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
8877 0 : PyStructSequence_SET_ITEM(v, 5,
8878 : PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
8879 0 : PyStructSequence_SET_ITEM(v, 6,
8880 : PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
8881 0 : PyStructSequence_SET_ITEM(v, 7,
8882 : PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
8883 0 : PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
8884 0 : PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
8885 : #endif
8886 :
8887 0 : return v;
8888 : }
8889 :
8890 : PyDoc_STRVAR(posix_fstatvfs__doc__,
8891 : "fstatvfs(fd) -> statvfs result\n\n\
8892 : Perform an fstatvfs system call on the given fd.\n\
8893 : Equivalent to statvfs(fd).");
8894 :
8895 : static PyObject *
8896 0 : posix_fstatvfs(PyObject *self, PyObject *args)
8897 : {
8898 : int fd, res;
8899 : struct statvfs st;
8900 :
8901 0 : if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
8902 0 : return NULL;
8903 0 : Py_BEGIN_ALLOW_THREADS
8904 0 : res = fstatvfs(fd, &st);
8905 0 : Py_END_ALLOW_THREADS
8906 0 : if (res != 0)
8907 0 : return posix_error();
8908 :
8909 0 : return _pystatvfs_fromstructstatvfs(st);
8910 : }
8911 : #endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
8912 :
8913 :
8914 : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
8915 : #include <sys/statvfs.h>
8916 :
8917 : PyDoc_STRVAR(posix_statvfs__doc__,
8918 : "statvfs(path)\n\n\
8919 : Perform a statvfs system call on the given path.\n\
8920 : \n\
8921 : path may always be specified as a string.\n\
8922 : On some platforms, path may also be specified as an open file descriptor.\n\
8923 : If this functionality is unavailable, using it raises an exception.");
8924 :
8925 : static PyObject *
8926 0 : posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs)
8927 : {
8928 : static char *keywords[] = {"path", NULL};
8929 : path_t path;
8930 : int result;
8931 0 : PyObject *return_value = NULL;
8932 : struct statvfs st;
8933 :
8934 0 : memset(&path, 0, sizeof(path));
8935 : #ifdef HAVE_FSTATVFS
8936 0 : path.allow_fd = 1;
8937 : #endif
8938 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords,
8939 : path_converter, &path
8940 : ))
8941 0 : return NULL;
8942 :
8943 0 : Py_BEGIN_ALLOW_THREADS
8944 : #ifdef HAVE_FSTATVFS
8945 0 : if (path.fd != -1) {
8946 : #ifdef __APPLE__
8947 : /* handle weak-linking on Mac OS X 10.3 */
8948 : if (fstatvfs == NULL) {
8949 : fd_specified("statvfs", path.fd);
8950 : goto exit;
8951 : }
8952 : #endif
8953 0 : result = fstatvfs(path.fd, &st);
8954 : }
8955 : else
8956 : #endif
8957 0 : result = statvfs(path.narrow, &st);
8958 0 : Py_END_ALLOW_THREADS
8959 :
8960 0 : if (result) {
8961 0 : return_value = path_posix_error("statvfs", &path);
8962 0 : goto exit;
8963 : }
8964 :
8965 0 : return_value = _pystatvfs_fromstructstatvfs(st);
8966 :
8967 : exit:
8968 0 : path_cleanup(&path);
8969 0 : return return_value;
8970 : }
8971 : #endif /* HAVE_STATVFS */
8972 :
8973 : #ifdef MS_WINDOWS
8974 : PyDoc_STRVAR(win32__getdiskusage__doc__,
8975 : "_getdiskusage(path) -> (total, free)\n\n\
8976 : Return disk usage statistics about the given path as (total, free) tuple.");
8977 :
8978 : static PyObject *
8979 : win32__getdiskusage(PyObject *self, PyObject *args)
8980 : {
8981 : BOOL retval;
8982 : ULARGE_INTEGER _, total, free;
8983 : const wchar_t *path;
8984 :
8985 : if (! PyArg_ParseTuple(args, "u", &path))
8986 : return NULL;
8987 :
8988 : Py_BEGIN_ALLOW_THREADS
8989 : retval = GetDiskFreeSpaceExW(path, &_, &total, &free);
8990 : Py_END_ALLOW_THREADS
8991 : if (retval == 0)
8992 : return PyErr_SetFromWindowsErr(0);
8993 :
8994 : return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
8995 : }
8996 : #endif
8997 :
8998 :
8999 : /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
9000 : * It maps strings representing configuration variable names to
9001 : * integer values, allowing those functions to be called with the
9002 : * magic names instead of polluting the module's namespace with tons of
9003 : * rarely-used constants. There are three separate tables that use
9004 : * these definitions.
9005 : *
9006 : * This code is always included, even if none of the interfaces that
9007 : * need it are included. The #if hackery needed to avoid it would be
9008 : * sufficiently pervasive that it's not worth the loss of readability.
9009 : */
9010 : struct constdef {
9011 : char *name;
9012 : long value;
9013 : };
9014 :
9015 : static int
9016 0 : conv_confname(PyObject *arg, int *valuep, struct constdef *table,
9017 : size_t tablesize)
9018 : {
9019 0 : if (PyLong_Check(arg)) {
9020 0 : *valuep = PyLong_AS_LONG(arg);
9021 0 : return 1;
9022 : }
9023 : else {
9024 : /* look up the value in the table using a binary search */
9025 0 : size_t lo = 0;
9026 : size_t mid;
9027 0 : size_t hi = tablesize;
9028 : int cmp;
9029 : const char *confname;
9030 0 : if (!PyUnicode_Check(arg)) {
9031 0 : PyErr_SetString(PyExc_TypeError,
9032 : "configuration names must be strings or integers");
9033 0 : return 0;
9034 : }
9035 0 : confname = _PyUnicode_AsString(arg);
9036 0 : if (confname == NULL)
9037 0 : return 0;
9038 0 : while (lo < hi) {
9039 0 : mid = (lo + hi) / 2;
9040 0 : cmp = strcmp(confname, table[mid].name);
9041 0 : if (cmp < 0)
9042 0 : hi = mid;
9043 0 : else if (cmp > 0)
9044 0 : lo = mid + 1;
9045 : else {
9046 0 : *valuep = table[mid].value;
9047 0 : return 1;
9048 : }
9049 : }
9050 0 : PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
9051 0 : return 0;
9052 : }
9053 : }
9054 :
9055 :
9056 : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
9057 : static struct constdef posix_constants_pathconf[] = {
9058 : #ifdef _PC_ABI_AIO_XFER_MAX
9059 : {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX},
9060 : #endif
9061 : #ifdef _PC_ABI_ASYNC_IO
9062 : {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
9063 : #endif
9064 : #ifdef _PC_ASYNC_IO
9065 : {"PC_ASYNC_IO", _PC_ASYNC_IO},
9066 : #endif
9067 : #ifdef _PC_CHOWN_RESTRICTED
9068 : {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED},
9069 : #endif
9070 : #ifdef _PC_FILESIZEBITS
9071 : {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
9072 : #endif
9073 : #ifdef _PC_LAST
9074 : {"PC_LAST", _PC_LAST},
9075 : #endif
9076 : #ifdef _PC_LINK_MAX
9077 : {"PC_LINK_MAX", _PC_LINK_MAX},
9078 : #endif
9079 : #ifdef _PC_MAX_CANON
9080 : {"PC_MAX_CANON", _PC_MAX_CANON},
9081 : #endif
9082 : #ifdef _PC_MAX_INPUT
9083 : {"PC_MAX_INPUT", _PC_MAX_INPUT},
9084 : #endif
9085 : #ifdef _PC_NAME_MAX
9086 : {"PC_NAME_MAX", _PC_NAME_MAX},
9087 : #endif
9088 : #ifdef _PC_NO_TRUNC
9089 : {"PC_NO_TRUNC", _PC_NO_TRUNC},
9090 : #endif
9091 : #ifdef _PC_PATH_MAX
9092 : {"PC_PATH_MAX", _PC_PATH_MAX},
9093 : #endif
9094 : #ifdef _PC_PIPE_BUF
9095 : {"PC_PIPE_BUF", _PC_PIPE_BUF},
9096 : #endif
9097 : #ifdef _PC_PRIO_IO
9098 : {"PC_PRIO_IO", _PC_PRIO_IO},
9099 : #endif
9100 : #ifdef _PC_SOCK_MAXBUF
9101 : {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF},
9102 : #endif
9103 : #ifdef _PC_SYNC_IO
9104 : {"PC_SYNC_IO", _PC_SYNC_IO},
9105 : #endif
9106 : #ifdef _PC_VDISABLE
9107 : {"PC_VDISABLE", _PC_VDISABLE},
9108 : #endif
9109 : #ifdef _PC_ACL_ENABLED
9110 : {"PC_ACL_ENABLED", _PC_ACL_ENABLED},
9111 : #endif
9112 : #ifdef _PC_MIN_HOLE_SIZE
9113 : {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE},
9114 : #endif
9115 : #ifdef _PC_ALLOC_SIZE_MIN
9116 : {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN},
9117 : #endif
9118 : #ifdef _PC_REC_INCR_XFER_SIZE
9119 : {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE},
9120 : #endif
9121 : #ifdef _PC_REC_MAX_XFER_SIZE
9122 : {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE},
9123 : #endif
9124 : #ifdef _PC_REC_MIN_XFER_SIZE
9125 : {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE},
9126 : #endif
9127 : #ifdef _PC_REC_XFER_ALIGN
9128 : {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN},
9129 : #endif
9130 : #ifdef _PC_SYMLINK_MAX
9131 : {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX},
9132 : #endif
9133 : #ifdef _PC_XATTR_ENABLED
9134 : {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED},
9135 : #endif
9136 : #ifdef _PC_XATTR_EXISTS
9137 : {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
9138 : #endif
9139 : #ifdef _PC_TIMESTAMP_RESOLUTION
9140 : {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
9141 : #endif
9142 : };
9143 :
9144 : static int
9145 0 : conv_path_confname(PyObject *arg, int *valuep)
9146 : {
9147 0 : return conv_confname(arg, valuep, posix_constants_pathconf,
9148 : sizeof(posix_constants_pathconf)
9149 : / sizeof(struct constdef));
9150 : }
9151 : #endif
9152 :
9153 : #ifdef HAVE_FPATHCONF
9154 : PyDoc_STRVAR(posix_fpathconf__doc__,
9155 : "fpathconf(fd, name) -> integer\n\n\
9156 : Return the configuration limit name for the file descriptor fd.\n\
9157 : If there is no limit, return -1.");
9158 :
9159 : static PyObject *
9160 0 : posix_fpathconf(PyObject *self, PyObject *args)
9161 : {
9162 0 : PyObject *result = NULL;
9163 : int name, fd;
9164 :
9165 0 : if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
9166 : conv_path_confname, &name)) {
9167 : long limit;
9168 :
9169 0 : errno = 0;
9170 0 : limit = fpathconf(fd, name);
9171 0 : if (limit == -1 && errno != 0)
9172 0 : posix_error();
9173 : else
9174 0 : result = PyLong_FromLong(limit);
9175 : }
9176 0 : return result;
9177 : }
9178 : #endif
9179 :
9180 :
9181 : #ifdef HAVE_PATHCONF
9182 : PyDoc_STRVAR(posix_pathconf__doc__,
9183 : "pathconf(path, name) -> integer\n\n\
9184 : Return the configuration limit name for the file or directory path.\n\
9185 : If there is no limit, return -1.\n\
9186 : On some platforms, path may also be specified as an open file descriptor.\n\
9187 : If this functionality is unavailable, using it raises an exception.");
9188 :
9189 : static PyObject *
9190 0 : posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs)
9191 : {
9192 : path_t path;
9193 0 : PyObject *result = NULL;
9194 : int name;
9195 : static char *keywords[] = {"path", "name", NULL};
9196 :
9197 0 : memset(&path, 0, sizeof(path));
9198 : #ifdef HAVE_FPATHCONF
9199 0 : path.allow_fd = 1;
9200 : #endif
9201 0 : if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords,
9202 : path_converter, &path,
9203 : conv_path_confname, &name)) {
9204 : long limit;
9205 :
9206 0 : errno = 0;
9207 : #ifdef HAVE_FPATHCONF
9208 0 : if (path.fd != -1)
9209 0 : limit = fpathconf(path.fd, name);
9210 : else
9211 : #endif
9212 0 : limit = pathconf(path.narrow, name);
9213 0 : if (limit == -1 && errno != 0) {
9214 0 : if (errno == EINVAL)
9215 : /* could be a path or name problem */
9216 0 : posix_error();
9217 : else
9218 0 : result = path_posix_error("pathconf", &path);
9219 : }
9220 : else
9221 0 : result = PyLong_FromLong(limit);
9222 : }
9223 0 : path_cleanup(&path);
9224 0 : return result;
9225 : }
9226 : #endif
9227 :
9228 : #ifdef HAVE_CONFSTR
9229 : static struct constdef posix_constants_confstr[] = {
9230 : #ifdef _CS_ARCHITECTURE
9231 : {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
9232 : #endif
9233 : #ifdef _CS_GNU_LIBC_VERSION
9234 : {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION},
9235 : #endif
9236 : #ifdef _CS_GNU_LIBPTHREAD_VERSION
9237 : {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION},
9238 : #endif
9239 : #ifdef _CS_HOSTNAME
9240 : {"CS_HOSTNAME", _CS_HOSTNAME},
9241 : #endif
9242 : #ifdef _CS_HW_PROVIDER
9243 : {"CS_HW_PROVIDER", _CS_HW_PROVIDER},
9244 : #endif
9245 : #ifdef _CS_HW_SERIAL
9246 : {"CS_HW_SERIAL", _CS_HW_SERIAL},
9247 : #endif
9248 : #ifdef _CS_INITTAB_NAME
9249 : {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
9250 : #endif
9251 : #ifdef _CS_LFS64_CFLAGS
9252 : {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
9253 : #endif
9254 : #ifdef _CS_LFS64_LDFLAGS
9255 : {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS},
9256 : #endif
9257 : #ifdef _CS_LFS64_LIBS
9258 : {"CS_LFS64_LIBS", _CS_LFS64_LIBS},
9259 : #endif
9260 : #ifdef _CS_LFS64_LINTFLAGS
9261 : {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS},
9262 : #endif
9263 : #ifdef _CS_LFS_CFLAGS
9264 : {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS},
9265 : #endif
9266 : #ifdef _CS_LFS_LDFLAGS
9267 : {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS},
9268 : #endif
9269 : #ifdef _CS_LFS_LIBS
9270 : {"CS_LFS_LIBS", _CS_LFS_LIBS},
9271 : #endif
9272 : #ifdef _CS_LFS_LINTFLAGS
9273 : {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS},
9274 : #endif
9275 : #ifdef _CS_MACHINE
9276 : {"CS_MACHINE", _CS_MACHINE},
9277 : #endif
9278 : #ifdef _CS_PATH
9279 : {"CS_PATH", _CS_PATH},
9280 : #endif
9281 : #ifdef _CS_RELEASE
9282 : {"CS_RELEASE", _CS_RELEASE},
9283 : #endif
9284 : #ifdef _CS_SRPC_DOMAIN
9285 : {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN},
9286 : #endif
9287 : #ifdef _CS_SYSNAME
9288 : {"CS_SYSNAME", _CS_SYSNAME},
9289 : #endif
9290 : #ifdef _CS_VERSION
9291 : {"CS_VERSION", _CS_VERSION},
9292 : #endif
9293 : #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
9294 : {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS},
9295 : #endif
9296 : #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
9297 : {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS},
9298 : #endif
9299 : #ifdef _CS_XBS5_ILP32_OFF32_LIBS
9300 : {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS},
9301 : #endif
9302 : #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
9303 : {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS},
9304 : #endif
9305 : #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
9306 : {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS},
9307 : #endif
9308 : #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
9309 : {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
9310 : #endif
9311 : #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
9312 : {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS},
9313 : #endif
9314 : #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
9315 : {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
9316 : #endif
9317 : #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
9318 : {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS},
9319 : #endif
9320 : #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
9321 : {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS},
9322 : #endif
9323 : #ifdef _CS_XBS5_LP64_OFF64_LIBS
9324 : {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
9325 : #endif
9326 : #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
9327 : {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS},
9328 : #endif
9329 : #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
9330 : {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
9331 : #endif
9332 : #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
9333 : {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
9334 : #endif
9335 : #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
9336 : {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS},
9337 : #endif
9338 : #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
9339 : {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
9340 : #endif
9341 : #ifdef _MIPS_CS_AVAIL_PROCESSORS
9342 : {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS},
9343 : #endif
9344 : #ifdef _MIPS_CS_BASE
9345 : {"MIPS_CS_BASE", _MIPS_CS_BASE},
9346 : #endif
9347 : #ifdef _MIPS_CS_HOSTID
9348 : {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID},
9349 : #endif
9350 : #ifdef _MIPS_CS_HW_NAME
9351 : {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
9352 : #endif
9353 : #ifdef _MIPS_CS_NUM_PROCESSORS
9354 : {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS},
9355 : #endif
9356 : #ifdef _MIPS_CS_OSREL_MAJ
9357 : {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ},
9358 : #endif
9359 : #ifdef _MIPS_CS_OSREL_MIN
9360 : {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN},
9361 : #endif
9362 : #ifdef _MIPS_CS_OSREL_PATCH
9363 : {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH},
9364 : #endif
9365 : #ifdef _MIPS_CS_OS_NAME
9366 : {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
9367 : #endif
9368 : #ifdef _MIPS_CS_OS_PROVIDER
9369 : {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER},
9370 : #endif
9371 : #ifdef _MIPS_CS_PROCESSORS
9372 : {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS},
9373 : #endif
9374 : #ifdef _MIPS_CS_SERIAL
9375 : {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL},
9376 : #endif
9377 : #ifdef _MIPS_CS_VENDOR
9378 : {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR},
9379 : #endif
9380 : };
9381 :
9382 : static int
9383 0 : conv_confstr_confname(PyObject *arg, int *valuep)
9384 : {
9385 0 : return conv_confname(arg, valuep, posix_constants_confstr,
9386 : sizeof(posix_constants_confstr)
9387 : / sizeof(struct constdef));
9388 : }
9389 :
9390 : PyDoc_STRVAR(posix_confstr__doc__,
9391 : "confstr(name) -> string\n\n\
9392 : Return a string-valued system configuration variable.");
9393 :
9394 : static PyObject *
9395 0 : posix_confstr(PyObject *self, PyObject *args)
9396 : {
9397 0 : PyObject *result = NULL;
9398 : int name;
9399 : char buffer[255];
9400 : int len;
9401 :
9402 0 : if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
9403 0 : return NULL;
9404 :
9405 0 : errno = 0;
9406 0 : len = confstr(name, buffer, sizeof(buffer));
9407 0 : if (len == 0) {
9408 0 : if (errno) {
9409 0 : posix_error();
9410 0 : return NULL;
9411 : }
9412 : else {
9413 0 : Py_RETURN_NONE;
9414 : }
9415 : }
9416 :
9417 0 : if ((unsigned int)len >= sizeof(buffer)) {
9418 0 : char *buf = PyMem_Malloc(len);
9419 0 : if (buf == NULL)
9420 0 : return PyErr_NoMemory();
9421 0 : confstr(name, buf, len);
9422 0 : result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
9423 0 : PyMem_Free(buf);
9424 : }
9425 : else
9426 0 : result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
9427 0 : return result;
9428 : }
9429 : #endif
9430 :
9431 :
9432 : #ifdef HAVE_SYSCONF
9433 : static struct constdef posix_constants_sysconf[] = {
9434 : #ifdef _SC_2_CHAR_TERM
9435 : {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM},
9436 : #endif
9437 : #ifdef _SC_2_C_BIND
9438 : {"SC_2_C_BIND", _SC_2_C_BIND},
9439 : #endif
9440 : #ifdef _SC_2_C_DEV
9441 : {"SC_2_C_DEV", _SC_2_C_DEV},
9442 : #endif
9443 : #ifdef _SC_2_C_VERSION
9444 : {"SC_2_C_VERSION", _SC_2_C_VERSION},
9445 : #endif
9446 : #ifdef _SC_2_FORT_DEV
9447 : {"SC_2_FORT_DEV", _SC_2_FORT_DEV},
9448 : #endif
9449 : #ifdef _SC_2_FORT_RUN
9450 : {"SC_2_FORT_RUN", _SC_2_FORT_RUN},
9451 : #endif
9452 : #ifdef _SC_2_LOCALEDEF
9453 : {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF},
9454 : #endif
9455 : #ifdef _SC_2_SW_DEV
9456 : {"SC_2_SW_DEV", _SC_2_SW_DEV},
9457 : #endif
9458 : #ifdef _SC_2_UPE
9459 : {"SC_2_UPE", _SC_2_UPE},
9460 : #endif
9461 : #ifdef _SC_2_VERSION
9462 : {"SC_2_VERSION", _SC_2_VERSION},
9463 : #endif
9464 : #ifdef _SC_ABI_ASYNCHRONOUS_IO
9465 : {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO},
9466 : #endif
9467 : #ifdef _SC_ACL
9468 : {"SC_ACL", _SC_ACL},
9469 : #endif
9470 : #ifdef _SC_AIO_LISTIO_MAX
9471 : {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX},
9472 : #endif
9473 : #ifdef _SC_AIO_MAX
9474 : {"SC_AIO_MAX", _SC_AIO_MAX},
9475 : #endif
9476 : #ifdef _SC_AIO_PRIO_DELTA_MAX
9477 : {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX},
9478 : #endif
9479 : #ifdef _SC_ARG_MAX
9480 : {"SC_ARG_MAX", _SC_ARG_MAX},
9481 : #endif
9482 : #ifdef _SC_ASYNCHRONOUS_IO
9483 : {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO},
9484 : #endif
9485 : #ifdef _SC_ATEXIT_MAX
9486 : {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX},
9487 : #endif
9488 : #ifdef _SC_AUDIT
9489 : {"SC_AUDIT", _SC_AUDIT},
9490 : #endif
9491 : #ifdef _SC_AVPHYS_PAGES
9492 : {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
9493 : #endif
9494 : #ifdef _SC_BC_BASE_MAX
9495 : {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX},
9496 : #endif
9497 : #ifdef _SC_BC_DIM_MAX
9498 : {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX},
9499 : #endif
9500 : #ifdef _SC_BC_SCALE_MAX
9501 : {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
9502 : #endif
9503 : #ifdef _SC_BC_STRING_MAX
9504 : {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX},
9505 : #endif
9506 : #ifdef _SC_CAP
9507 : {"SC_CAP", _SC_CAP},
9508 : #endif
9509 : #ifdef _SC_CHARCLASS_NAME_MAX
9510 : {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX},
9511 : #endif
9512 : #ifdef _SC_CHAR_BIT
9513 : {"SC_CHAR_BIT", _SC_CHAR_BIT},
9514 : #endif
9515 : #ifdef _SC_CHAR_MAX
9516 : {"SC_CHAR_MAX", _SC_CHAR_MAX},
9517 : #endif
9518 : #ifdef _SC_CHAR_MIN
9519 : {"SC_CHAR_MIN", _SC_CHAR_MIN},
9520 : #endif
9521 : #ifdef _SC_CHILD_MAX
9522 : {"SC_CHILD_MAX", _SC_CHILD_MAX},
9523 : #endif
9524 : #ifdef _SC_CLK_TCK
9525 : {"SC_CLK_TCK", _SC_CLK_TCK},
9526 : #endif
9527 : #ifdef _SC_COHER_BLKSZ
9528 : {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ},
9529 : #endif
9530 : #ifdef _SC_COLL_WEIGHTS_MAX
9531 : {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX},
9532 : #endif
9533 : #ifdef _SC_DCACHE_ASSOC
9534 : {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
9535 : #endif
9536 : #ifdef _SC_DCACHE_BLKSZ
9537 : {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
9538 : #endif
9539 : #ifdef _SC_DCACHE_LINESZ
9540 : {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ},
9541 : #endif
9542 : #ifdef _SC_DCACHE_SZ
9543 : {"SC_DCACHE_SZ", _SC_DCACHE_SZ},
9544 : #endif
9545 : #ifdef _SC_DCACHE_TBLKSZ
9546 : {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ},
9547 : #endif
9548 : #ifdef _SC_DELAYTIMER_MAX
9549 : {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX},
9550 : #endif
9551 : #ifdef _SC_EQUIV_CLASS_MAX
9552 : {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX},
9553 : #endif
9554 : #ifdef _SC_EXPR_NEST_MAX
9555 : {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX},
9556 : #endif
9557 : #ifdef _SC_FSYNC
9558 : {"SC_FSYNC", _SC_FSYNC},
9559 : #endif
9560 : #ifdef _SC_GETGR_R_SIZE_MAX
9561 : {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX},
9562 : #endif
9563 : #ifdef _SC_GETPW_R_SIZE_MAX
9564 : {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX},
9565 : #endif
9566 : #ifdef _SC_ICACHE_ASSOC
9567 : {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
9568 : #endif
9569 : #ifdef _SC_ICACHE_BLKSZ
9570 : {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
9571 : #endif
9572 : #ifdef _SC_ICACHE_LINESZ
9573 : {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ},
9574 : #endif
9575 : #ifdef _SC_ICACHE_SZ
9576 : {"SC_ICACHE_SZ", _SC_ICACHE_SZ},
9577 : #endif
9578 : #ifdef _SC_INF
9579 : {"SC_INF", _SC_INF},
9580 : #endif
9581 : #ifdef _SC_INT_MAX
9582 : {"SC_INT_MAX", _SC_INT_MAX},
9583 : #endif
9584 : #ifdef _SC_INT_MIN
9585 : {"SC_INT_MIN", _SC_INT_MIN},
9586 : #endif
9587 : #ifdef _SC_IOV_MAX
9588 : {"SC_IOV_MAX", _SC_IOV_MAX},
9589 : #endif
9590 : #ifdef _SC_IP_SECOPTS
9591 : {"SC_IP_SECOPTS", _SC_IP_SECOPTS},
9592 : #endif
9593 : #ifdef _SC_JOB_CONTROL
9594 : {"SC_JOB_CONTROL", _SC_JOB_CONTROL},
9595 : #endif
9596 : #ifdef _SC_KERN_POINTERS
9597 : {"SC_KERN_POINTERS", _SC_KERN_POINTERS},
9598 : #endif
9599 : #ifdef _SC_KERN_SIM
9600 : {"SC_KERN_SIM", _SC_KERN_SIM},
9601 : #endif
9602 : #ifdef _SC_LINE_MAX
9603 : {"SC_LINE_MAX", _SC_LINE_MAX},
9604 : #endif
9605 : #ifdef _SC_LOGIN_NAME_MAX
9606 : {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX},
9607 : #endif
9608 : #ifdef _SC_LOGNAME_MAX
9609 : {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX},
9610 : #endif
9611 : #ifdef _SC_LONG_BIT
9612 : {"SC_LONG_BIT", _SC_LONG_BIT},
9613 : #endif
9614 : #ifdef _SC_MAC
9615 : {"SC_MAC", _SC_MAC},
9616 : #endif
9617 : #ifdef _SC_MAPPED_FILES
9618 : {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
9619 : #endif
9620 : #ifdef _SC_MAXPID
9621 : {"SC_MAXPID", _SC_MAXPID},
9622 : #endif
9623 : #ifdef _SC_MB_LEN_MAX
9624 : {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX},
9625 : #endif
9626 : #ifdef _SC_MEMLOCK
9627 : {"SC_MEMLOCK", _SC_MEMLOCK},
9628 : #endif
9629 : #ifdef _SC_MEMLOCK_RANGE
9630 : {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE},
9631 : #endif
9632 : #ifdef _SC_MEMORY_PROTECTION
9633 : {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION},
9634 : #endif
9635 : #ifdef _SC_MESSAGE_PASSING
9636 : {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING},
9637 : #endif
9638 : #ifdef _SC_MMAP_FIXED_ALIGNMENT
9639 : {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
9640 : #endif
9641 : #ifdef _SC_MQ_OPEN_MAX
9642 : {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX},
9643 : #endif
9644 : #ifdef _SC_MQ_PRIO_MAX
9645 : {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX},
9646 : #endif
9647 : #ifdef _SC_NACLS_MAX
9648 : {"SC_NACLS_MAX", _SC_NACLS_MAX},
9649 : #endif
9650 : #ifdef _SC_NGROUPS_MAX
9651 : {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX},
9652 : #endif
9653 : #ifdef _SC_NL_ARGMAX
9654 : {"SC_NL_ARGMAX", _SC_NL_ARGMAX},
9655 : #endif
9656 : #ifdef _SC_NL_LANGMAX
9657 : {"SC_NL_LANGMAX", _SC_NL_LANGMAX},
9658 : #endif
9659 : #ifdef _SC_NL_MSGMAX
9660 : {"SC_NL_MSGMAX", _SC_NL_MSGMAX},
9661 : #endif
9662 : #ifdef _SC_NL_NMAX
9663 : {"SC_NL_NMAX", _SC_NL_NMAX},
9664 : #endif
9665 : #ifdef _SC_NL_SETMAX
9666 : {"SC_NL_SETMAX", _SC_NL_SETMAX},
9667 : #endif
9668 : #ifdef _SC_NL_TEXTMAX
9669 : {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX},
9670 : #endif
9671 : #ifdef _SC_NPROCESSORS_CONF
9672 : {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF},
9673 : #endif
9674 : #ifdef _SC_NPROCESSORS_ONLN
9675 : {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN},
9676 : #endif
9677 : #ifdef _SC_NPROC_CONF
9678 : {"SC_NPROC_CONF", _SC_NPROC_CONF},
9679 : #endif
9680 : #ifdef _SC_NPROC_ONLN
9681 : {"SC_NPROC_ONLN", _SC_NPROC_ONLN},
9682 : #endif
9683 : #ifdef _SC_NZERO
9684 : {"SC_NZERO", _SC_NZERO},
9685 : #endif
9686 : #ifdef _SC_OPEN_MAX
9687 : {"SC_OPEN_MAX", _SC_OPEN_MAX},
9688 : #endif
9689 : #ifdef _SC_PAGESIZE
9690 : {"SC_PAGESIZE", _SC_PAGESIZE},
9691 : #endif
9692 : #ifdef _SC_PAGE_SIZE
9693 : {"SC_PAGE_SIZE", _SC_PAGE_SIZE},
9694 : #endif
9695 : #ifdef _SC_PASS_MAX
9696 : {"SC_PASS_MAX", _SC_PASS_MAX},
9697 : #endif
9698 : #ifdef _SC_PHYS_PAGES
9699 : {"SC_PHYS_PAGES", _SC_PHYS_PAGES},
9700 : #endif
9701 : #ifdef _SC_PII
9702 : {"SC_PII", _SC_PII},
9703 : #endif
9704 : #ifdef _SC_PII_INTERNET
9705 : {"SC_PII_INTERNET", _SC_PII_INTERNET},
9706 : #endif
9707 : #ifdef _SC_PII_INTERNET_DGRAM
9708 : {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM},
9709 : #endif
9710 : #ifdef _SC_PII_INTERNET_STREAM
9711 : {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM},
9712 : #endif
9713 : #ifdef _SC_PII_OSI
9714 : {"SC_PII_OSI", _SC_PII_OSI},
9715 : #endif
9716 : #ifdef _SC_PII_OSI_CLTS
9717 : {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
9718 : #endif
9719 : #ifdef _SC_PII_OSI_COTS
9720 : {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
9721 : #endif
9722 : #ifdef _SC_PII_OSI_M
9723 : {"SC_PII_OSI_M", _SC_PII_OSI_M},
9724 : #endif
9725 : #ifdef _SC_PII_SOCKET
9726 : {"SC_PII_SOCKET", _SC_PII_SOCKET},
9727 : #endif
9728 : #ifdef _SC_PII_XTI
9729 : {"SC_PII_XTI", _SC_PII_XTI},
9730 : #endif
9731 : #ifdef _SC_POLL
9732 : {"SC_POLL", _SC_POLL},
9733 : #endif
9734 : #ifdef _SC_PRIORITIZED_IO
9735 : {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO},
9736 : #endif
9737 : #ifdef _SC_PRIORITY_SCHEDULING
9738 : {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING},
9739 : #endif
9740 : #ifdef _SC_REALTIME_SIGNALS
9741 : {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS},
9742 : #endif
9743 : #ifdef _SC_RE_DUP_MAX
9744 : {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX},
9745 : #endif
9746 : #ifdef _SC_RTSIG_MAX
9747 : {"SC_RTSIG_MAX", _SC_RTSIG_MAX},
9748 : #endif
9749 : #ifdef _SC_SAVED_IDS
9750 : {"SC_SAVED_IDS", _SC_SAVED_IDS},
9751 : #endif
9752 : #ifdef _SC_SCHAR_MAX
9753 : {"SC_SCHAR_MAX", _SC_SCHAR_MAX},
9754 : #endif
9755 : #ifdef _SC_SCHAR_MIN
9756 : {"SC_SCHAR_MIN", _SC_SCHAR_MIN},
9757 : #endif
9758 : #ifdef _SC_SELECT
9759 : {"SC_SELECT", _SC_SELECT},
9760 : #endif
9761 : #ifdef _SC_SEMAPHORES
9762 : {"SC_SEMAPHORES", _SC_SEMAPHORES},
9763 : #endif
9764 : #ifdef _SC_SEM_NSEMS_MAX
9765 : {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX},
9766 : #endif
9767 : #ifdef _SC_SEM_VALUE_MAX
9768 : {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX},
9769 : #endif
9770 : #ifdef _SC_SHARED_MEMORY_OBJECTS
9771 : {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS},
9772 : #endif
9773 : #ifdef _SC_SHRT_MAX
9774 : {"SC_SHRT_MAX", _SC_SHRT_MAX},
9775 : #endif
9776 : #ifdef _SC_SHRT_MIN
9777 : {"SC_SHRT_MIN", _SC_SHRT_MIN},
9778 : #endif
9779 : #ifdef _SC_SIGQUEUE_MAX
9780 : {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
9781 : #endif
9782 : #ifdef _SC_SIGRT_MAX
9783 : {"SC_SIGRT_MAX", _SC_SIGRT_MAX},
9784 : #endif
9785 : #ifdef _SC_SIGRT_MIN
9786 : {"SC_SIGRT_MIN", _SC_SIGRT_MIN},
9787 : #endif
9788 : #ifdef _SC_SOFTPOWER
9789 : {"SC_SOFTPOWER", _SC_SOFTPOWER},
9790 : #endif
9791 : #ifdef _SC_SPLIT_CACHE
9792 : {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE},
9793 : #endif
9794 : #ifdef _SC_SSIZE_MAX
9795 : {"SC_SSIZE_MAX", _SC_SSIZE_MAX},
9796 : #endif
9797 : #ifdef _SC_STACK_PROT
9798 : {"SC_STACK_PROT", _SC_STACK_PROT},
9799 : #endif
9800 : #ifdef _SC_STREAM_MAX
9801 : {"SC_STREAM_MAX", _SC_STREAM_MAX},
9802 : #endif
9803 : #ifdef _SC_SYNCHRONIZED_IO
9804 : {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO},
9805 : #endif
9806 : #ifdef _SC_THREADS
9807 : {"SC_THREADS", _SC_THREADS},
9808 : #endif
9809 : #ifdef _SC_THREAD_ATTR_STACKADDR
9810 : {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR},
9811 : #endif
9812 : #ifdef _SC_THREAD_ATTR_STACKSIZE
9813 : {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE},
9814 : #endif
9815 : #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
9816 : {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
9817 : #endif
9818 : #ifdef _SC_THREAD_KEYS_MAX
9819 : {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX},
9820 : #endif
9821 : #ifdef _SC_THREAD_PRIORITY_SCHEDULING
9822 : {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING},
9823 : #endif
9824 : #ifdef _SC_THREAD_PRIO_INHERIT
9825 : {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT},
9826 : #endif
9827 : #ifdef _SC_THREAD_PRIO_PROTECT
9828 : {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT},
9829 : #endif
9830 : #ifdef _SC_THREAD_PROCESS_SHARED
9831 : {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED},
9832 : #endif
9833 : #ifdef _SC_THREAD_SAFE_FUNCTIONS
9834 : {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS},
9835 : #endif
9836 : #ifdef _SC_THREAD_STACK_MIN
9837 : {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN},
9838 : #endif
9839 : #ifdef _SC_THREAD_THREADS_MAX
9840 : {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX},
9841 : #endif
9842 : #ifdef _SC_TIMERS
9843 : {"SC_TIMERS", _SC_TIMERS},
9844 : #endif
9845 : #ifdef _SC_TIMER_MAX
9846 : {"SC_TIMER_MAX", _SC_TIMER_MAX},
9847 : #endif
9848 : #ifdef _SC_TTY_NAME_MAX
9849 : {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
9850 : #endif
9851 : #ifdef _SC_TZNAME_MAX
9852 : {"SC_TZNAME_MAX", _SC_TZNAME_MAX},
9853 : #endif
9854 : #ifdef _SC_T_IOV_MAX
9855 : {"SC_T_IOV_MAX", _SC_T_IOV_MAX},
9856 : #endif
9857 : #ifdef _SC_UCHAR_MAX
9858 : {"SC_UCHAR_MAX", _SC_UCHAR_MAX},
9859 : #endif
9860 : #ifdef _SC_UINT_MAX
9861 : {"SC_UINT_MAX", _SC_UINT_MAX},
9862 : #endif
9863 : #ifdef _SC_UIO_MAXIOV
9864 : {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV},
9865 : #endif
9866 : #ifdef _SC_ULONG_MAX
9867 : {"SC_ULONG_MAX", _SC_ULONG_MAX},
9868 : #endif
9869 : #ifdef _SC_USHRT_MAX
9870 : {"SC_USHRT_MAX", _SC_USHRT_MAX},
9871 : #endif
9872 : #ifdef _SC_VERSION
9873 : {"SC_VERSION", _SC_VERSION},
9874 : #endif
9875 : #ifdef _SC_WORD_BIT
9876 : {"SC_WORD_BIT", _SC_WORD_BIT},
9877 : #endif
9878 : #ifdef _SC_XBS5_ILP32_OFF32
9879 : {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32},
9880 : #endif
9881 : #ifdef _SC_XBS5_ILP32_OFFBIG
9882 : {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG},
9883 : #endif
9884 : #ifdef _SC_XBS5_LP64_OFF64
9885 : {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64},
9886 : #endif
9887 : #ifdef _SC_XBS5_LPBIG_OFFBIG
9888 : {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG},
9889 : #endif
9890 : #ifdef _SC_XOPEN_CRYPT
9891 : {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT},
9892 : #endif
9893 : #ifdef _SC_XOPEN_ENH_I18N
9894 : {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N},
9895 : #endif
9896 : #ifdef _SC_XOPEN_LEGACY
9897 : {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
9898 : #endif
9899 : #ifdef _SC_XOPEN_REALTIME
9900 : {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME},
9901 : #endif
9902 : #ifdef _SC_XOPEN_REALTIME_THREADS
9903 : {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS},
9904 : #endif
9905 : #ifdef _SC_XOPEN_SHM
9906 : {"SC_XOPEN_SHM", _SC_XOPEN_SHM},
9907 : #endif
9908 : #ifdef _SC_XOPEN_UNIX
9909 : {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX},
9910 : #endif
9911 : #ifdef _SC_XOPEN_VERSION
9912 : {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION},
9913 : #endif
9914 : #ifdef _SC_XOPEN_XCU_VERSION
9915 : {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION},
9916 : #endif
9917 : #ifdef _SC_XOPEN_XPG2
9918 : {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2},
9919 : #endif
9920 : #ifdef _SC_XOPEN_XPG3
9921 : {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3},
9922 : #endif
9923 : #ifdef _SC_XOPEN_XPG4
9924 : {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4},
9925 : #endif
9926 : };
9927 :
9928 : static int
9929 0 : conv_sysconf_confname(PyObject *arg, int *valuep)
9930 : {
9931 0 : return conv_confname(arg, valuep, posix_constants_sysconf,
9932 : sizeof(posix_constants_sysconf)
9933 : / sizeof(struct constdef));
9934 : }
9935 :
9936 : PyDoc_STRVAR(posix_sysconf__doc__,
9937 : "sysconf(name) -> integer\n\n\
9938 : Return an integer-valued system configuration variable.");
9939 :
9940 : static PyObject *
9941 0 : posix_sysconf(PyObject *self, PyObject *args)
9942 : {
9943 0 : PyObject *result = NULL;
9944 : int name;
9945 :
9946 0 : if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
9947 : int value;
9948 :
9949 0 : errno = 0;
9950 0 : value = sysconf(name);
9951 0 : if (value == -1 && errno != 0)
9952 0 : posix_error();
9953 : else
9954 0 : result = PyLong_FromLong(value);
9955 : }
9956 0 : return result;
9957 : }
9958 : #endif
9959 :
9960 :
9961 : /* This code is used to ensure that the tables of configuration value names
9962 : * are in sorted order as required by conv_confname(), and also to build the
9963 : * the exported dictionaries that are used to publish information about the
9964 : * names available on the host platform.
9965 : *
9966 : * Sorting the table at runtime ensures that the table is properly ordered
9967 : * when used, even for platforms we're not able to test on. It also makes
9968 : * it easier to add additional entries to the tables.
9969 : */
9970 :
9971 : static int
9972 567 : cmp_constdefs(const void *v1, const void *v2)
9973 : {
9974 567 : const struct constdef *c1 =
9975 : (const struct constdef *) v1;
9976 567 : const struct constdef *c2 =
9977 : (const struct constdef *) v2;
9978 :
9979 567 : return strcmp(c1->name, c2->name);
9980 : }
9981 :
9982 : static int
9983 3 : setup_confname_table(struct constdef *table, size_t tablesize,
9984 : char *tablename, PyObject *module)
9985 : {
9986 3 : PyObject *d = NULL;
9987 : size_t i;
9988 :
9989 3 : qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
9990 3 : d = PyDict_New();
9991 3 : if (d == NULL)
9992 0 : return -1;
9993 :
9994 184 : for (i=0; i < tablesize; ++i) {
9995 181 : PyObject *o = PyLong_FromLong(table[i].value);
9996 181 : if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
9997 0 : Py_XDECREF(o);
9998 0 : Py_DECREF(d);
9999 0 : return -1;
10000 : }
10001 181 : Py_DECREF(o);
10002 : }
10003 3 : return PyModule_AddObject(module, tablename, d);
10004 : }
10005 :
10006 : /* Return -1 on failure, 0 on success. */
10007 : static int
10008 1 : setup_confname_tables(PyObject *module)
10009 : {
10010 : #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
10011 1 : if (setup_confname_table(posix_constants_pathconf,
10012 : sizeof(posix_constants_pathconf)
10013 : / sizeof(struct constdef),
10014 : "pathconf_names", module))
10015 0 : return -1;
10016 : #endif
10017 : #ifdef HAVE_CONFSTR
10018 1 : if (setup_confname_table(posix_constants_confstr,
10019 : sizeof(posix_constants_confstr)
10020 : / sizeof(struct constdef),
10021 : "confstr_names", module))
10022 0 : return -1;
10023 : #endif
10024 : #ifdef HAVE_SYSCONF
10025 1 : if (setup_confname_table(posix_constants_sysconf,
10026 : sizeof(posix_constants_sysconf)
10027 : / sizeof(struct constdef),
10028 : "sysconf_names", module))
10029 0 : return -1;
10030 : #endif
10031 1 : return 0;
10032 : }
10033 :
10034 :
10035 : PyDoc_STRVAR(posix_abort__doc__,
10036 : "abort() -> does not return!\n\n\
10037 : Abort the interpreter immediately. This 'dumps core' or otherwise fails\n\
10038 : in the hardest way possible on the hosting operating system.");
10039 :
10040 : static PyObject *
10041 0 : posix_abort(PyObject *self, PyObject *noargs)
10042 : {
10043 0 : abort();
10044 : /*NOTREACHED*/
10045 : Py_FatalError("abort() called from Python code didn't abort!");
10046 : return NULL;
10047 : }
10048 :
10049 : #ifdef MS_WINDOWS
10050 : PyDoc_STRVAR(win32_startfile__doc__,
10051 : "startfile(filepath [, operation]) - Start a file with its associated\n\
10052 : application.\n\
10053 : \n\
10054 : When \"operation\" is not specified or \"open\", this acts like\n\
10055 : double-clicking the file in Explorer, or giving the file name as an\n\
10056 : argument to the DOS \"start\" command: the file is opened with whatever\n\
10057 : application (if any) its extension is associated.\n\
10058 : When another \"operation\" is given, it specifies what should be done with\n\
10059 : the file. A typical operation is \"print\".\n\
10060 : \n\
10061 : startfile returns as soon as the associated application is launched.\n\
10062 : There is no option to wait for the application to close, and no way\n\
10063 : to retrieve the application's exit status.\n\
10064 : \n\
10065 : The filepath is relative to the current directory. If you want to use\n\
10066 : an absolute path, make sure the first character is not a slash (\"/\");\n\
10067 : the underlying Win32 ShellExecute function doesn't work if it is.");
10068 :
10069 : static PyObject *
10070 : win32_startfile(PyObject *self, PyObject *args)
10071 : {
10072 : PyObject *ofilepath;
10073 : char *filepath;
10074 : char *operation = NULL;
10075 : wchar_t *wpath, *woperation;
10076 : HINSTANCE rc;
10077 :
10078 : PyObject *unipath, *uoperation = NULL;
10079 : if (!PyArg_ParseTuple(args, "U|s:startfile",
10080 : &unipath, &operation)) {
10081 : PyErr_Clear();
10082 : goto normal;
10083 : }
10084 :
10085 : if (operation) {
10086 : uoperation = PyUnicode_DecodeASCII(operation,
10087 : strlen(operation), NULL);
10088 : if (!uoperation) {
10089 : PyErr_Clear();
10090 : operation = NULL;
10091 : goto normal;
10092 : }
10093 : }
10094 :
10095 : wpath = PyUnicode_AsUnicode(unipath);
10096 : if (wpath == NULL)
10097 : goto normal;
10098 : if (uoperation) {
10099 : woperation = PyUnicode_AsUnicode(uoperation);
10100 : if (woperation == NULL)
10101 : goto normal;
10102 : }
10103 : else
10104 : woperation = NULL;
10105 :
10106 : Py_BEGIN_ALLOW_THREADS
10107 : rc = ShellExecuteW((HWND)0, woperation, wpath,
10108 : NULL, NULL, SW_SHOWNORMAL);
10109 : Py_END_ALLOW_THREADS
10110 :
10111 : Py_XDECREF(uoperation);
10112 : if (rc <= (HINSTANCE)32) {
10113 : win32_error_object("startfile", unipath);
10114 : return NULL;
10115 : }
10116 : Py_INCREF(Py_None);
10117 : return Py_None;
10118 :
10119 : normal:
10120 : if (!PyArg_ParseTuple(args, "O&|s:startfile",
10121 : PyUnicode_FSConverter, &ofilepath,
10122 : &operation))
10123 : return NULL;
10124 : if (win32_warn_bytes_api()) {
10125 : Py_DECREF(ofilepath);
10126 : return NULL;
10127 : }
10128 : filepath = PyBytes_AsString(ofilepath);
10129 : Py_BEGIN_ALLOW_THREADS
10130 : rc = ShellExecute((HWND)0, operation, filepath,
10131 : NULL, NULL, SW_SHOWNORMAL);
10132 : Py_END_ALLOW_THREADS
10133 : if (rc <= (HINSTANCE)32) {
10134 : PyObject *errval = win32_error("startfile", filepath);
10135 : Py_DECREF(ofilepath);
10136 : return errval;
10137 : }
10138 : Py_DECREF(ofilepath);
10139 : Py_INCREF(Py_None);
10140 : return Py_None;
10141 : }
10142 : #endif
10143 :
10144 : #ifdef HAVE_GETLOADAVG
10145 : PyDoc_STRVAR(posix_getloadavg__doc__,
10146 : "getloadavg() -> (float, float, float)\n\n\
10147 : Return the number of processes in the system run queue averaged over\n\
10148 : the last 1, 5, and 15 minutes or raises OSError if the load average\n\
10149 : was unobtainable");
10150 :
10151 : static PyObject *
10152 0 : posix_getloadavg(PyObject *self, PyObject *noargs)
10153 : {
10154 : double loadavg[3];
10155 0 : if (getloadavg(loadavg, 3)!=3) {
10156 0 : PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
10157 0 : return NULL;
10158 : } else
10159 0 : return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
10160 : }
10161 : #endif
10162 :
10163 : PyDoc_STRVAR(device_encoding__doc__,
10164 : "device_encoding(fd) -> str\n\n\
10165 : Return a string describing the encoding of the device\n\
10166 : if the output is a terminal; else return None.");
10167 :
10168 : static PyObject *
10169 0 : device_encoding(PyObject *self, PyObject *args)
10170 : {
10171 : int fd;
10172 :
10173 0 : if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
10174 0 : return NULL;
10175 :
10176 0 : return _Py_device_encoding(fd);
10177 : }
10178 :
10179 : #ifdef HAVE_SETRESUID
10180 : PyDoc_STRVAR(posix_setresuid__doc__,
10181 : "setresuid(ruid, euid, suid)\n\n\
10182 : Set the current process's real, effective, and saved user ids.");
10183 :
10184 : static PyObject*
10185 0 : posix_setresuid (PyObject *self, PyObject *args)
10186 : {
10187 : /* We assume uid_t is no larger than a long. */
10188 : long ruid, euid, suid;
10189 0 : if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
10190 0 : return NULL;
10191 0 : if (setresuid(ruid, euid, suid) < 0)
10192 0 : return posix_error();
10193 0 : Py_RETURN_NONE;
10194 : }
10195 : #endif
10196 :
10197 : #ifdef HAVE_SETRESGID
10198 : PyDoc_STRVAR(posix_setresgid__doc__,
10199 : "setresgid(rgid, egid, sgid)\n\n\
10200 : Set the current process's real, effective, and saved group ids.");
10201 :
10202 : static PyObject*
10203 0 : posix_setresgid (PyObject *self, PyObject *args)
10204 : {
10205 : /* We assume uid_t is no larger than a long. */
10206 : long rgid, egid, sgid;
10207 0 : if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
10208 0 : return NULL;
10209 0 : if (setresgid(rgid, egid, sgid) < 0)
10210 0 : return posix_error();
10211 0 : Py_RETURN_NONE;
10212 : }
10213 : #endif
10214 :
10215 : #ifdef HAVE_GETRESUID
10216 : PyDoc_STRVAR(posix_getresuid__doc__,
10217 : "getresuid() -> (ruid, euid, suid)\n\n\
10218 : Get tuple of the current process's real, effective, and saved user ids.");
10219 :
10220 : static PyObject*
10221 0 : posix_getresuid (PyObject *self, PyObject *noargs)
10222 : {
10223 : uid_t ruid, euid, suid;
10224 : long l_ruid, l_euid, l_suid;
10225 0 : if (getresuid(&ruid, &euid, &suid) < 0)
10226 0 : return posix_error();
10227 : /* Force the values into long's as we don't know the size of uid_t. */
10228 0 : l_ruid = ruid;
10229 0 : l_euid = euid;
10230 0 : l_suid = suid;
10231 0 : return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
10232 : }
10233 : #endif
10234 :
10235 : #ifdef HAVE_GETRESGID
10236 : PyDoc_STRVAR(posix_getresgid__doc__,
10237 : "getresgid() -> (rgid, egid, sgid)\n\n\
10238 : Get tuple of the current process's real, effective, and saved group ids.");
10239 :
10240 : static PyObject*
10241 0 : posix_getresgid (PyObject *self, PyObject *noargs)
10242 : {
10243 : uid_t rgid, egid, sgid;
10244 : long l_rgid, l_egid, l_sgid;
10245 0 : if (getresgid(&rgid, &egid, &sgid) < 0)
10246 0 : return posix_error();
10247 : /* Force the values into long's as we don't know the size of uid_t. */
10248 0 : l_rgid = rgid;
10249 0 : l_egid = egid;
10250 0 : l_sgid = sgid;
10251 0 : return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
10252 : }
10253 : #endif
10254 :
10255 : #ifdef USE_XATTRS
10256 :
10257 : PyDoc_STRVAR(posix_getxattr__doc__,
10258 : "getxattr(path, attribute, *, follow_symlinks=True) -> value\n\n\
10259 : Return the value of extended attribute attribute on path.\n\
10260 : \n\
10261 : path may be either a string or an open file descriptor.\n\
10262 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
10263 : link, getxattr will examine the symbolic link itself instead of the file\n\
10264 : the link points to.");
10265 :
10266 : static PyObject *
10267 0 : posix_getxattr(PyObject *self, PyObject *args, PyObject *kwargs)
10268 : {
10269 : path_t path;
10270 : path_t attribute;
10271 0 : int follow_symlinks = 1;
10272 0 : PyObject *buffer = NULL;
10273 : int i;
10274 : static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL};
10275 :
10276 0 : memset(&path, 0, sizeof(path));
10277 0 : memset(&attribute, 0, sizeof(attribute));
10278 0 : path.allow_fd = 1;
10279 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:getxattr", keywords,
10280 : path_converter, &path,
10281 : path_converter, &attribute,
10282 : &follow_symlinks))
10283 0 : return NULL;
10284 :
10285 0 : if (fd_and_follow_symlinks_invalid("getxattr", path.fd, follow_symlinks))
10286 0 : goto exit;
10287 :
10288 0 : for (i = 0; ; i++) {
10289 : void *ptr;
10290 : ssize_t result;
10291 : static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
10292 0 : Py_ssize_t buffer_size = buffer_sizes[i];
10293 0 : if (!buffer_size) {
10294 0 : path_error("getxattr", &path);
10295 0 : goto exit;
10296 : }
10297 0 : buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
10298 0 : if (!buffer)
10299 0 : goto exit;
10300 0 : ptr = PyBytes_AS_STRING(buffer);
10301 :
10302 0 : Py_BEGIN_ALLOW_THREADS;
10303 0 : if (path.fd >= 0)
10304 0 : result = fgetxattr(path.fd, attribute.narrow, ptr, buffer_size);
10305 0 : else if (follow_symlinks)
10306 0 : result = getxattr(path.narrow, attribute.narrow, ptr, buffer_size);
10307 : else
10308 0 : result = lgetxattr(path.narrow, attribute.narrow, ptr, buffer_size);
10309 0 : Py_END_ALLOW_THREADS;
10310 :
10311 0 : if (result < 0) {
10312 0 : Py_DECREF(buffer);
10313 0 : buffer = NULL;
10314 0 : if (errno == ERANGE)
10315 0 : continue;
10316 0 : path_error("getxattr", &path);
10317 0 : goto exit;
10318 : }
10319 :
10320 0 : if (result != buffer_size) {
10321 : /* Can only shrink. */
10322 0 : _PyBytes_Resize(&buffer, result);
10323 : }
10324 0 : break;
10325 0 : }
10326 :
10327 : exit:
10328 0 : path_cleanup(&path);
10329 0 : path_cleanup(&attribute);
10330 0 : return buffer;
10331 : }
10332 :
10333 : PyDoc_STRVAR(posix_setxattr__doc__,
10334 : "setxattr(path, attribute, value, flags=0, *, follow_symlinks=True)\n\n\
10335 : Set extended attribute attribute on path to value.\n\
10336 : path may be either a string or an open file descriptor.\n\
10337 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
10338 : link, setxattr will modify the symbolic link itself instead of the file\n\
10339 : the link points to.");
10340 :
10341 : static PyObject *
10342 0 : posix_setxattr(PyObject *self, PyObject *args, PyObject *kwargs)
10343 : {
10344 : path_t path;
10345 : path_t attribute;
10346 : Py_buffer value;
10347 0 : int flags = 0;
10348 0 : int follow_symlinks = 1;
10349 : int result;
10350 0 : PyObject *return_value = NULL;
10351 : static char *keywords[] = {"path", "attribute", "value",
10352 : "flags", "follow_symlinks", NULL};
10353 :
10354 0 : memset(&path, 0, sizeof(path));
10355 0 : path.allow_fd = 1;
10356 0 : memset(&attribute, 0, sizeof(attribute));
10357 0 : memset(&value, 0, sizeof(value));
10358 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&y*|i$p:setxattr",
10359 : keywords,
10360 : path_converter, &path,
10361 : path_converter, &attribute,
10362 : &value, &flags,
10363 : &follow_symlinks))
10364 0 : return NULL;
10365 :
10366 0 : if (fd_and_follow_symlinks_invalid("setxattr", path.fd, follow_symlinks))
10367 0 : goto exit;
10368 :
10369 0 : Py_BEGIN_ALLOW_THREADS;
10370 0 : if (path.fd > -1)
10371 0 : result = fsetxattr(path.fd, attribute.narrow,
10372 0 : value.buf, value.len, flags);
10373 0 : else if (follow_symlinks)
10374 0 : result = setxattr(path.narrow, attribute.narrow,
10375 0 : value.buf, value.len, flags);
10376 : else
10377 0 : result = lsetxattr(path.narrow, attribute.narrow,
10378 0 : value.buf, value.len, flags);
10379 0 : Py_END_ALLOW_THREADS;
10380 :
10381 0 : if (result) {
10382 0 : return_value = path_error("setxattr", &path);
10383 0 : goto exit;
10384 : }
10385 :
10386 0 : return_value = Py_None;
10387 0 : Py_INCREF(return_value);
10388 :
10389 : exit:
10390 0 : path_cleanup(&path);
10391 0 : path_cleanup(&attribute);
10392 0 : PyBuffer_Release(&value);
10393 :
10394 0 : return return_value;
10395 : }
10396 :
10397 : PyDoc_STRVAR(posix_removexattr__doc__,
10398 : "removexattr(path, attribute, *, follow_symlinks=True)\n\n\
10399 : Remove extended attribute attribute on path.\n\
10400 : path may be either a string or an open file descriptor.\n\
10401 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
10402 : link, removexattr will modify the symbolic link itself instead of the file\n\
10403 : the link points to.");
10404 :
10405 : static PyObject *
10406 0 : posix_removexattr(PyObject *self, PyObject *args, PyObject *kwargs)
10407 : {
10408 : path_t path;
10409 : path_t attribute;
10410 0 : int follow_symlinks = 1;
10411 : int result;
10412 0 : PyObject *return_value = NULL;
10413 : static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL};
10414 :
10415 0 : memset(&path, 0, sizeof(path));
10416 0 : memset(&attribute, 0, sizeof(attribute));
10417 0 : path.allow_fd = 1;
10418 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:removexattr",
10419 : keywords,
10420 : path_converter, &path,
10421 : path_converter, &attribute,
10422 : &follow_symlinks))
10423 0 : return NULL;
10424 :
10425 0 : if (fd_and_follow_symlinks_invalid("removexattr", path.fd, follow_symlinks))
10426 0 : goto exit;
10427 :
10428 0 : Py_BEGIN_ALLOW_THREADS;
10429 0 : if (path.fd > -1)
10430 0 : result = fremovexattr(path.fd, attribute.narrow);
10431 0 : else if (follow_symlinks)
10432 0 : result = removexattr(path.narrow, attribute.narrow);
10433 : else
10434 0 : result = lremovexattr(path.narrow, attribute.narrow);
10435 0 : Py_END_ALLOW_THREADS;
10436 :
10437 0 : if (result) {
10438 0 : return_value = path_error("removexattr", &path);
10439 0 : goto exit;
10440 : }
10441 :
10442 0 : return_value = Py_None;
10443 0 : Py_INCREF(return_value);
10444 :
10445 : exit:
10446 0 : path_cleanup(&path);
10447 0 : path_cleanup(&attribute);
10448 :
10449 0 : return return_value;
10450 : }
10451 :
10452 : PyDoc_STRVAR(posix_listxattr__doc__,
10453 : "listxattr(path='.', *, follow_symlinks=True)\n\n\
10454 : Return a list of extended attributes on path.\n\
10455 : \n\
10456 : path may be either None, a string, or an open file descriptor.\n\
10457 : if path is None, listxattr will examine the current directory.\n\
10458 : If follow_symlinks is False, and the last element of the path is a symbolic\n\
10459 : link, listxattr will examine the symbolic link itself instead of the file\n\
10460 : the link points to.");
10461 :
10462 : static PyObject *
10463 0 : posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs)
10464 : {
10465 : path_t path;
10466 0 : int follow_symlinks = 1;
10467 : Py_ssize_t i;
10468 0 : PyObject *result = NULL;
10469 0 : char *buffer = NULL;
10470 : char *name;
10471 : static char *keywords[] = {"path", "follow_symlinks", NULL};
10472 :
10473 0 : memset(&path, 0, sizeof(path));
10474 0 : path.allow_fd = 1;
10475 0 : path.fd = -1;
10476 0 : if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&$p:listxattr", keywords,
10477 : path_converter, &path,
10478 : &follow_symlinks))
10479 0 : return NULL;
10480 :
10481 0 : if (fd_and_follow_symlinks_invalid("listxattr", path.fd, follow_symlinks))
10482 0 : goto exit;
10483 :
10484 0 : name = path.narrow ? path.narrow : ".";
10485 0 : for (i = 0; ; i++) {
10486 : char *start, *trace, *end;
10487 : ssize_t length;
10488 : static Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
10489 0 : Py_ssize_t buffer_size = buffer_sizes[i];
10490 0 : if (!buffer_size) {
10491 : /* ERANGE */
10492 0 : path_error("listxattr", &path);
10493 0 : break;
10494 : }
10495 0 : buffer = PyMem_MALLOC(buffer_size);
10496 0 : if (!buffer) {
10497 0 : PyErr_NoMemory();
10498 0 : break;
10499 : }
10500 :
10501 0 : Py_BEGIN_ALLOW_THREADS;
10502 0 : if (path.fd > -1)
10503 0 : length = flistxattr(path.fd, buffer, buffer_size);
10504 0 : else if (follow_symlinks)
10505 0 : length = listxattr(name, buffer, buffer_size);
10506 : else
10507 0 : length = llistxattr(name, buffer, buffer_size);
10508 0 : Py_END_ALLOW_THREADS;
10509 :
10510 0 : if (length < 0) {
10511 0 : if (errno == ERANGE)
10512 0 : continue;
10513 0 : path_error("listxattr", &path);
10514 0 : break;
10515 : }
10516 :
10517 0 : result = PyList_New(0);
10518 0 : if (!result) {
10519 0 : goto exit;
10520 : }
10521 :
10522 0 : end = buffer + length;
10523 0 : for (trace = start = buffer; trace != end; trace++) {
10524 0 : if (!*trace) {
10525 : int error;
10526 0 : PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
10527 : trace - start);
10528 0 : if (!attribute) {
10529 0 : Py_DECREF(result);
10530 0 : result = NULL;
10531 0 : goto exit;
10532 : }
10533 0 : error = PyList_Append(result, attribute);
10534 0 : Py_DECREF(attribute);
10535 0 : if (error) {
10536 0 : Py_DECREF(result);
10537 0 : result = NULL;
10538 0 : goto exit;
10539 : }
10540 0 : start = trace + 1;
10541 : }
10542 : }
10543 0 : break;
10544 0 : }
10545 : exit:
10546 0 : path_cleanup(&path);
10547 0 : if (buffer)
10548 0 : PyMem_FREE(buffer);
10549 0 : return result;
10550 : }
10551 :
10552 : #endif /* USE_XATTRS */
10553 :
10554 :
10555 : PyDoc_STRVAR(posix_urandom__doc__,
10556 : "urandom(n) -> str\n\n\
10557 : Return n random bytes suitable for cryptographic use.");
10558 :
10559 : static PyObject *
10560 0 : posix_urandom(PyObject *self, PyObject *args)
10561 : {
10562 : Py_ssize_t size;
10563 : PyObject *result;
10564 : int ret;
10565 :
10566 : /* Read arguments */
10567 0 : if (!PyArg_ParseTuple(args, "n:urandom", &size))
10568 0 : return NULL;
10569 0 : if (size < 0)
10570 0 : return PyErr_Format(PyExc_ValueError,
10571 : "negative argument not allowed");
10572 0 : result = PyBytes_FromStringAndSize(NULL, size);
10573 0 : if (result == NULL)
10574 0 : return NULL;
10575 :
10576 0 : ret = _PyOS_URandom(PyBytes_AS_STRING(result),
10577 : PyBytes_GET_SIZE(result));
10578 0 : if (ret == -1) {
10579 0 : Py_DECREF(result);
10580 0 : return NULL;
10581 : }
10582 0 : return result;
10583 : }
10584 :
10585 : /* Terminal size querying */
10586 :
10587 : static PyTypeObject TerminalSizeType;
10588 :
10589 : PyDoc_STRVAR(TerminalSize_docstring,
10590 : "A tuple of (columns, lines) for holding terminal window size");
10591 :
10592 : static PyStructSequence_Field TerminalSize_fields[] = {
10593 : {"columns", "width of the terminal window in characters"},
10594 : {"lines", "height of the terminal window in characters"},
10595 : {NULL, NULL}
10596 : };
10597 :
10598 : static PyStructSequence_Desc TerminalSize_desc = {
10599 : "os.terminal_size",
10600 : TerminalSize_docstring,
10601 : TerminalSize_fields,
10602 : 2,
10603 : };
10604 :
10605 : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
10606 : PyDoc_STRVAR(termsize__doc__,
10607 : "Return the size of the terminal window as (columns, lines).\n" \
10608 : "\n" \
10609 : "The optional argument fd (default standard output) specifies\n" \
10610 : "which file descriptor should be queried.\n" \
10611 : "\n" \
10612 : "If the file descriptor is not connected to a terminal, an OSError\n" \
10613 : "is thrown.\n" \
10614 : "\n" \
10615 : "This function will only be defined if an implementation is\n" \
10616 : "available for this system.\n" \
10617 : "\n" \
10618 : "shutil.get_terminal_size is the high-level function which should \n" \
10619 : "normally be used, os.get_terminal_size is the low-level implementation.");
10620 :
10621 : static PyObject*
10622 0 : get_terminal_size(PyObject *self, PyObject *args)
10623 : {
10624 : int columns, lines;
10625 : PyObject *termsize;
10626 :
10627 0 : int fd = fileno(stdout);
10628 : /* Under some conditions stdout may not be connected and
10629 : * fileno(stdout) may point to an invalid file descriptor. For example
10630 : * GUI apps don't have valid standard streams by default.
10631 : *
10632 : * If this happens, and the optional fd argument is not present,
10633 : * the ioctl below will fail returning EBADF. This is what we want.
10634 : */
10635 :
10636 0 : if (!PyArg_ParseTuple(args, "|i", &fd))
10637 0 : return NULL;
10638 :
10639 : #ifdef TERMSIZE_USE_IOCTL
10640 : {
10641 : struct winsize w;
10642 0 : if (ioctl(fd, TIOCGWINSZ, &w))
10643 0 : return PyErr_SetFromErrno(PyExc_OSError);
10644 0 : columns = w.ws_col;
10645 0 : lines = w.ws_row;
10646 : }
10647 : #endif /* TERMSIZE_USE_IOCTL */
10648 :
10649 : #ifdef TERMSIZE_USE_CONIO
10650 : {
10651 : DWORD nhandle;
10652 : HANDLE handle;
10653 : CONSOLE_SCREEN_BUFFER_INFO csbi;
10654 : switch (fd) {
10655 : case 0: nhandle = STD_INPUT_HANDLE;
10656 : break;
10657 : case 1: nhandle = STD_OUTPUT_HANDLE;
10658 : break;
10659 : case 2: nhandle = STD_ERROR_HANDLE;
10660 : break;
10661 : default:
10662 : return PyErr_Format(PyExc_ValueError, "bad file descriptor");
10663 : }
10664 : handle = GetStdHandle(nhandle);
10665 : if (handle == NULL)
10666 : return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
10667 : if (handle == INVALID_HANDLE_VALUE)
10668 : return PyErr_SetFromWindowsErr(0);
10669 :
10670 : if (!GetConsoleScreenBufferInfo(handle, &csbi))
10671 : return PyErr_SetFromWindowsErr(0);
10672 :
10673 : columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
10674 : lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
10675 : }
10676 : #endif /* TERMSIZE_USE_CONIO */
10677 :
10678 0 : termsize = PyStructSequence_New(&TerminalSizeType);
10679 0 : if (termsize == NULL)
10680 0 : return NULL;
10681 0 : PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
10682 0 : PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
10683 0 : if (PyErr_Occurred()) {
10684 0 : Py_DECREF(termsize);
10685 0 : return NULL;
10686 : }
10687 0 : return termsize;
10688 : }
10689 : #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
10690 :
10691 :
10692 : static PyMethodDef posix_methods[] = {
10693 : {"access", (PyCFunction)posix_access,
10694 : METH_VARARGS | METH_KEYWORDS,
10695 : posix_access__doc__},
10696 : #ifdef HAVE_TTYNAME
10697 : {"ttyname", posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
10698 : #endif
10699 : {"chdir", (PyCFunction)posix_chdir,
10700 : METH_VARARGS | METH_KEYWORDS,
10701 : posix_chdir__doc__},
10702 : #ifdef HAVE_CHFLAGS
10703 : {"chflags", (PyCFunction)posix_chflags,
10704 : METH_VARARGS | METH_KEYWORDS,
10705 : posix_chflags__doc__},
10706 : #endif /* HAVE_CHFLAGS */
10707 : {"chmod", (PyCFunction)posix_chmod,
10708 : METH_VARARGS | METH_KEYWORDS,
10709 : posix_chmod__doc__},
10710 : #ifdef HAVE_FCHMOD
10711 : {"fchmod", posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
10712 : #endif /* HAVE_FCHMOD */
10713 : #ifdef HAVE_CHOWN
10714 : {"chown", (PyCFunction)posix_chown,
10715 : METH_VARARGS | METH_KEYWORDS,
10716 : posix_chown__doc__},
10717 : #endif /* HAVE_CHOWN */
10718 : #ifdef HAVE_LCHMOD
10719 : {"lchmod", posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
10720 : #endif /* HAVE_LCHMOD */
10721 : #ifdef HAVE_FCHOWN
10722 : {"fchown", posix_fchown, METH_VARARGS, posix_fchown__doc__},
10723 : #endif /* HAVE_FCHOWN */
10724 : #ifdef HAVE_LCHFLAGS
10725 : {"lchflags", posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
10726 : #endif /* HAVE_LCHFLAGS */
10727 : #ifdef HAVE_LCHOWN
10728 : {"lchown", posix_lchown, METH_VARARGS, posix_lchown__doc__},
10729 : #endif /* HAVE_LCHOWN */
10730 : #ifdef HAVE_CHROOT
10731 : {"chroot", posix_chroot, METH_VARARGS, posix_chroot__doc__},
10732 : #endif
10733 : #ifdef HAVE_CTERMID
10734 : {"ctermid", posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
10735 : #endif
10736 : #ifdef HAVE_GETCWD
10737 : {"getcwd", (PyCFunction)posix_getcwd_unicode,
10738 : METH_NOARGS, posix_getcwd__doc__},
10739 : {"getcwdb", (PyCFunction)posix_getcwd_bytes,
10740 : METH_NOARGS, posix_getcwdb__doc__},
10741 : #endif
10742 : #if defined(HAVE_LINK) || defined(MS_WINDOWS)
10743 : {"link", (PyCFunction)posix_link,
10744 : METH_VARARGS | METH_KEYWORDS,
10745 : posix_link__doc__},
10746 : #endif /* HAVE_LINK */
10747 : {"listdir", (PyCFunction)posix_listdir,
10748 : METH_VARARGS | METH_KEYWORDS,
10749 : posix_listdir__doc__},
10750 : {"lstat", (PyCFunction)posix_lstat,
10751 : METH_VARARGS | METH_KEYWORDS,
10752 : posix_lstat__doc__},
10753 : {"mkdir", (PyCFunction)posix_mkdir,
10754 : METH_VARARGS | METH_KEYWORDS,
10755 : posix_mkdir__doc__},
10756 : #ifdef HAVE_NICE
10757 : {"nice", posix_nice, METH_VARARGS, posix_nice__doc__},
10758 : #endif /* HAVE_NICE */
10759 : #ifdef HAVE_GETPRIORITY
10760 : {"getpriority", posix_getpriority, METH_VARARGS, posix_getpriority__doc__},
10761 : #endif /* HAVE_GETPRIORITY */
10762 : #ifdef HAVE_SETPRIORITY
10763 : {"setpriority", posix_setpriority, METH_VARARGS, posix_setpriority__doc__},
10764 : #endif /* HAVE_SETPRIORITY */
10765 : #ifdef HAVE_READLINK
10766 : {"readlink", (PyCFunction)posix_readlink,
10767 : METH_VARARGS | METH_KEYWORDS,
10768 : readlink__doc__},
10769 : #endif /* HAVE_READLINK */
10770 : #if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
10771 : {"readlink", (PyCFunction)win_readlink,
10772 : METH_VARARGS | METH_KEYWORDS,
10773 : readlink__doc__},
10774 : #endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
10775 : {"rename", (PyCFunction)posix_rename,
10776 : METH_VARARGS | METH_KEYWORDS,
10777 : posix_rename__doc__},
10778 : {"replace", (PyCFunction)posix_replace,
10779 : METH_VARARGS | METH_KEYWORDS,
10780 : posix_replace__doc__},
10781 : {"rmdir", (PyCFunction)posix_rmdir,
10782 : METH_VARARGS | METH_KEYWORDS,
10783 : posix_rmdir__doc__},
10784 : {"stat", (PyCFunction)posix_stat,
10785 : METH_VARARGS | METH_KEYWORDS,
10786 : posix_stat__doc__},
10787 : {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
10788 : #if defined(HAVE_SYMLINK)
10789 : {"symlink", (PyCFunction)posix_symlink,
10790 : METH_VARARGS | METH_KEYWORDS,
10791 : posix_symlink__doc__},
10792 : #endif /* HAVE_SYMLINK */
10793 : #ifdef HAVE_SYSTEM
10794 : {"system", posix_system, METH_VARARGS, posix_system__doc__},
10795 : #endif
10796 : {"umask", posix_umask, METH_VARARGS, posix_umask__doc__},
10797 : #ifdef HAVE_UNAME
10798 : {"uname", posix_uname, METH_NOARGS, posix_uname__doc__},
10799 : #endif /* HAVE_UNAME */
10800 : {"unlink", (PyCFunction)posix_unlink,
10801 : METH_VARARGS | METH_KEYWORDS,
10802 : posix_unlink__doc__},
10803 : {"remove", (PyCFunction)posix_unlink,
10804 : METH_VARARGS | METH_KEYWORDS,
10805 : posix_remove__doc__},
10806 : {"utime", (PyCFunction)posix_utime,
10807 : METH_VARARGS | METH_KEYWORDS, posix_utime__doc__},
10808 : #ifdef HAVE_TIMES
10809 : {"times", posix_times, METH_NOARGS, posix_times__doc__},
10810 : #endif /* HAVE_TIMES */
10811 : {"_exit", posix__exit, METH_VARARGS, posix__exit__doc__},
10812 : #ifdef HAVE_EXECV
10813 : {"execv", posix_execv, METH_VARARGS, posix_execv__doc__},
10814 : {"execve", (PyCFunction)posix_execve,
10815 : METH_VARARGS | METH_KEYWORDS,
10816 : posix_execve__doc__},
10817 : #endif /* HAVE_EXECV */
10818 : #ifdef HAVE_SPAWNV
10819 : {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
10820 : {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
10821 : #if defined(PYOS_OS2)
10822 : {"spawnvp", posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
10823 : {"spawnvpe", posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
10824 : #endif /* PYOS_OS2 */
10825 : #endif /* HAVE_SPAWNV */
10826 : #ifdef HAVE_FORK1
10827 : {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__},
10828 : #endif /* HAVE_FORK1 */
10829 : #ifdef HAVE_FORK
10830 : {"fork", posix_fork, METH_NOARGS, posix_fork__doc__},
10831 : #endif /* HAVE_FORK */
10832 : #ifdef HAVE_SCHED_H
10833 : #ifdef HAVE_SCHED_GET_PRIORITY_MAX
10834 : {"sched_get_priority_max", posix_sched_get_priority_max, METH_VARARGS, posix_sched_get_priority_max__doc__},
10835 : {"sched_get_priority_min", posix_sched_get_priority_min, METH_VARARGS, posix_sched_get_priority_min__doc__},
10836 : #endif
10837 : #ifdef HAVE_SCHED_SETPARAM
10838 : {"sched_getparam", posix_sched_getparam, METH_VARARGS, posix_sched_getparam__doc__},
10839 : #endif
10840 : #ifdef HAVE_SCHED_SETSCHEDULER
10841 : {"sched_getscheduler", posix_sched_getscheduler, METH_VARARGS, posix_sched_getscheduler__doc__},
10842 : #endif
10843 : #ifdef HAVE_SCHED_RR_GET_INTERVAL
10844 : {"sched_rr_get_interval", posix_sched_rr_get_interval, METH_VARARGS, posix_sched_rr_get_interval__doc__},
10845 : #endif
10846 : #ifdef HAVE_SCHED_SETPARAM
10847 : {"sched_setparam", posix_sched_setparam, METH_VARARGS, posix_sched_setparam__doc__},
10848 : #endif
10849 : #ifdef HAVE_SCHED_SETSCHEDULER
10850 : {"sched_setscheduler", posix_sched_setscheduler, METH_VARARGS, posix_sched_setscheduler__doc__},
10851 : #endif
10852 : {"sched_yield", posix_sched_yield, METH_NOARGS, posix_sched_yield__doc__},
10853 : #ifdef HAVE_SCHED_SETAFFINITY
10854 : {"sched_setaffinity", posix_sched_setaffinity, METH_VARARGS, posix_sched_setaffinity__doc__},
10855 : {"sched_getaffinity", posix_sched_getaffinity, METH_VARARGS, posix_sched_getaffinity__doc__},
10856 : #endif
10857 : #endif /* HAVE_SCHED_H */
10858 : #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
10859 : {"openpty", posix_openpty, METH_NOARGS, posix_openpty__doc__},
10860 : #endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
10861 : #ifdef HAVE_FORKPTY
10862 : {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
10863 : #endif /* HAVE_FORKPTY */
10864 : #ifdef HAVE_GETEGID
10865 : {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__},
10866 : #endif /* HAVE_GETEGID */
10867 : #ifdef HAVE_GETEUID
10868 : {"geteuid", posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
10869 : #endif /* HAVE_GETEUID */
10870 : #ifdef HAVE_GETGID
10871 : {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__},
10872 : #endif /* HAVE_GETGID */
10873 : #ifdef HAVE_GETGROUPLIST
10874 : {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__},
10875 : #endif
10876 : #ifdef HAVE_GETGROUPS
10877 : {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
10878 : #endif
10879 : {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__},
10880 : #ifdef HAVE_GETPGRP
10881 : {"getpgrp", posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
10882 : #endif /* HAVE_GETPGRP */
10883 : #ifdef HAVE_GETPPID
10884 : {"getppid", posix_getppid, METH_NOARGS, posix_getppid__doc__},
10885 : #endif /* HAVE_GETPPID */
10886 : #ifdef HAVE_GETUID
10887 : {"getuid", posix_getuid, METH_NOARGS, posix_getuid__doc__},
10888 : #endif /* HAVE_GETUID */
10889 : #ifdef HAVE_GETLOGIN
10890 : {"getlogin", posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
10891 : #endif
10892 : #ifdef HAVE_KILL
10893 : {"kill", posix_kill, METH_VARARGS, posix_kill__doc__},
10894 : #endif /* HAVE_KILL */
10895 : #ifdef HAVE_KILLPG
10896 : {"killpg", posix_killpg, METH_VARARGS, posix_killpg__doc__},
10897 : #endif /* HAVE_KILLPG */
10898 : #ifdef HAVE_PLOCK
10899 : {"plock", posix_plock, METH_VARARGS, posix_plock__doc__},
10900 : #endif /* HAVE_PLOCK */
10901 : #ifdef MS_WINDOWS
10902 : {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__},
10903 : {"kill", win32_kill, METH_VARARGS, win32_kill__doc__},
10904 : #endif
10905 : #ifdef HAVE_SETUID
10906 : {"setuid", posix_setuid, METH_VARARGS, posix_setuid__doc__},
10907 : #endif /* HAVE_SETUID */
10908 : #ifdef HAVE_SETEUID
10909 : {"seteuid", posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
10910 : #endif /* HAVE_SETEUID */
10911 : #ifdef HAVE_SETEGID
10912 : {"setegid", posix_setegid, METH_VARARGS, posix_setegid__doc__},
10913 : #endif /* HAVE_SETEGID */
10914 : #ifdef HAVE_SETREUID
10915 : {"setreuid", posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
10916 : #endif /* HAVE_SETREUID */
10917 : #ifdef HAVE_SETREGID
10918 : {"setregid", posix_setregid, METH_VARARGS, posix_setregid__doc__},
10919 : #endif /* HAVE_SETREGID */
10920 : #ifdef HAVE_SETGID
10921 : {"setgid", posix_setgid, METH_VARARGS, posix_setgid__doc__},
10922 : #endif /* HAVE_SETGID */
10923 : #ifdef HAVE_SETGROUPS
10924 : {"setgroups", posix_setgroups, METH_O, posix_setgroups__doc__},
10925 : #endif /* HAVE_SETGROUPS */
10926 : #ifdef HAVE_INITGROUPS
10927 : {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
10928 : #endif /* HAVE_INITGROUPS */
10929 : #ifdef HAVE_GETPGID
10930 : {"getpgid", posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
10931 : #endif /* HAVE_GETPGID */
10932 : #ifdef HAVE_SETPGRP
10933 : {"setpgrp", posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
10934 : #endif /* HAVE_SETPGRP */
10935 : #ifdef HAVE_WAIT
10936 : {"wait", posix_wait, METH_NOARGS, posix_wait__doc__},
10937 : #endif /* HAVE_WAIT */
10938 : #ifdef HAVE_WAIT3
10939 : {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__},
10940 : #endif /* HAVE_WAIT3 */
10941 : #ifdef HAVE_WAIT4
10942 : {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__},
10943 : #endif /* HAVE_WAIT4 */
10944 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
10945 : {"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__},
10946 : #endif
10947 : #if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
10948 : {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
10949 : #endif /* HAVE_WAITPID */
10950 : #ifdef HAVE_GETSID
10951 : {"getsid", posix_getsid, METH_VARARGS, posix_getsid__doc__},
10952 : #endif /* HAVE_GETSID */
10953 : #ifdef HAVE_SETSID
10954 : {"setsid", posix_setsid, METH_NOARGS, posix_setsid__doc__},
10955 : #endif /* HAVE_SETSID */
10956 : #ifdef HAVE_SETPGID
10957 : {"setpgid", posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
10958 : #endif /* HAVE_SETPGID */
10959 : #ifdef HAVE_TCGETPGRP
10960 : {"tcgetpgrp", posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
10961 : #endif /* HAVE_TCGETPGRP */
10962 : #ifdef HAVE_TCSETPGRP
10963 : {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
10964 : #endif /* HAVE_TCSETPGRP */
10965 : {"open", (PyCFunction)posix_open,\
10966 : METH_VARARGS | METH_KEYWORDS,
10967 : posix_open__doc__},
10968 : {"close", posix_close, METH_VARARGS, posix_close__doc__},
10969 : {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__},
10970 : {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
10971 : {"dup", posix_dup, METH_VARARGS, posix_dup__doc__},
10972 : {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__},
10973 : #ifdef HAVE_LOCKF
10974 : {"lockf", posix_lockf, METH_VARARGS, posix_lockf__doc__},
10975 : #endif
10976 : {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__},
10977 : {"read", posix_read, METH_VARARGS, posix_read__doc__},
10978 : #ifdef HAVE_READV
10979 : {"readv", posix_readv, METH_VARARGS, posix_readv__doc__},
10980 : #endif
10981 : #ifdef HAVE_PREAD
10982 : {"pread", posix_pread, METH_VARARGS, posix_pread__doc__},
10983 : #endif
10984 : {"write", posix_write, METH_VARARGS, posix_write__doc__},
10985 : #ifdef HAVE_WRITEV
10986 : {"writev", posix_writev, METH_VARARGS, posix_writev__doc__},
10987 : #endif
10988 : #ifdef HAVE_PWRITE
10989 : {"pwrite", posix_pwrite, METH_VARARGS, posix_pwrite__doc__},
10990 : #endif
10991 : #ifdef HAVE_SENDFILE
10992 : {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS,
10993 : posix_sendfile__doc__},
10994 : #endif
10995 : {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__},
10996 : {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__},
10997 : #ifdef HAVE_PIPE
10998 : {"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__},
10999 : #endif
11000 : #ifdef HAVE_PIPE2
11001 : {"pipe2", posix_pipe2, METH_O, posix_pipe2__doc__},
11002 : #endif
11003 : #ifdef HAVE_MKFIFO
11004 : {"mkfifo", (PyCFunction)posix_mkfifo,
11005 : METH_VARARGS | METH_KEYWORDS,
11006 : posix_mkfifo__doc__},
11007 : #endif
11008 : #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
11009 : {"mknod", (PyCFunction)posix_mknod,
11010 : METH_VARARGS | METH_KEYWORDS,
11011 : posix_mknod__doc__},
11012 : #endif
11013 : #ifdef HAVE_DEVICE_MACROS
11014 : {"major", posix_major, METH_VARARGS, posix_major__doc__},
11015 : {"minor", posix_minor, METH_VARARGS, posix_minor__doc__},
11016 : {"makedev", posix_makedev, METH_VARARGS, posix_makedev__doc__},
11017 : #endif
11018 : #ifdef HAVE_FTRUNCATE
11019 : {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
11020 : #endif
11021 : #ifdef HAVE_TRUNCATE
11022 : {"truncate", (PyCFunction)posix_truncate,
11023 : METH_VARARGS | METH_KEYWORDS,
11024 : posix_truncate__doc__},
11025 : #endif
11026 : #ifdef HAVE_POSIX_FALLOCATE
11027 : {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__},
11028 : #endif
11029 : #ifdef HAVE_POSIX_FADVISE
11030 : {"posix_fadvise", posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__},
11031 : #endif
11032 : #ifdef HAVE_PUTENV
11033 : {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__},
11034 : #endif
11035 : #ifdef HAVE_UNSETENV
11036 : {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
11037 : #endif
11038 : {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__},
11039 : #ifdef HAVE_FCHDIR
11040 : {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__},
11041 : #endif
11042 : #ifdef HAVE_FSYNC
11043 : {"fsync", posix_fsync, METH_O, posix_fsync__doc__},
11044 : #endif
11045 : #ifdef HAVE_SYNC
11046 : {"sync", posix_sync, METH_NOARGS, posix_sync__doc__},
11047 : #endif
11048 : #ifdef HAVE_FDATASYNC
11049 : {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__},
11050 : #endif
11051 : #ifdef HAVE_SYS_WAIT_H
11052 : #ifdef WCOREDUMP
11053 : {"WCOREDUMP", posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
11054 : #endif /* WCOREDUMP */
11055 : #ifdef WIFCONTINUED
11056 : {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
11057 : #endif /* WIFCONTINUED */
11058 : #ifdef WIFSTOPPED
11059 : {"WIFSTOPPED", posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
11060 : #endif /* WIFSTOPPED */
11061 : #ifdef WIFSIGNALED
11062 : {"WIFSIGNALED", posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
11063 : #endif /* WIFSIGNALED */
11064 : #ifdef WIFEXITED
11065 : {"WIFEXITED", posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
11066 : #endif /* WIFEXITED */
11067 : #ifdef WEXITSTATUS
11068 : {"WEXITSTATUS", posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
11069 : #endif /* WEXITSTATUS */
11070 : #ifdef WTERMSIG
11071 : {"WTERMSIG", posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
11072 : #endif /* WTERMSIG */
11073 : #ifdef WSTOPSIG
11074 : {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
11075 : #endif /* WSTOPSIG */
11076 : #endif /* HAVE_SYS_WAIT_H */
11077 : #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11078 : {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
11079 : #endif
11080 : #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11081 : {"statvfs", (PyCFunction)posix_statvfs,
11082 : METH_VARARGS | METH_KEYWORDS,
11083 : posix_statvfs__doc__},
11084 : #endif
11085 : #ifdef HAVE_CONFSTR
11086 : {"confstr", posix_confstr, METH_VARARGS, posix_confstr__doc__},
11087 : #endif
11088 : #ifdef HAVE_SYSCONF
11089 : {"sysconf", posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
11090 : #endif
11091 : #ifdef HAVE_FPATHCONF
11092 : {"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
11093 : #endif
11094 : #ifdef HAVE_PATHCONF
11095 : {"pathconf", (PyCFunction)posix_pathconf,
11096 : METH_VARARGS | METH_KEYWORDS,
11097 : posix_pathconf__doc__},
11098 : #endif
11099 : {"abort", posix_abort, METH_NOARGS, posix_abort__doc__},
11100 : #ifdef MS_WINDOWS
11101 : {"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL},
11102 : {"_getfinalpathname", posix__getfinalpathname, METH_VARARGS, NULL},
11103 : {"_getfileinformation", posix__getfileinformation, METH_VARARGS, NULL},
11104 : {"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__},
11105 : {"_getdiskusage", win32__getdiskusage, METH_VARARGS, win32__getdiskusage__doc__},
11106 : #endif
11107 : #ifdef HAVE_GETLOADAVG
11108 : {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
11109 : #endif
11110 : {"urandom", posix_urandom, METH_VARARGS, posix_urandom__doc__},
11111 : #ifdef HAVE_SETRESUID
11112 : {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
11113 : #endif
11114 : #ifdef HAVE_SETRESGID
11115 : {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
11116 : #endif
11117 : #ifdef HAVE_GETRESUID
11118 : {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
11119 : #endif
11120 : #ifdef HAVE_GETRESGID
11121 : {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
11122 : #endif
11123 :
11124 : #ifdef USE_XATTRS
11125 : {"setxattr", (PyCFunction)posix_setxattr,
11126 : METH_VARARGS | METH_KEYWORDS,
11127 : posix_setxattr__doc__},
11128 : {"getxattr", (PyCFunction)posix_getxattr,
11129 : METH_VARARGS | METH_KEYWORDS,
11130 : posix_getxattr__doc__},
11131 : {"removexattr", (PyCFunction)posix_removexattr,
11132 : METH_VARARGS | METH_KEYWORDS,
11133 : posix_removexattr__doc__},
11134 : {"listxattr", (PyCFunction)posix_listxattr,
11135 : METH_VARARGS | METH_KEYWORDS,
11136 : posix_listxattr__doc__},
11137 : #endif
11138 : #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
11139 : {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__},
11140 : #endif
11141 : {NULL, NULL} /* Sentinel */
11142 : };
11143 :
11144 :
11145 : static int
11146 82 : ins(PyObject *module, char *symbol, long value)
11147 : {
11148 82 : return PyModule_AddIntConstant(module, symbol, value);
11149 : }
11150 :
11151 : #if defined(PYOS_OS2)
11152 : /* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
11153 : static int insertvalues(PyObject *module)
11154 : {
11155 : APIRET rc;
11156 : ULONG values[QSV_MAX+1];
11157 : PyObject *v;
11158 : char *ver, tmp[50];
11159 :
11160 : Py_BEGIN_ALLOW_THREADS
11161 : rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
11162 : Py_END_ALLOW_THREADS
11163 :
11164 : if (rc != NO_ERROR) {
11165 : os2_error(rc);
11166 : return -1;
11167 : }
11168 :
11169 : if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
11170 : if (ins(module, "memkernel", values[QSV_TOTRESMEM])) return -1;
11171 : if (ins(module, "memvirtual", values[QSV_TOTAVAILMEM])) return -1;
11172 : if (ins(module, "maxpathlen", values[QSV_MAX_PATH_LENGTH])) return -1;
11173 : if (ins(module, "maxnamelen", values[QSV_MAX_COMP_LENGTH])) return -1;
11174 : if (ins(module, "revision", values[QSV_VERSION_REVISION])) return -1;
11175 : if (ins(module, "timeslice", values[QSV_MIN_SLICE])) return -1;
11176 :
11177 : switch (values[QSV_VERSION_MINOR]) {
11178 : case 0: ver = "2.00"; break;
11179 : case 10: ver = "2.10"; break;
11180 : case 11: ver = "2.11"; break;
11181 : case 30: ver = "3.00"; break;
11182 : case 40: ver = "4.00"; break;
11183 : case 50: ver = "5.00"; break;
11184 : default:
11185 : PyOS_snprintf(tmp, sizeof(tmp),
11186 : "%d-%d", values[QSV_VERSION_MAJOR],
11187 : values[QSV_VERSION_MINOR]);
11188 : ver = &tmp[0];
11189 : }
11190 :
11191 : /* Add Indicator of the Version of the Operating System */
11192 : if (PyModule_AddStringConstant(module, "version", tmp) < 0)
11193 : return -1;
11194 :
11195 : /* Add Indicator of Which Drive was Used to Boot the System */
11196 : tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
11197 : tmp[1] = ':';
11198 : tmp[2] = '\0';
11199 :
11200 : return PyModule_AddStringConstant(module, "bootdrive", tmp);
11201 : }
11202 : #endif
11203 :
11204 : #if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
11205 : static int
11206 : enable_symlink()
11207 : {
11208 : HANDLE tok;
11209 : TOKEN_PRIVILEGES tok_priv;
11210 : LUID luid;
11211 : int meth_idx = 0;
11212 :
11213 : if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok))
11214 : return 0;
11215 :
11216 : if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid))
11217 : return 0;
11218 :
11219 : tok_priv.PrivilegeCount = 1;
11220 : tok_priv.Privileges[0].Luid = luid;
11221 : tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
11222 :
11223 : if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv,
11224 : sizeof(TOKEN_PRIVILEGES),
11225 : (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
11226 : return 0;
11227 :
11228 : /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */
11229 : return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1;
11230 : }
11231 : #endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
11232 :
11233 : static int
11234 1 : all_ins(PyObject *d)
11235 : {
11236 : #ifdef F_OK
11237 1 : if (ins(d, "F_OK", (long)F_OK)) return -1;
11238 : #endif
11239 : #ifdef R_OK
11240 1 : if (ins(d, "R_OK", (long)R_OK)) return -1;
11241 : #endif
11242 : #ifdef W_OK
11243 1 : if (ins(d, "W_OK", (long)W_OK)) return -1;
11244 : #endif
11245 : #ifdef X_OK
11246 1 : if (ins(d, "X_OK", (long)X_OK)) return -1;
11247 : #endif
11248 : #ifdef NGROUPS_MAX
11249 1 : if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
11250 : #endif
11251 : #ifdef TMP_MAX
11252 1 : if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
11253 : #endif
11254 : #ifdef WCONTINUED
11255 1 : if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
11256 : #endif
11257 : #ifdef WNOHANG
11258 1 : if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
11259 : #endif
11260 : #ifdef WUNTRACED
11261 1 : if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
11262 : #endif
11263 : #ifdef O_RDONLY
11264 1 : if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
11265 : #endif
11266 : #ifdef O_WRONLY
11267 1 : if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
11268 : #endif
11269 : #ifdef O_RDWR
11270 1 : if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
11271 : #endif
11272 : #ifdef O_NDELAY
11273 1 : if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
11274 : #endif
11275 : #ifdef O_NONBLOCK
11276 1 : if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
11277 : #endif
11278 : #ifdef O_APPEND
11279 1 : if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
11280 : #endif
11281 : #ifdef O_DSYNC
11282 1 : if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
11283 : #endif
11284 : #ifdef O_RSYNC
11285 1 : if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
11286 : #endif
11287 : #ifdef O_SYNC
11288 1 : if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
11289 : #endif
11290 : #ifdef O_NOCTTY
11291 1 : if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
11292 : #endif
11293 : #ifdef O_CREAT
11294 1 : if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
11295 : #endif
11296 : #ifdef O_EXCL
11297 1 : if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
11298 : #endif
11299 : #ifdef O_TRUNC
11300 1 : if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
11301 : #endif
11302 : #ifdef O_BINARY
11303 : if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
11304 : #endif
11305 : #ifdef O_TEXT
11306 : if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
11307 : #endif
11308 : #ifdef O_XATTR
11309 : if (ins(d, "O_XATTR", (long)O_XATTR)) return -1;
11310 : #endif
11311 : #ifdef O_LARGEFILE
11312 1 : if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
11313 : #endif
11314 : #ifdef O_SHLOCK
11315 : if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
11316 : #endif
11317 : #ifdef O_EXLOCK
11318 : if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
11319 : #endif
11320 : #ifdef O_EXEC
11321 : if (ins(d, "O_EXEC", (long)O_EXEC)) return -1;
11322 : #endif
11323 : #ifdef O_SEARCH
11324 : if (ins(d, "O_SEARCH", (long)O_SEARCH)) return -1;
11325 : #endif
11326 : #ifdef O_TTY_INIT
11327 : if (ins(d, "O_TTY_INIT", (long)O_TTY_INIT)) return -1;
11328 : #endif
11329 : #ifdef PRIO_PROCESS
11330 1 : if (ins(d, "PRIO_PROCESS", (long)PRIO_PROCESS)) return -1;
11331 : #endif
11332 : #ifdef PRIO_PGRP
11333 1 : if (ins(d, "PRIO_PGRP", (long)PRIO_PGRP)) return -1;
11334 : #endif
11335 : #ifdef PRIO_USER
11336 1 : if (ins(d, "PRIO_USER", (long)PRIO_USER)) return -1;
11337 : #endif
11338 : #ifdef O_CLOEXEC
11339 1 : if (ins(d, "O_CLOEXEC", (long)O_CLOEXEC)) return -1;
11340 : #endif
11341 : #ifdef O_ACCMODE
11342 1 : if (ins(d, "O_ACCMODE", (long)O_ACCMODE)) return -1;
11343 : #endif
11344 :
11345 :
11346 : #ifdef SEEK_HOLE
11347 1 : if (ins(d, "SEEK_HOLE", (long)SEEK_HOLE)) return -1;
11348 : #endif
11349 : #ifdef SEEK_DATA
11350 1 : if (ins(d, "SEEK_DATA", (long)SEEK_DATA)) return -1;
11351 : #endif
11352 :
11353 : /* MS Windows */
11354 : #ifdef O_NOINHERIT
11355 : /* Don't inherit in child processes. */
11356 : if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
11357 : #endif
11358 : #ifdef _O_SHORT_LIVED
11359 : /* Optimize for short life (keep in memory). */
11360 : /* MS forgot to define this one with a non-underscore form too. */
11361 : if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
11362 : #endif
11363 : #ifdef O_TEMPORARY
11364 : /* Automatically delete when last handle is closed. */
11365 : if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
11366 : #endif
11367 : #ifdef O_RANDOM
11368 : /* Optimize for random access. */
11369 : if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
11370 : #endif
11371 : #ifdef O_SEQUENTIAL
11372 : /* Optimize for sequential access. */
11373 : if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
11374 : #endif
11375 :
11376 : /* GNU extensions. */
11377 : #ifdef O_ASYNC
11378 : /* Send a SIGIO signal whenever input or output
11379 : becomes available on file descriptor */
11380 1 : if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
11381 : #endif
11382 : #ifdef O_DIRECT
11383 : /* Direct disk access. */
11384 1 : if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
11385 : #endif
11386 : #ifdef O_DIRECTORY
11387 : /* Must be a directory. */
11388 1 : if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
11389 : #endif
11390 : #ifdef O_NOFOLLOW
11391 : /* Do not follow links. */
11392 1 : if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
11393 : #endif
11394 : #ifdef O_NOLINKS
11395 : /* Fails if link count of the named file is greater than 1 */
11396 : if (ins(d, "O_NOLINKS", (long)O_NOLINKS)) return -1;
11397 : #endif
11398 : #ifdef O_NOATIME
11399 : /* Do not update the access time. */
11400 1 : if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
11401 : #endif
11402 :
11403 : /* These come from sysexits.h */
11404 : #ifdef EX_OK
11405 1 : if (ins(d, "EX_OK", (long)EX_OK)) return -1;
11406 : #endif /* EX_OK */
11407 : #ifdef EX_USAGE
11408 1 : if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
11409 : #endif /* EX_USAGE */
11410 : #ifdef EX_DATAERR
11411 1 : if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
11412 : #endif /* EX_DATAERR */
11413 : #ifdef EX_NOINPUT
11414 1 : if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
11415 : #endif /* EX_NOINPUT */
11416 : #ifdef EX_NOUSER
11417 1 : if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
11418 : #endif /* EX_NOUSER */
11419 : #ifdef EX_NOHOST
11420 1 : if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
11421 : #endif /* EX_NOHOST */
11422 : #ifdef EX_UNAVAILABLE
11423 1 : if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
11424 : #endif /* EX_UNAVAILABLE */
11425 : #ifdef EX_SOFTWARE
11426 1 : if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
11427 : #endif /* EX_SOFTWARE */
11428 : #ifdef EX_OSERR
11429 1 : if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
11430 : #endif /* EX_OSERR */
11431 : #ifdef EX_OSFILE
11432 1 : if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
11433 : #endif /* EX_OSFILE */
11434 : #ifdef EX_CANTCREAT
11435 1 : if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
11436 : #endif /* EX_CANTCREAT */
11437 : #ifdef EX_IOERR
11438 1 : if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
11439 : #endif /* EX_IOERR */
11440 : #ifdef EX_TEMPFAIL
11441 1 : if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
11442 : #endif /* EX_TEMPFAIL */
11443 : #ifdef EX_PROTOCOL
11444 1 : if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
11445 : #endif /* EX_PROTOCOL */
11446 : #ifdef EX_NOPERM
11447 1 : if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
11448 : #endif /* EX_NOPERM */
11449 : #ifdef EX_CONFIG
11450 1 : if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
11451 : #endif /* EX_CONFIG */
11452 : #ifdef EX_NOTFOUND
11453 : if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
11454 : #endif /* EX_NOTFOUND */
11455 :
11456 : /* statvfs */
11457 : #ifdef ST_RDONLY
11458 1 : if (ins(d, "ST_RDONLY", (long)ST_RDONLY)) return -1;
11459 : #endif /* ST_RDONLY */
11460 : #ifdef ST_NOSUID
11461 1 : if (ins(d, "ST_NOSUID", (long)ST_NOSUID)) return -1;
11462 : #endif /* ST_NOSUID */
11463 :
11464 : /* FreeBSD sendfile() constants */
11465 : #ifdef SF_NODISKIO
11466 : if (ins(d, "SF_NODISKIO", (long)SF_NODISKIO)) return -1;
11467 : #endif
11468 : #ifdef SF_MNOWAIT
11469 : if (ins(d, "SF_MNOWAIT", (long)SF_MNOWAIT)) return -1;
11470 : #endif
11471 : #ifdef SF_SYNC
11472 : if (ins(d, "SF_SYNC", (long)SF_SYNC)) return -1;
11473 : #endif
11474 :
11475 : /* constants for posix_fadvise */
11476 : #ifdef POSIX_FADV_NORMAL
11477 1 : if (ins(d, "POSIX_FADV_NORMAL", (long)POSIX_FADV_NORMAL)) return -1;
11478 : #endif
11479 : #ifdef POSIX_FADV_SEQUENTIAL
11480 1 : if (ins(d, "POSIX_FADV_SEQUENTIAL", (long)POSIX_FADV_SEQUENTIAL)) return -1;
11481 : #endif
11482 : #ifdef POSIX_FADV_RANDOM
11483 1 : if (ins(d, "POSIX_FADV_RANDOM", (long)POSIX_FADV_RANDOM)) return -1;
11484 : #endif
11485 : #ifdef POSIX_FADV_NOREUSE
11486 1 : if (ins(d, "POSIX_FADV_NOREUSE", (long)POSIX_FADV_NOREUSE)) return -1;
11487 : #endif
11488 : #ifdef POSIX_FADV_WILLNEED
11489 1 : if (ins(d, "POSIX_FADV_WILLNEED", (long)POSIX_FADV_WILLNEED)) return -1;
11490 : #endif
11491 : #ifdef POSIX_FADV_DONTNEED
11492 1 : if (ins(d, "POSIX_FADV_DONTNEED", (long)POSIX_FADV_DONTNEED)) return -1;
11493 : #endif
11494 :
11495 : /* constants for waitid */
11496 : #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
11497 1 : if (ins(d, "P_PID", (long)P_PID)) return -1;
11498 1 : if (ins(d, "P_PGID", (long)P_PGID)) return -1;
11499 1 : if (ins(d, "P_ALL", (long)P_ALL)) return -1;
11500 : #endif
11501 : #ifdef WEXITED
11502 1 : if (ins(d, "WEXITED", (long)WEXITED)) return -1;
11503 : #endif
11504 : #ifdef WNOWAIT
11505 1 : if (ins(d, "WNOWAIT", (long)WNOWAIT)) return -1;
11506 : #endif
11507 : #ifdef WSTOPPED
11508 1 : if (ins(d, "WSTOPPED", (long)WSTOPPED)) return -1;
11509 : #endif
11510 : #ifdef CLD_EXITED
11511 1 : if (ins(d, "CLD_EXITED", (long)CLD_EXITED)) return -1;
11512 : #endif
11513 : #ifdef CLD_DUMPED
11514 1 : if (ins(d, "CLD_DUMPED", (long)CLD_DUMPED)) return -1;
11515 : #endif
11516 : #ifdef CLD_TRAPPED
11517 1 : if (ins(d, "CLD_TRAPPED", (long)CLD_TRAPPED)) return -1;
11518 : #endif
11519 : #ifdef CLD_CONTINUED
11520 1 : if (ins(d, "CLD_CONTINUED", (long)CLD_CONTINUED)) return -1;
11521 : #endif
11522 :
11523 : /* constants for lockf */
11524 : #ifdef F_LOCK
11525 1 : if (ins(d, "F_LOCK", (long)F_LOCK)) return -1;
11526 : #endif
11527 : #ifdef F_TLOCK
11528 1 : if (ins(d, "F_TLOCK", (long)F_TLOCK)) return -1;
11529 : #endif
11530 : #ifdef F_ULOCK
11531 1 : if (ins(d, "F_ULOCK", (long)F_ULOCK)) return -1;
11532 : #endif
11533 : #ifdef F_TEST
11534 1 : if (ins(d, "F_TEST", (long)F_TEST)) return -1;
11535 : #endif
11536 :
11537 : #ifdef HAVE_SPAWNV
11538 : #if defined(PYOS_OS2) && defined(PYCC_GCC)
11539 : if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
11540 : if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
11541 : if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
11542 : if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
11543 : if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
11544 : if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
11545 : if (ins(d, "P_PM", (long)P_PM)) return -1;
11546 : if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
11547 : if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
11548 : if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
11549 : if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
11550 : if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
11551 : if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
11552 : if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
11553 : if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
11554 : if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
11555 : if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
11556 : if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
11557 : if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
11558 : if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
11559 : #else
11560 : if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
11561 : if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
11562 : if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
11563 : if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
11564 : if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
11565 : #endif
11566 : #endif
11567 :
11568 : #ifdef HAVE_SCHED_H
11569 1 : if (ins(d, "SCHED_OTHER", (long)SCHED_OTHER)) return -1;
11570 1 : if (ins(d, "SCHED_FIFO", (long)SCHED_FIFO)) return -1;
11571 1 : if (ins(d, "SCHED_RR", (long)SCHED_RR)) return -1;
11572 : #ifdef SCHED_SPORADIC
11573 : if (ins(d, "SCHED_SPORADIC", (long)SCHED_SPORADIC) return -1;
11574 : #endif
11575 : #ifdef SCHED_BATCH
11576 1 : if (ins(d, "SCHED_BATCH", (long)SCHED_BATCH)) return -1;
11577 : #endif
11578 : #ifdef SCHED_IDLE
11579 1 : if (ins(d, "SCHED_IDLE", (long)SCHED_IDLE)) return -1;
11580 : #endif
11581 : #ifdef SCHED_RESET_ON_FORK
11582 1 : if (ins(d, "SCHED_RESET_ON_FORK", (long)SCHED_RESET_ON_FORK)) return -1;
11583 : #endif
11584 : #ifdef SCHED_SYS
11585 : if (ins(d, "SCHED_SYS", (long)SCHED_SYS)) return -1;
11586 : #endif
11587 : #ifdef SCHED_IA
11588 : if (ins(d, "SCHED_IA", (long)SCHED_IA)) return -1;
11589 : #endif
11590 : #ifdef SCHED_FSS
11591 : if (ins(d, "SCHED_FSS", (long)SCHED_FSS)) return -1;
11592 : #endif
11593 : #ifdef SCHED_FX
11594 : if (ins(d, "SCHED_FX", (long)SCHED_FSS)) return -1;
11595 : #endif
11596 : #endif
11597 :
11598 : #ifdef USE_XATTRS
11599 1 : if (ins(d, "XATTR_CREATE", (long)XATTR_CREATE)) return -1;
11600 1 : if (ins(d, "XATTR_REPLACE", (long)XATTR_REPLACE)) return -1;
11601 1 : if (ins(d, "XATTR_SIZE_MAX", (long)XATTR_SIZE_MAX)) return -1;
11602 : #endif
11603 :
11604 : #ifdef RTLD_LAZY
11605 1 : if (PyModule_AddIntMacro(d, RTLD_LAZY)) return -1;
11606 : #endif
11607 : #ifdef RTLD_NOW
11608 1 : if (PyModule_AddIntMacro(d, RTLD_NOW)) return -1;
11609 : #endif
11610 : #ifdef RTLD_GLOBAL
11611 1 : if (PyModule_AddIntMacro(d, RTLD_GLOBAL)) return -1;
11612 : #endif
11613 : #ifdef RTLD_LOCAL
11614 1 : if (PyModule_AddIntMacro(d, RTLD_LOCAL)) return -1;
11615 : #endif
11616 : #ifdef RTLD_NODELETE
11617 1 : if (PyModule_AddIntMacro(d, RTLD_NODELETE)) return -1;
11618 : #endif
11619 : #ifdef RTLD_NOLOAD
11620 1 : if (PyModule_AddIntMacro(d, RTLD_NOLOAD)) return -1;
11621 : #endif
11622 : #ifdef RTLD_DEEPBIND
11623 1 : if (PyModule_AddIntMacro(d, RTLD_DEEPBIND)) return -1;
11624 : #endif
11625 :
11626 : #if defined(PYOS_OS2)
11627 : if (insertvalues(d)) return -1;
11628 : #endif
11629 1 : return 0;
11630 : }
11631 :
11632 :
11633 : #if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
11634 : #define INITFUNC PyInit_nt
11635 : #define MODNAME "nt"
11636 :
11637 : #elif defined(PYOS_OS2)
11638 : #define INITFUNC PyInit_os2
11639 : #define MODNAME "os2"
11640 :
11641 : #else
11642 : #define INITFUNC PyInit_posix
11643 : #define MODNAME "posix"
11644 : #endif
11645 :
11646 : static struct PyModuleDef posixmodule = {
11647 : PyModuleDef_HEAD_INIT,
11648 : MODNAME,
11649 : posix__doc__,
11650 : -1,
11651 : posix_methods,
11652 : NULL,
11653 : NULL,
11654 : NULL,
11655 : NULL
11656 : };
11657 :
11658 :
11659 : static char *have_functions[] = {
11660 :
11661 : #ifdef HAVE_FACCESSAT
11662 : "HAVE_FACCESSAT",
11663 : #endif
11664 :
11665 : #ifdef HAVE_FCHDIR
11666 : "HAVE_FCHDIR",
11667 : #endif
11668 :
11669 : #ifdef HAVE_FCHMOD
11670 : "HAVE_FCHMOD",
11671 : #endif
11672 :
11673 : #ifdef HAVE_FCHMODAT
11674 : "HAVE_FCHMODAT",
11675 : #endif
11676 :
11677 : #ifdef HAVE_FCHOWN
11678 : "HAVE_FCHOWN",
11679 : #endif
11680 :
11681 : #ifdef HAVE_FEXECVE
11682 : "HAVE_FEXECVE",
11683 : #endif
11684 :
11685 : #ifdef HAVE_FDOPENDIR
11686 : "HAVE_FDOPENDIR",
11687 : #endif
11688 :
11689 : #ifdef HAVE_FPATHCONF
11690 : "HAVE_FPATHCONF",
11691 : #endif
11692 :
11693 : #ifdef HAVE_FSTATAT
11694 : "HAVE_FSTATAT",
11695 : #endif
11696 :
11697 : #ifdef HAVE_FSTATVFS
11698 : "HAVE_FSTATVFS",
11699 : #endif
11700 :
11701 : #ifdef HAVE_FTRUNCATE
11702 : "HAVE_FTRUNCATE",
11703 : #endif
11704 :
11705 : #ifdef HAVE_FUTIMENS
11706 : "HAVE_FUTIMENS",
11707 : #endif
11708 :
11709 : #ifdef HAVE_FUTIMES
11710 : "HAVE_FUTIMES",
11711 : #endif
11712 :
11713 : #ifdef HAVE_FUTIMESAT
11714 : "HAVE_FUTIMESAT",
11715 : #endif
11716 :
11717 : #ifdef HAVE_LINKAT
11718 : "HAVE_LINKAT",
11719 : #endif
11720 :
11721 : #ifdef HAVE_LCHFLAGS
11722 : "HAVE_LCHFLAGS",
11723 : #endif
11724 :
11725 : #ifdef HAVE_LCHMOD
11726 : "HAVE_LCHMOD",
11727 : #endif
11728 :
11729 : #ifdef HAVE_LCHOWN
11730 : "HAVE_LCHOWN",
11731 : #endif
11732 :
11733 : #ifdef HAVE_LSTAT
11734 : "HAVE_LSTAT",
11735 : #endif
11736 :
11737 : #ifdef HAVE_LUTIMES
11738 : "HAVE_LUTIMES",
11739 : #endif
11740 :
11741 : #ifdef HAVE_MKDIRAT
11742 : "HAVE_MKDIRAT",
11743 : #endif
11744 :
11745 : #ifdef HAVE_MKFIFOAT
11746 : "HAVE_MKFIFOAT",
11747 : #endif
11748 :
11749 : #ifdef HAVE_MKNODAT
11750 : "HAVE_MKNODAT",
11751 : #endif
11752 :
11753 : #ifdef HAVE_OPENAT
11754 : "HAVE_OPENAT",
11755 : #endif
11756 :
11757 : #ifdef HAVE_READLINKAT
11758 : "HAVE_READLINKAT",
11759 : #endif
11760 :
11761 : #ifdef HAVE_RENAMEAT
11762 : "HAVE_RENAMEAT",
11763 : #endif
11764 :
11765 : #ifdef HAVE_SYMLINKAT
11766 : "HAVE_SYMLINKAT",
11767 : #endif
11768 :
11769 : #ifdef HAVE_UNLINKAT
11770 : "HAVE_UNLINKAT",
11771 : #endif
11772 :
11773 : #ifdef HAVE_UTIMENSAT
11774 : "HAVE_UTIMENSAT",
11775 : #endif
11776 :
11777 : #ifdef MS_WINDOWS
11778 : "MS_WINDOWS",
11779 : #endif
11780 :
11781 : NULL
11782 : };
11783 :
11784 :
11785 : PyMODINIT_FUNC
11786 1 : INITFUNC(void)
11787 : {
11788 : PyObject *m, *v;
11789 : PyObject *list;
11790 : char **trace;
11791 :
11792 : #if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
11793 : win32_can_symlink = enable_symlink();
11794 : #endif
11795 :
11796 1 : m = PyModule_Create(&posixmodule);
11797 1 : if (m == NULL)
11798 0 : return NULL;
11799 :
11800 : /* Initialize environ dictionary */
11801 1 : v = convertenviron();
11802 1 : Py_XINCREF(v);
11803 1 : if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
11804 0 : return NULL;
11805 1 : Py_DECREF(v);
11806 :
11807 1 : if (all_ins(m))
11808 0 : return NULL;
11809 :
11810 1 : if (setup_confname_tables(m))
11811 0 : return NULL;
11812 :
11813 1 : Py_INCREF(PyExc_OSError);
11814 1 : PyModule_AddObject(m, "error", PyExc_OSError);
11815 :
11816 : #ifdef HAVE_PUTENV
11817 1 : if (posix_putenv_garbage == NULL)
11818 1 : posix_putenv_garbage = PyDict_New();
11819 : #endif
11820 :
11821 1 : if (!initialized) {
11822 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
11823 1 : waitid_result_desc.name = MODNAME ".waitid_result";
11824 1 : PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc);
11825 : #endif
11826 :
11827 1 : stat_result_desc.name = MODNAME ".stat_result";
11828 1 : stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
11829 1 : stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
11830 1 : stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
11831 1 : PyStructSequence_InitType(&StatResultType, &stat_result_desc);
11832 1 : structseq_new = StatResultType.tp_new;
11833 1 : StatResultType.tp_new = statresult_new;
11834 :
11835 1 : statvfs_result_desc.name = MODNAME ".statvfs_result";
11836 1 : PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
11837 : #ifdef NEED_TICKS_PER_SECOND
11838 : # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
11839 1 : ticks_per_second = sysconf(_SC_CLK_TCK);
11840 : # elif defined(HZ)
11841 : ticks_per_second = HZ;
11842 : # else
11843 : ticks_per_second = 60; /* magic fallback value; may be bogus */
11844 : # endif
11845 : #endif
11846 :
11847 : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
11848 1 : sched_param_desc.name = MODNAME ".sched_param";
11849 1 : PyStructSequence_InitType(&SchedParamType, &sched_param_desc);
11850 1 : SchedParamType.tp_new = sched_param_new;
11851 : #endif
11852 :
11853 : /* initialize TerminalSize_info */
11854 1 : PyStructSequence_InitType(&TerminalSizeType, &TerminalSize_desc);
11855 : }
11856 : #if defined(HAVE_WAITID) && !defined(__APPLE__)
11857 1 : Py_INCREF((PyObject*) &WaitidResultType);
11858 1 : PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType);
11859 : #endif
11860 1 : Py_INCREF((PyObject*) &StatResultType);
11861 1 : PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
11862 1 : Py_INCREF((PyObject*) &StatVFSResultType);
11863 1 : PyModule_AddObject(m, "statvfs_result",
11864 : (PyObject*) &StatVFSResultType);
11865 :
11866 : #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER)
11867 1 : Py_INCREF(&SchedParamType);
11868 1 : PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType);
11869 : #endif
11870 :
11871 1 : times_result_desc.name = MODNAME ".times_result";
11872 1 : PyStructSequence_InitType(&TimesResultType, ×_result_desc);
11873 1 : PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType);
11874 :
11875 1 : uname_result_desc.name = MODNAME ".uname_result";
11876 1 : PyStructSequence_InitType(&UnameResultType, &uname_result_desc);
11877 1 : PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType);
11878 :
11879 : #ifdef __APPLE__
11880 : /*
11881 : * Step 2 of weak-linking support on Mac OS X.
11882 : *
11883 : * The code below removes functions that are not available on the
11884 : * currently active platform.
11885 : *
11886 : * This block allow one to use a python binary that was build on
11887 : * OSX 10.4 on OSX 10.3, without losing access to new APIs on
11888 : * OSX 10.4.
11889 : */
11890 : #ifdef HAVE_FSTATVFS
11891 : if (fstatvfs == NULL) {
11892 : if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
11893 : return NULL;
11894 : }
11895 : }
11896 : #endif /* HAVE_FSTATVFS */
11897 :
11898 : #ifdef HAVE_STATVFS
11899 : if (statvfs == NULL) {
11900 : if (PyObject_DelAttrString(m, "statvfs") == -1) {
11901 : return NULL;
11902 : }
11903 : }
11904 : #endif /* HAVE_STATVFS */
11905 :
11906 : # ifdef HAVE_LCHOWN
11907 : if (lchown == NULL) {
11908 : if (PyObject_DelAttrString(m, "lchown") == -1) {
11909 : return NULL;
11910 : }
11911 : }
11912 : #endif /* HAVE_LCHOWN */
11913 :
11914 :
11915 : #endif /* __APPLE__ */
11916 :
11917 1 : Py_INCREF(&TerminalSizeType);
11918 1 : PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType);
11919 :
11920 1 : billion = PyLong_FromLong(1000000000);
11921 1 : if (!billion)
11922 0 : return NULL;
11923 :
11924 : /* suppress "function not used" warnings */
11925 : {
11926 : int ignored;
11927 1 : fd_specified("", -1);
11928 1 : follow_symlinks_specified("", 1);
11929 1 : dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
11930 1 : dir_fd_converter(Py_None, &ignored);
11931 1 : dir_fd_unavailable(Py_None, &ignored);
11932 : }
11933 :
11934 : /*
11935 : * provide list of locally available functions
11936 : * so os.py can populate support_* lists
11937 : */
11938 1 : list = PyList_New(0);
11939 1 : if (!list)
11940 0 : return NULL;
11941 28 : for (trace = have_functions; *trace; trace++) {
11942 27 : PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL);
11943 27 : if (!unicode)
11944 0 : return NULL;
11945 27 : if (PyList_Append(list, unicode))
11946 0 : return NULL;
11947 27 : Py_DECREF(unicode);
11948 : }
11949 1 : PyModule_AddObject(m, "_have_functions", list);
11950 :
11951 1 : initialized = 1;
11952 :
11953 1 : return m;
11954 :
11955 : }
11956 :
11957 : #ifdef __cplusplus
11958 : }
11959 : #endif
|