1 /* POSIX module implementation */
2 
3 /* This file is also used for Windows NT/MS-Win.  In that case the
4    module actually calls itself 'nt', not 'posix', and a few
5    functions are either unimplemented or implemented differently.  The source
6    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
7    of the compiler used.  Different compilers define their own feature
8    test macro, e.g. '_MSC_VER'. */
9 
10 #define PY_SSIZE_T_CLEAN
11 
12 #include "Python.h"
13 #include "pycore_fileutils.h"
14 #include "pycore_moduleobject.h"  // _PyModule_GetState()
15 #ifdef MS_WINDOWS
16    /* include <windows.h> early to avoid conflict with pycore_condvar.h:
17 
18         #define WIN32_LEAN_AND_MEAN
19         #include <windows.h>
20 
21       FSCTL_GET_REPARSE_POINT is not exported with WIN32_LEAN_AND_MEAN. */
22 #  include <windows.h>
23 #  include <pathcch.h>
24 #endif
25 
26 #ifdef __VXWORKS__
27 #  include "pycore_bitutils.h"    // _Py_popcount32()
28 #endif
29 #include "pycore_ceval.h"         // _PyEval_ReInitThreads()
30 #include "pycore_import.h"        // _PyImport_ReInitLock()
31 #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
32 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
33 #include "structmember.h"         // PyMemberDef
34 #ifndef MS_WINDOWS
35 #  include "posixmodule.h"
36 #else
37 #  include "winreparse.h"
38 #endif
39 
40 /* On android API level 21, 'AT_EACCESS' is not declared although
41  * HAVE_FACCESSAT is defined. */
42 #ifdef __ANDROID__
43 #  undef HAVE_FACCESSAT
44 #endif
45 
46 #include <stdio.h>  /* needed for ctermid() */
47 
48 /*
49  * A number of APIs are available on macOS from a certain macOS version.
50  * To support building with a new SDK while deploying to older versions
51  * the availability test is split into two:
52  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
53  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
54  *
55  * The latter is always true when not on macOS, or when using a compiler
56  * that does not support __has_builtin (older versions of Xcode).
57  *
58  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
59  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
60  *
61  * In mixing the test with other tests or using negations will result in compile
62  * errors.
63  */
64 #if defined(__APPLE__)
65 
66 #if defined(__has_builtin)
67 #if __has_builtin(__builtin_available)
68 #define HAVE_BUILTIN_AVAILABLE 1
69 #endif
70 #endif
71 
72 #ifdef HAVE_BUILTIN_AVAILABLE
73 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
74 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
75 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
76 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
77 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
78 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
79 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
80 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
81 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
82 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
86 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
87 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
88 
89 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
90 
91 #else /* Xcode 8 or earlier */
92 
93    /* __builtin_available is not present in these compilers, but
94     * some of the symbols might be weak linked (10.10 SDK or later
95     * deploying on 10.9.
96     *
97     * Fall back to the older style of availability checking for
98     * symbols introduced in macOS 10.10.
99     */
100 
101 #  ifdef HAVE_FSTATAT
102 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
103 #  endif
104 
105 #  ifdef HAVE_FACCESSAT
106 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
107 #  endif
108 
109 #  ifdef HAVE_FCHMODAT
110 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
111 #  endif
112 
113 #  ifdef HAVE_FCHOWNAT
114 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
115 #  endif
116 
117 #  ifdef HAVE_LINKAT
118 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
119 #  endif
120 
121 #  ifdef HAVE_FDOPENDIR
122 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
123 #  endif
124 
125 #  ifdef HAVE_MKDIRAT
126 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
127 #  endif
128 
129 #  ifdef HAVE_RENAMEAT
130 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
131 #  endif
132 
133 #  ifdef HAVE_UNLINKAT
134 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
135 #  endif
136 
137 #  ifdef HAVE_OPENAT
138 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
139 #  endif
140 
141 #  ifdef HAVE_READLINKAT
142 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
143 #  endif
144 
145 #  ifdef HAVE_SYMLINKAT
146 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
147 #  endif
148 
149 #endif
150 
151 #ifdef HAVE_FUTIMESAT
152 /* Some of the logic for weak linking depends on this assertion */
153 # error "HAVE_FUTIMESAT unexpectedly defined"
154 #endif
155 
156 #else
157 #  define HAVE_FSTATAT_RUNTIME 1
158 #  define HAVE_FACCESSAT_RUNTIME 1
159 #  define HAVE_FCHMODAT_RUNTIME 1
160 #  define HAVE_FCHOWNAT_RUNTIME 1
161 #  define HAVE_LINKAT_RUNTIME 1
162 #  define HAVE_FDOPENDIR_RUNTIME 1
163 #  define HAVE_MKDIRAT_RUNTIME 1
164 #  define HAVE_RENAMEAT_RUNTIME 1
165 #  define HAVE_UNLINKAT_RUNTIME 1
166 #  define HAVE_OPENAT_RUNTIME 1
167 #  define HAVE_READLINKAT_RUNTIME 1
168 #  define HAVE_SYMLINKAT_RUNTIME 1
169 #  define HAVE_FUTIMENS_RUNTIME 1
170 #  define HAVE_UTIMENSAT_RUNTIME 1
171 #  define HAVE_PWRITEV_RUNTIME 1
172 #endif
173 
174 
175 #ifdef __cplusplus
176 extern "C" {
177 #endif
178 
179 PyDoc_STRVAR(posix__doc__,
180 "This module provides access to operating system functionality that is\n\
181 standardized by the C Standard and the POSIX standard (a thinly\n\
182 disguised Unix interface).  Refer to the library manual and\n\
183 corresponding Unix manual entries for more information on calls.");
184 
185 
186 #ifdef HAVE_SYS_UIO_H
187 #  include <sys/uio.h>
188 #endif
189 
190 #ifdef HAVE_SYS_SYSMACROS_H
191 /* GNU C Library: major(), minor(), makedev() */
192 #  include <sys/sysmacros.h>
193 #endif
194 
195 #ifdef HAVE_SYS_TYPES_H
196 #  include <sys/types.h>
197 #endif /* HAVE_SYS_TYPES_H */
198 
199 #ifdef HAVE_SYS_STAT_H
200 #  include <sys/stat.h>
201 #endif /* HAVE_SYS_STAT_H */
202 
203 #ifdef HAVE_SYS_WAIT_H
204 #  include <sys/wait.h>           // WNOHANG
205 #endif
206 #ifdef HAVE_LINUX_WAIT_H
207 #  include <linux/wait.h>         // P_PIDFD
208 #endif
209 
210 #ifdef HAVE_SIGNAL_H
211 #  include <signal.h>
212 #endif
213 
214 #ifdef HAVE_FCNTL_H
215 #  include <fcntl.h>
216 #endif
217 
218 #ifdef HAVE_GRP_H
219 #  include <grp.h>
220 #endif
221 
222 #ifdef HAVE_SYSEXITS_H
223 #  include <sysexits.h>
224 #endif
225 
226 #ifdef HAVE_SYS_LOADAVG_H
227 #  include <sys/loadavg.h>
228 #endif
229 
230 #ifdef HAVE_SYS_SENDFILE_H
231 #  include <sys/sendfile.h>
232 #endif
233 
234 #if defined(__APPLE__)
235 #  include <copyfile.h>
236 #endif
237 
238 #ifdef HAVE_SCHED_H
239 #  include <sched.h>
240 #endif
241 
242 #ifdef HAVE_COPY_FILE_RANGE
243 #  include <unistd.h>
244 #endif
245 
246 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
247 #  undef HAVE_SCHED_SETAFFINITY
248 #endif
249 
250 #if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
251 #  define USE_XATTRS
252 #endif
253 
254 #ifdef USE_XATTRS
255 #  include <sys/xattr.h>
256 #endif
257 
258 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
259 #  ifdef HAVE_SYS_SOCKET_H
260 #    include <sys/socket.h>
261 #  endif
262 #endif
263 
264 #ifdef HAVE_DLFCN_H
265 #  include <dlfcn.h>
266 #endif
267 
268 #ifdef __hpux
269 #  include <sys/mpctl.h>
270 #endif
271 
272 #if defined(__DragonFly__) || \
273     defined(__OpenBSD__)   || \
274     defined(__FreeBSD__)   || \
275     defined(__NetBSD__)    || \
276     defined(__APPLE__)
277 #  include <sys/sysctl.h>
278 #endif
279 
280 #ifdef HAVE_LINUX_RANDOM_H
281 #  include <linux/random.h>
282 #endif
283 #ifdef HAVE_GETRANDOM_SYSCALL
284 #  include <sys/syscall.h>
285 #endif
286 
287 #if defined(MS_WINDOWS)
288 #  define TERMSIZE_USE_CONIO
289 #elif defined(HAVE_SYS_IOCTL_H)
290 #  include <sys/ioctl.h>
291 #  if defined(HAVE_TERMIOS_H)
292 #    include <termios.h>
293 #  endif
294 #  if defined(TIOCGWINSZ)
295 #    define TERMSIZE_USE_IOCTL
296 #  endif
297 #endif /* MS_WINDOWS */
298 
299 /* Various compilers have only certain posix functions */
300 /* XXX Gosh I wish these were all moved into pyconfig.h */
301 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
302 #  define HAVE_OPENDIR    1
303 #  define HAVE_SYSTEM     1
304 #  include <process.h>
305 #else
306 #  ifdef _MSC_VER
307      /* Microsoft compiler */
308 #    define HAVE_GETPPID    1
309 #    define HAVE_GETLOGIN   1
310 #    define HAVE_SPAWNV     1
311 #    define HAVE_EXECV      1
312 #    define HAVE_WSPAWNV    1
313 #    define HAVE_WEXECV     1
314 #    define HAVE_PIPE       1
315 #    define HAVE_SYSTEM     1
316 #    define HAVE_CWAIT      1
317 #    define HAVE_FSYNC      1
318 #    define fsync _commit
319 #  else
320      /* Unix functions that the configure script doesn't check for */
321 #    ifndef __VXWORKS__
322 #      define HAVE_EXECV      1
323 #      define HAVE_FORK       1
324 #      if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
325 #        define HAVE_FORK1      1
326 #      endif
327 #    endif
328 #    define HAVE_GETEGID    1
329 #    define HAVE_GETEUID    1
330 #    define HAVE_GETGID     1
331 #    define HAVE_GETPPID    1
332 #    define HAVE_GETUID     1
333 #    define HAVE_KILL       1
334 #    define HAVE_OPENDIR    1
335 #    define HAVE_PIPE       1
336 #    define HAVE_SYSTEM     1
337 #    define HAVE_WAIT       1
338 #    define HAVE_TTYNAME    1
339 #  endif  /* _MSC_VER */
340 #endif  /* ! __WATCOMC__ || __QNX__ */
341 
342 _Py_IDENTIFIER(__fspath__);
343 
344 /*[clinic input]
345 # one of the few times we lie about this name!
346 module os
347 [clinic start generated code]*/
348 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
349 
350 #ifndef _MSC_VER
351 
352 #if defined(__sgi)&&_COMPILER_VERSION>=700
353 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
354    (default) */
355 extern char        *ctermid_r(char *);
356 #endif
357 
358 #endif /* !_MSC_VER */
359 
360 #if defined(__VXWORKS__)
361 #  include <vxCpuLib.h>
362 #  include <rtpLib.h>
363 #  include <wait.h>
364 #  include <taskLib.h>
365 #  ifndef _P_WAIT
366 #    define _P_WAIT          0
367 #    define _P_NOWAIT        1
368 #    define _P_NOWAITO       1
369 #  endif
370 #endif /* __VXWORKS__ */
371 
372 #ifdef HAVE_POSIX_SPAWN
373 #  include <spawn.h>
374 #endif
375 
376 #ifdef HAVE_UTIME_H
377 #  include <utime.h>
378 #endif /* HAVE_UTIME_H */
379 
380 #ifdef HAVE_SYS_UTIME_H
381 #  include <sys/utime.h>
382 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
383 #endif /* HAVE_SYS_UTIME_H */
384 
385 #ifdef HAVE_SYS_TIMES_H
386 #  include <sys/times.h>
387 #endif /* HAVE_SYS_TIMES_H */
388 
389 #ifdef HAVE_SYS_PARAM_H
390 #  include <sys/param.h>
391 #endif /* HAVE_SYS_PARAM_H */
392 
393 #ifdef HAVE_SYS_UTSNAME_H
394 #  include <sys/utsname.h>
395 #endif /* HAVE_SYS_UTSNAME_H */
396 
397 #ifdef HAVE_DIRENT_H
398 #  include <dirent.h>
399 #  define NAMLEN(dirent) strlen((dirent)->d_name)
400 #else
401 #  if defined(__WATCOMC__) && !defined(__QNX__)
402 #    include <direct.h>
403 #    define NAMLEN(dirent) strlen((dirent)->d_name)
404 #  else
405 #    define dirent direct
406 #    define NAMLEN(dirent) (dirent)->d_namlen
407 #  endif
408 #  ifdef HAVE_SYS_NDIR_H
409 #    include <sys/ndir.h>
410 #  endif
411 #  ifdef HAVE_SYS_DIR_H
412 #    include <sys/dir.h>
413 #  endif
414 #  ifdef HAVE_NDIR_H
415 #    include <ndir.h>
416 #  endif
417 #endif
418 
419 #ifdef _MSC_VER
420 #  ifdef HAVE_DIRECT_H
421 #    include <direct.h>
422 #  endif
423 #  ifdef HAVE_IO_H
424 #    include <io.h>
425 #  endif
426 #  ifdef HAVE_PROCESS_H
427 #    include <process.h>
428 #  endif
429 #  ifndef IO_REPARSE_TAG_SYMLINK
430 #    define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
431 #  endif
432 #  ifndef IO_REPARSE_TAG_MOUNT_POINT
433 #    define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L)
434 #  endif
435 #  include "osdefs.h"             // SEP
436 #  include <malloc.h>
437 #  include <windows.h>
438 #  include <shellapi.h>           // ShellExecute()
439 #  include <lmcons.h>             // UNLEN
440 #  define HAVE_SYMLINK
441 #endif /* _MSC_VER */
442 
443 #ifndef MAXPATHLEN
444 #  if defined(PATH_MAX) && PATH_MAX > 1024
445 #    define MAXPATHLEN PATH_MAX
446 #  else
447 #    define MAXPATHLEN 1024
448 #  endif
449 #endif /* MAXPATHLEN */
450 
451 #ifdef UNION_WAIT
452    /* Emulate some macros on systems that have a union instead of macros */
453 #  ifndef WIFEXITED
454 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
455 #  endif
456 #  ifndef WEXITSTATUS
457 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
458 #  endif
459 #  ifndef WTERMSIG
460 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
461 #  endif
462 #  define WAIT_TYPE union wait
463 #  define WAIT_STATUS_INT(s) (s.w_status)
464 #else
465    /* !UNION_WAIT */
466 #  define WAIT_TYPE int
467 #  define WAIT_STATUS_INT(s) (s)
468 #endif /* UNION_WAIT */
469 
470 /* Don't use the "_r" form if we don't need it (also, won't have a
471    prototype for it, at least on Solaris -- maybe others as well?). */
472 #if defined(HAVE_CTERMID_R)
473 #  define USE_CTERMID_R
474 #endif
475 
476 /* choose the appropriate stat and fstat functions and return structs */
477 #undef STAT
478 #undef FSTAT
479 #undef STRUCT_STAT
480 #ifdef MS_WINDOWS
481 #  define STAT win32_stat
482 #  define LSTAT win32_lstat
483 #  define FSTAT _Py_fstat_noraise
484 #  define STRUCT_STAT struct _Py_stat_struct
485 #else
486 #  define STAT stat
487 #  define LSTAT lstat
488 #  define FSTAT fstat
489 #  define STRUCT_STAT struct stat
490 #endif
491 
492 #if defined(MAJOR_IN_MKDEV)
493 #  include <sys/mkdev.h>
494 #else
495 #  if defined(MAJOR_IN_SYSMACROS)
496 #    include <sys/sysmacros.h>
497 #  endif
498 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
499 #    include <sys/mkdev.h>
500 #  endif
501 #endif
502 
503 #ifdef MS_WINDOWS
504 #  define INITFUNC PyInit_nt
505 #  define MODNAME "nt"
506 #else
507 #  define INITFUNC PyInit_posix
508 #  define MODNAME "posix"
509 #endif
510 
511 #if defined(__sun)
512 /* Something to implement in autoconf, not present in autoconf 2.69 */
513 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
514 #endif
515 
516 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
517  * linux/memfd.h defines additional flags
518  */
519 #ifdef HAVE_SYS_MMAN_H
520 #  include <sys/mman.h>
521 #endif
522 #ifdef HAVE_SYS_MEMFD_H
523 #  include <sys/memfd.h>
524 #endif
525 #ifdef HAVE_LINUX_MEMFD_H
526 #  include <linux/memfd.h>
527 #endif
528 
529 /* eventfd() */
530 #ifdef HAVE_SYS_EVENTFD_H
531 #  include <sys/eventfd.h>
532 #endif
533 
534 #ifdef _Py_MEMORY_SANITIZER
535 #  include <sanitizer/msan_interface.h>
536 #endif
537 
538 #ifdef HAVE_FORK
539 static void
run_at_forkers(PyObject * lst,int reverse)540 run_at_forkers(PyObject *lst, int reverse)
541 {
542     Py_ssize_t i;
543     PyObject *cpy;
544 
545     if (lst != NULL) {
546         assert(PyList_CheckExact(lst));
547 
548         /* Use a list copy in case register_at_fork() is called from
549          * one of the callbacks.
550          */
551         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
552         if (cpy == NULL)
553             PyErr_WriteUnraisable(lst);
554         else {
555             if (reverse)
556                 PyList_Reverse(cpy);
557             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
558                 PyObject *func, *res;
559                 func = PyList_GET_ITEM(cpy, i);
560                 res = _PyObject_CallNoArg(func);
561                 if (res == NULL)
562                     PyErr_WriteUnraisable(func);
563                 else
564                     Py_DECREF(res);
565             }
566             Py_DECREF(cpy);
567         }
568     }
569 }
570 
571 void
PyOS_BeforeFork(void)572 PyOS_BeforeFork(void)
573 {
574     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
575 
576     _PyImport_AcquireLock();
577 }
578 
579 void
PyOS_AfterFork_Parent(void)580 PyOS_AfterFork_Parent(void)
581 {
582     if (_PyImport_ReleaseLock() <= 0)
583         Py_FatalError("failed releasing import lock after fork");
584 
585     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
586 }
587 
588 void
PyOS_AfterFork_Child(void)589 PyOS_AfterFork_Child(void)
590 {
591     PyStatus status;
592     _PyRuntimeState *runtime = &_PyRuntime;
593 
594     status = _PyGILState_Reinit(runtime);
595     if (_PyStatus_EXCEPTION(status)) {
596         goto fatal_error;
597     }
598 
599     PyThreadState *tstate = _PyThreadState_GET();
600     _Py_EnsureTstateNotNULL(tstate);
601 
602     status = _PyEval_ReInitThreads(tstate);
603     if (_PyStatus_EXCEPTION(status)) {
604         goto fatal_error;
605     }
606 
607     status = _PyImport_ReInitLock();
608     if (_PyStatus_EXCEPTION(status)) {
609         goto fatal_error;
610     }
611 
612     _PySignal_AfterFork();
613 
614     status = _PyRuntimeState_ReInitThreads(runtime);
615     if (_PyStatus_EXCEPTION(status)) {
616         goto fatal_error;
617     }
618 
619     status = _PyInterpreterState_DeleteExceptMain(runtime);
620     if (_PyStatus_EXCEPTION(status)) {
621         goto fatal_error;
622     }
623     assert(_PyThreadState_GET() == tstate);
624 
625     run_at_forkers(tstate->interp->after_forkers_child, 0);
626     return;
627 
628 fatal_error:
629     Py_ExitStatusException(status);
630 }
631 
632 static int
register_at_forker(PyObject ** lst,PyObject * func)633 register_at_forker(PyObject **lst, PyObject *func)
634 {
635     if (func == NULL)  /* nothing to register? do nothing. */
636         return 0;
637     if (*lst == NULL) {
638         *lst = PyList_New(0);
639         if (*lst == NULL)
640             return -1;
641     }
642     return PyList_Append(*lst, func);
643 }
644 #endif  /* HAVE_FORK */
645 
646 
647 /* Legacy wrapper */
648 void
PyOS_AfterFork(void)649 PyOS_AfterFork(void)
650 {
651 #ifdef HAVE_FORK
652     PyOS_AfterFork_Child();
653 #endif
654 }
655 
656 
657 #ifdef MS_WINDOWS
658 /* defined in fileutils.c */
659 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
660 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
661                                             ULONG, struct _Py_stat_struct *);
662 #endif
663 
664 
665 #ifndef MS_WINDOWS
666 PyObject *
_PyLong_FromUid(uid_t uid)667 _PyLong_FromUid(uid_t uid)
668 {
669     if (uid == (uid_t)-1)
670         return PyLong_FromLong(-1);
671     return PyLong_FromUnsignedLong(uid);
672 }
673 
674 PyObject *
_PyLong_FromGid(gid_t gid)675 _PyLong_FromGid(gid_t gid)
676 {
677     if (gid == (gid_t)-1)
678         return PyLong_FromLong(-1);
679     return PyLong_FromUnsignedLong(gid);
680 }
681 
682 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)683 _Py_Uid_Converter(PyObject *obj, uid_t *p)
684 {
685     uid_t uid;
686     PyObject *index;
687     int overflow;
688     long result;
689     unsigned long uresult;
690 
691     index = _PyNumber_Index(obj);
692     if (index == NULL) {
693         PyErr_Format(PyExc_TypeError,
694                      "uid should be integer, not %.200s",
695                      _PyType_Name(Py_TYPE(obj)));
696         return 0;
697     }
698 
699     /*
700      * Handling uid_t is complicated for two reasons:
701      *  * Although uid_t is (always?) unsigned, it still
702      *    accepts -1.
703      *  * We don't know its size in advance--it may be
704      *    bigger than an int, or it may be smaller than
705      *    a long.
706      *
707      * So a bit of defensive programming is in order.
708      * Start with interpreting the value passed
709      * in as a signed long and see if it works.
710      */
711 
712     result = PyLong_AsLongAndOverflow(index, &overflow);
713 
714     if (!overflow) {
715         uid = (uid_t)result;
716 
717         if (result == -1) {
718             if (PyErr_Occurred())
719                 goto fail;
720             /* It's a legitimate -1, we're done. */
721             goto success;
722         }
723 
724         /* Any other negative number is disallowed. */
725         if (result < 0)
726             goto underflow;
727 
728         /* Ensure the value wasn't truncated. */
729         if (sizeof(uid_t) < sizeof(long) &&
730             (long)uid != result)
731             goto underflow;
732         goto success;
733     }
734 
735     if (overflow < 0)
736         goto underflow;
737 
738     /*
739      * Okay, the value overflowed a signed long.  If it
740      * fits in an *unsigned* long, it may still be okay,
741      * as uid_t may be unsigned long on this platform.
742      */
743     uresult = PyLong_AsUnsignedLong(index);
744     if (PyErr_Occurred()) {
745         if (PyErr_ExceptionMatches(PyExc_OverflowError))
746             goto overflow;
747         goto fail;
748     }
749 
750     uid = (uid_t)uresult;
751 
752     /*
753      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
754      * but this value would get interpreted as (uid_t)-1  by chown
755      * and its siblings.   That's not what the user meant!  So we
756      * throw an overflow exception instead.   (We already
757      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
758      */
759     if (uid == (uid_t)-1)
760         goto overflow;
761 
762     /* Ensure the value wasn't truncated. */
763     if (sizeof(uid_t) < sizeof(long) &&
764         (unsigned long)uid != uresult)
765         goto overflow;
766     /* fallthrough */
767 
768 success:
769     Py_DECREF(index);
770     *p = uid;
771     return 1;
772 
773 underflow:
774     PyErr_SetString(PyExc_OverflowError,
775                     "uid is less than minimum");
776     goto fail;
777 
778 overflow:
779     PyErr_SetString(PyExc_OverflowError,
780                     "uid is greater than maximum");
781     /* fallthrough */
782 
783 fail:
784     Py_DECREF(index);
785     return 0;
786 }
787 
788 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)789 _Py_Gid_Converter(PyObject *obj, gid_t *p)
790 {
791     gid_t gid;
792     PyObject *index;
793     int overflow;
794     long result;
795     unsigned long uresult;
796 
797     index = _PyNumber_Index(obj);
798     if (index == NULL) {
799         PyErr_Format(PyExc_TypeError,
800                      "gid should be integer, not %.200s",
801                      _PyType_Name(Py_TYPE(obj)));
802         return 0;
803     }
804 
805     /*
806      * Handling gid_t is complicated for two reasons:
807      *  * Although gid_t is (always?) unsigned, it still
808      *    accepts -1.
809      *  * We don't know its size in advance--it may be
810      *    bigger than an int, or it may be smaller than
811      *    a long.
812      *
813      * So a bit of defensive programming is in order.
814      * Start with interpreting the value passed
815      * in as a signed long and see if it works.
816      */
817 
818     result = PyLong_AsLongAndOverflow(index, &overflow);
819 
820     if (!overflow) {
821         gid = (gid_t)result;
822 
823         if (result == -1) {
824             if (PyErr_Occurred())
825                 goto fail;
826             /* It's a legitimate -1, we're done. */
827             goto success;
828         }
829 
830         /* Any other negative number is disallowed. */
831         if (result < 0) {
832             goto underflow;
833         }
834 
835         /* Ensure the value wasn't truncated. */
836         if (sizeof(gid_t) < sizeof(long) &&
837             (long)gid != result)
838             goto underflow;
839         goto success;
840     }
841 
842     if (overflow < 0)
843         goto underflow;
844 
845     /*
846      * Okay, the value overflowed a signed long.  If it
847      * fits in an *unsigned* long, it may still be okay,
848      * as gid_t may be unsigned long on this platform.
849      */
850     uresult = PyLong_AsUnsignedLong(index);
851     if (PyErr_Occurred()) {
852         if (PyErr_ExceptionMatches(PyExc_OverflowError))
853             goto overflow;
854         goto fail;
855     }
856 
857     gid = (gid_t)uresult;
858 
859     /*
860      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
861      * but this value would get interpreted as (gid_t)-1  by chown
862      * and its siblings.   That's not what the user meant!  So we
863      * throw an overflow exception instead.   (We already
864      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
865      */
866     if (gid == (gid_t)-1)
867         goto overflow;
868 
869     /* Ensure the value wasn't truncated. */
870     if (sizeof(gid_t) < sizeof(long) &&
871         (unsigned long)gid != uresult)
872         goto overflow;
873     /* fallthrough */
874 
875 success:
876     Py_DECREF(index);
877     *p = gid;
878     return 1;
879 
880 underflow:
881     PyErr_SetString(PyExc_OverflowError,
882                     "gid is less than minimum");
883     goto fail;
884 
885 overflow:
886     PyErr_SetString(PyExc_OverflowError,
887                     "gid is greater than maximum");
888     /* fallthrough */
889 
890 fail:
891     Py_DECREF(index);
892     return 0;
893 }
894 #endif /* MS_WINDOWS */
895 
896 
897 #define _PyLong_FromDev PyLong_FromLongLong
898 
899 
900 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
901 static int
_Py_Dev_Converter(PyObject * obj,void * p)902 _Py_Dev_Converter(PyObject *obj, void *p)
903 {
904     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
905     if (PyErr_Occurred())
906         return 0;
907     return 1;
908 }
909 #endif /* HAVE_MKNOD && HAVE_MAKEDEV */
910 
911 
912 #ifdef AT_FDCWD
913 /*
914  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
915  * without the int cast, the value gets interpreted as uint (4291925331),
916  * which doesn't play nicely with all the initializer lines in this file that
917  * look like this:
918  *      int dir_fd = DEFAULT_DIR_FD;
919  */
920 #define DEFAULT_DIR_FD (int)AT_FDCWD
921 #else
922 #define DEFAULT_DIR_FD (-100)
923 #endif
924 
925 static int
_fd_converter(PyObject * o,int * p)926 _fd_converter(PyObject *o, int *p)
927 {
928     int overflow;
929     long long_value;
930 
931     PyObject *index = _PyNumber_Index(o);
932     if (index == NULL) {
933         return 0;
934     }
935 
936     assert(PyLong_Check(index));
937     long_value = PyLong_AsLongAndOverflow(index, &overflow);
938     Py_DECREF(index);
939     assert(!PyErr_Occurred());
940     if (overflow > 0 || long_value > INT_MAX) {
941         PyErr_SetString(PyExc_OverflowError,
942                         "fd is greater than maximum");
943         return 0;
944     }
945     if (overflow < 0 || long_value < INT_MIN) {
946         PyErr_SetString(PyExc_OverflowError,
947                         "fd is less than minimum");
948         return 0;
949     }
950 
951     *p = (int)long_value;
952     return 1;
953 }
954 
955 static int
dir_fd_converter(PyObject * o,void * p)956 dir_fd_converter(PyObject *o, void *p)
957 {
958     if (o == Py_None) {
959         *(int *)p = DEFAULT_DIR_FD;
960         return 1;
961     }
962     else if (PyIndex_Check(o)) {
963         return _fd_converter(o, (int *)p);
964     }
965     else {
966         PyErr_Format(PyExc_TypeError,
967                      "argument should be integer or None, not %.200s",
968                      _PyType_Name(Py_TYPE(o)));
969         return 0;
970     }
971 }
972 
973 typedef struct {
974     PyObject *billion;
975     PyObject *DirEntryType;
976     PyObject *ScandirIteratorType;
977 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
978     PyObject *SchedParamType;
979 #endif
980     PyObject *StatResultType;
981     PyObject *StatVFSResultType;
982     PyObject *TerminalSizeType;
983     PyObject *TimesResultType;
984     PyObject *UnameResultType;
985 #if defined(HAVE_WAITID) && !defined(__APPLE__)
986     PyObject *WaitidResultType;
987 #endif
988 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
989     PyObject *struct_rusage;
990 #endif
991     PyObject *st_mode;
992 } _posixstate;
993 
994 
995 static inline _posixstate*
get_posix_state(PyObject * module)996 get_posix_state(PyObject *module)
997 {
998     void *state = _PyModule_GetState(module);
999     assert(state != NULL);
1000     return (_posixstate *)state;
1001 }
1002 
1003 /*
1004  * A PyArg_ParseTuple "converter" function
1005  * that handles filesystem paths in the manner
1006  * preferred by the os module.
1007  *
1008  * path_converter accepts (Unicode) strings and their
1009  * subclasses, and bytes and their subclasses.  What
1010  * it does with the argument depends on the platform:
1011  *
1012  *   * On Windows, if we get a (Unicode) string we
1013  *     extract the wchar_t * and return it; if we get
1014  *     bytes we decode to wchar_t * and return that.
1015  *
1016  *   * On all other platforms, strings are encoded
1017  *     to bytes using PyUnicode_FSConverter, then we
1018  *     extract the char * from the bytes object and
1019  *     return that.
1020  *
1021  * path_converter also optionally accepts signed
1022  * integers (representing open file descriptors) instead
1023  * of path strings.
1024  *
1025  * Input fields:
1026  *   path.nullable
1027  *     If nonzero, the path is permitted to be None.
1028  *   path.allow_fd
1029  *     If nonzero, the path is permitted to be a file handle
1030  *     (a signed int) instead of a string.
1031  *   path.function_name
1032  *     If non-NULL, path_converter will use that as the name
1033  *     of the function in error messages.
1034  *     (If path.function_name is NULL it omits the function name.)
1035  *   path.argument_name
1036  *     If non-NULL, path_converter will use that as the name
1037  *     of the parameter in error messages.
1038  *     (If path.argument_name is NULL it uses "path".)
1039  *
1040  * Output fields:
1041  *   path.wide
1042  *     Points to the path if it was expressed as Unicode
1043  *     and was not encoded.  (Only used on Windows.)
1044  *   path.narrow
1045  *     Points to the path if it was expressed as bytes,
1046  *     or it was Unicode and was encoded to bytes. (On Windows,
1047  *     is a non-zero integer if the path was expressed as bytes.
1048  *     The type is deliberately incompatible to prevent misuse.)
1049  *   path.fd
1050  *     Contains a file descriptor if path.accept_fd was true
1051  *     and the caller provided a signed integer instead of any
1052  *     sort of string.
1053  *
1054  *     WARNING: if your "path" parameter is optional, and is
1055  *     unspecified, path_converter will never get called.
1056  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1057  *     yourself!
1058  *   path.length
1059  *     The length of the path in characters, if specified as
1060  *     a string.
1061  *   path.object
1062  *     The original object passed in (if get a PathLike object,
1063  *     the result of PyOS_FSPath() is treated as the original object).
1064  *     Own a reference to the object.
1065  *   path.cleanup
1066  *     For internal use only.  May point to a temporary object.
1067  *     (Pay no attention to the man behind the curtain.)
1068  *
1069  *   At most one of path.wide or path.narrow will be non-NULL.
1070  *   If path was None and path.nullable was set,
1071  *     or if path was an integer and path.allow_fd was set,
1072  *     both path.wide and path.narrow will be NULL
1073  *     and path.length will be 0.
1074  *
1075  *   path_converter takes care to not write to the path_t
1076  *   unless it's successful.  However it must reset the
1077  *   "cleanup" field each time it's called.
1078  *
1079  * Use as follows:
1080  *      path_t path;
1081  *      memset(&path, 0, sizeof(path));
1082  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1083  *      // ... use values from path ...
1084  *      path_cleanup(&path);
1085  *
1086  * (Note that if PyArg_Parse fails you don't need to call
1087  * path_cleanup().  However it is safe to do so.)
1088  */
1089 typedef struct {
1090     const char *function_name;
1091     const char *argument_name;
1092     int nullable;
1093     int allow_fd;
1094     const wchar_t *wide;
1095 #ifdef MS_WINDOWS
1096     BOOL narrow;
1097 #else
1098     const char *narrow;
1099 #endif
1100     int fd;
1101     Py_ssize_t length;
1102     PyObject *object;
1103     PyObject *cleanup;
1104 } path_t;
1105 
1106 #ifdef MS_WINDOWS
1107 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1108     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1109 #else
1110 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1111     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1112 #endif
1113 
1114 static void
path_cleanup(path_t * path)1115 path_cleanup(path_t *path)
1116 {
1117 #if !USE_UNICODE_WCHAR_CACHE
1118     wchar_t *wide = (wchar_t *)path->wide;
1119     path->wide = NULL;
1120     PyMem_Free(wide);
1121 #endif /* USE_UNICODE_WCHAR_CACHE */
1122     Py_CLEAR(path->object);
1123     Py_CLEAR(path->cleanup);
1124 }
1125 
1126 static int
path_converter(PyObject * o,void * p)1127 path_converter(PyObject *o, void *p)
1128 {
1129     path_t *path = (path_t *)p;
1130     PyObject *bytes = NULL;
1131     Py_ssize_t length = 0;
1132     int is_index, is_buffer, is_bytes, is_unicode;
1133     const char *narrow;
1134 #ifdef MS_WINDOWS
1135     PyObject *wo = NULL;
1136     wchar_t *wide = NULL;
1137 #endif
1138 
1139 #define FORMAT_EXCEPTION(exc, fmt) \
1140     PyErr_Format(exc, "%s%s" fmt, \
1141         path->function_name ? path->function_name : "", \
1142         path->function_name ? ": "                : "", \
1143         path->argument_name ? path->argument_name : "path")
1144 
1145     /* Py_CLEANUP_SUPPORTED support */
1146     if (o == NULL) {
1147         path_cleanup(path);
1148         return 1;
1149     }
1150 
1151     /* Ensure it's always safe to call path_cleanup(). */
1152     path->object = path->cleanup = NULL;
1153     /* path->object owns a reference to the original object */
1154     Py_INCREF(o);
1155 
1156     if ((o == Py_None) && path->nullable) {
1157         path->wide = NULL;
1158 #ifdef MS_WINDOWS
1159         path->narrow = FALSE;
1160 #else
1161         path->narrow = NULL;
1162 #endif
1163         path->fd = -1;
1164         goto success_exit;
1165     }
1166 
1167     /* Only call this here so that we don't treat the return value of
1168        os.fspath() as an fd or buffer. */
1169     is_index = path->allow_fd && PyIndex_Check(o);
1170     is_buffer = PyObject_CheckBuffer(o);
1171     is_bytes = PyBytes_Check(o);
1172     is_unicode = PyUnicode_Check(o);
1173 
1174     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1175         /* Inline PyOS_FSPath() for better error messages. */
1176         PyObject *func, *res;
1177 
1178         func = _PyObject_LookupSpecial(o, &PyId___fspath__);
1179         if (NULL == func) {
1180             goto error_format;
1181         }
1182         res = _PyObject_CallNoArg(func);
1183         Py_DECREF(func);
1184         if (NULL == res) {
1185             goto error_exit;
1186         }
1187         else if (PyUnicode_Check(res)) {
1188             is_unicode = 1;
1189         }
1190         else if (PyBytes_Check(res)) {
1191             is_bytes = 1;
1192         }
1193         else {
1194             PyErr_Format(PyExc_TypeError,
1195                  "expected %.200s.__fspath__() to return str or bytes, "
1196                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1197                  _PyType_Name(Py_TYPE(res)));
1198             Py_DECREF(res);
1199             goto error_exit;
1200         }
1201 
1202         /* still owns a reference to the original object */
1203         Py_DECREF(o);
1204         o = res;
1205     }
1206 
1207     if (is_unicode) {
1208 #ifdef MS_WINDOWS
1209 #if USE_UNICODE_WCHAR_CACHE
1210 _Py_COMP_DIAG_PUSH
1211 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1212         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1213 _Py_COMP_DIAG_POP
1214 #else /* USE_UNICODE_WCHAR_CACHE */
1215         wide = PyUnicode_AsWideCharString(o, &length);
1216 #endif /* USE_UNICODE_WCHAR_CACHE */
1217         if (!wide) {
1218             goto error_exit;
1219         }
1220         if (length > 32767) {
1221             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1222             goto error_exit;
1223         }
1224         if (wcslen(wide) != length) {
1225             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1226             goto error_exit;
1227         }
1228 
1229         path->wide = wide;
1230         path->narrow = FALSE;
1231         path->fd = -1;
1232 #if !USE_UNICODE_WCHAR_CACHE
1233         wide = NULL;
1234 #endif /* USE_UNICODE_WCHAR_CACHE */
1235         goto success_exit;
1236 #else
1237         if (!PyUnicode_FSConverter(o, &bytes)) {
1238             goto error_exit;
1239         }
1240 #endif
1241     }
1242     else if (is_bytes) {
1243         bytes = o;
1244         Py_INCREF(bytes);
1245     }
1246     else if (is_buffer) {
1247         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1248            after removing support of non-bytes buffer objects. */
1249         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1250             "%s%s%s should be %s, not %.200s",
1251             path->function_name ? path->function_name : "",
1252             path->function_name ? ": "                : "",
1253             path->argument_name ? path->argument_name : "path",
1254             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1255                                                "integer or None" :
1256             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1257             path->nullable ? "string, bytes, os.PathLike or None" :
1258                              "string, bytes or os.PathLike",
1259             _PyType_Name(Py_TYPE(o)))) {
1260             goto error_exit;
1261         }
1262         bytes = PyBytes_FromObject(o);
1263         if (!bytes) {
1264             goto error_exit;
1265         }
1266     }
1267     else if (is_index) {
1268         if (!_fd_converter(o, &path->fd)) {
1269             goto error_exit;
1270         }
1271         path->wide = NULL;
1272 #ifdef MS_WINDOWS
1273         path->narrow = FALSE;
1274 #else
1275         path->narrow = NULL;
1276 #endif
1277         goto success_exit;
1278     }
1279     else {
1280  error_format:
1281         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1282             path->function_name ? path->function_name : "",
1283             path->function_name ? ": "                : "",
1284             path->argument_name ? path->argument_name : "path",
1285             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1286                                                "integer or None" :
1287             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1288             path->nullable ? "string, bytes, os.PathLike or None" :
1289                              "string, bytes or os.PathLike",
1290             _PyType_Name(Py_TYPE(o)));
1291         goto error_exit;
1292     }
1293 
1294     length = PyBytes_GET_SIZE(bytes);
1295     narrow = PyBytes_AS_STRING(bytes);
1296     if ((size_t)length != strlen(narrow)) {
1297         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1298         goto error_exit;
1299     }
1300 
1301 #ifdef MS_WINDOWS
1302     wo = PyUnicode_DecodeFSDefaultAndSize(
1303         narrow,
1304         length
1305     );
1306     if (!wo) {
1307         goto error_exit;
1308     }
1309 
1310 #if USE_UNICODE_WCHAR_CACHE
1311 _Py_COMP_DIAG_PUSH
1312 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1313     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1314 _Py_COMP_DIAG_POP
1315 #else /* USE_UNICODE_WCHAR_CACHE */
1316     wide = PyUnicode_AsWideCharString(wo, &length);
1317     Py_DECREF(wo);
1318 #endif /* USE_UNICODE_WCHAR_CACHE */
1319     if (!wide) {
1320         goto error_exit;
1321     }
1322     if (length > 32767) {
1323         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1324         goto error_exit;
1325     }
1326     if (wcslen(wide) != length) {
1327         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1328         goto error_exit;
1329     }
1330     path->wide = wide;
1331     path->narrow = TRUE;
1332     Py_DECREF(bytes);
1333 #if USE_UNICODE_WCHAR_CACHE
1334     path->cleanup = wo;
1335 #else /* USE_UNICODE_WCHAR_CACHE */
1336     wide = NULL;
1337 #endif /* USE_UNICODE_WCHAR_CACHE */
1338 #else
1339     path->wide = NULL;
1340     path->narrow = narrow;
1341     if (bytes == o) {
1342         /* Still a reference owned by path->object, don't have to
1343            worry about path->narrow is used after free. */
1344         Py_DECREF(bytes);
1345     }
1346     else {
1347         path->cleanup = bytes;
1348     }
1349 #endif
1350     path->fd = -1;
1351 
1352  success_exit:
1353     path->length = length;
1354     path->object = o;
1355     return Py_CLEANUP_SUPPORTED;
1356 
1357  error_exit:
1358     Py_XDECREF(o);
1359     Py_XDECREF(bytes);
1360 #ifdef MS_WINDOWS
1361 #if USE_UNICODE_WCHAR_CACHE
1362     Py_XDECREF(wo);
1363 #else /* USE_UNICODE_WCHAR_CACHE */
1364     PyMem_Free(wide);
1365 #endif /* USE_UNICODE_WCHAR_CACHE */
1366 #endif
1367     return 0;
1368 }
1369 
1370 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1371 argument_unavailable_error(const char *function_name, const char *argument_name)
1372 {
1373     PyErr_Format(PyExc_NotImplementedError,
1374         "%s%s%s unavailable on this platform",
1375         (function_name != NULL) ? function_name : "",
1376         (function_name != NULL) ? ": ": "",
1377         argument_name);
1378 }
1379 
1380 static int
dir_fd_unavailable(PyObject * o,void * p)1381 dir_fd_unavailable(PyObject *o, void *p)
1382 {
1383     int dir_fd;
1384     if (!dir_fd_converter(o, &dir_fd))
1385         return 0;
1386     if (dir_fd != DEFAULT_DIR_FD) {
1387         argument_unavailable_error(NULL, "dir_fd");
1388         return 0;
1389     }
1390     *(int *)p = dir_fd;
1391     return 1;
1392 }
1393 
1394 static int
fd_specified(const char * function_name,int fd)1395 fd_specified(const char *function_name, int fd)
1396 {
1397     if (fd == -1)
1398         return 0;
1399 
1400     argument_unavailable_error(function_name, "fd");
1401     return 1;
1402 }
1403 
1404 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1405 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1406 {
1407     if (follow_symlinks)
1408         return 0;
1409 
1410     argument_unavailable_error(function_name, "follow_symlinks");
1411     return 1;
1412 }
1413 
1414 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1415 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1416 {
1417     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1418 #ifndef MS_WINDOWS
1419         && !path->narrow
1420 #endif
1421     ) {
1422         PyErr_Format(PyExc_ValueError,
1423                      "%s: can't specify dir_fd without matching path",
1424                      function_name);
1425         return 1;
1426     }
1427     return 0;
1428 }
1429 
1430 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1431 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1432 {
1433     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1434         PyErr_Format(PyExc_ValueError,
1435                      "%s: can't specify both dir_fd and fd",
1436                      function_name);
1437         return 1;
1438     }
1439     return 0;
1440 }
1441 
1442 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1443 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1444                                int follow_symlinks)
1445 {
1446     if ((fd > 0) && (!follow_symlinks)) {
1447         PyErr_Format(PyExc_ValueError,
1448                      "%s: cannot use fd and follow_symlinks together",
1449                      function_name);
1450         return 1;
1451     }
1452     return 0;
1453 }
1454 
1455 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1456 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1457                                    int follow_symlinks)
1458 {
1459     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1460         PyErr_Format(PyExc_ValueError,
1461                      "%s: cannot use dir_fd and follow_symlinks together",
1462                      function_name);
1463         return 1;
1464     }
1465     return 0;
1466 }
1467 
1468 #ifdef MS_WINDOWS
1469     typedef long long Py_off_t;
1470 #else
1471     typedef off_t Py_off_t;
1472 #endif
1473 
1474 static int
Py_off_t_converter(PyObject * arg,void * addr)1475 Py_off_t_converter(PyObject *arg, void *addr)
1476 {
1477 #ifdef HAVE_LARGEFILE_SUPPORT
1478     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1479 #else
1480     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1481 #endif
1482     if (PyErr_Occurred())
1483         return 0;
1484     return 1;
1485 }
1486 
1487 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1488 PyLong_FromPy_off_t(Py_off_t offset)
1489 {
1490 #ifdef HAVE_LARGEFILE_SUPPORT
1491     return PyLong_FromLongLong(offset);
1492 #else
1493     return PyLong_FromLong(offset);
1494 #endif
1495 }
1496 
1497 #ifdef HAVE_SIGSET_T
1498 /* Convert an iterable of integers to a sigset.
1499    Return 1 on success, return 0 and raise an exception on error. */
1500 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1501 _Py_Sigset_Converter(PyObject *obj, void *addr)
1502 {
1503     sigset_t *mask = (sigset_t *)addr;
1504     PyObject *iterator, *item;
1505     long signum;
1506     int overflow;
1507 
1508     // The extra parens suppress the unreachable-code warning with clang on MacOS
1509     if (sigemptyset(mask) < (0)) {
1510         /* Probably only if mask == NULL. */
1511         PyErr_SetFromErrno(PyExc_OSError);
1512         return 0;
1513     }
1514 
1515     iterator = PyObject_GetIter(obj);
1516     if (iterator == NULL) {
1517         return 0;
1518     }
1519 
1520     while ((item = PyIter_Next(iterator)) != NULL) {
1521         signum = PyLong_AsLongAndOverflow(item, &overflow);
1522         Py_DECREF(item);
1523         if (signum <= 0 || signum >= NSIG) {
1524             if (overflow || signum != -1 || !PyErr_Occurred()) {
1525                 PyErr_Format(PyExc_ValueError,
1526                              "signal number %ld out of range", signum);
1527             }
1528             goto error;
1529         }
1530         if (sigaddset(mask, (int)signum)) {
1531             if (errno != EINVAL) {
1532                 /* Probably impossible */
1533                 PyErr_SetFromErrno(PyExc_OSError);
1534                 goto error;
1535             }
1536             /* For backwards compatibility, allow idioms such as
1537              * `range(1, NSIG)` but warn about invalid signal numbers
1538              */
1539             const char msg[] =
1540                 "invalid signal number %ld, please use valid_signals()";
1541             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1542                 goto error;
1543             }
1544         }
1545     }
1546     if (!PyErr_Occurred()) {
1547         Py_DECREF(iterator);
1548         return 1;
1549     }
1550 
1551 error:
1552     Py_DECREF(iterator);
1553     return 0;
1554 }
1555 #endif /* HAVE_SIGSET_T */
1556 
1557 #ifdef MS_WINDOWS
1558 
1559 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1560 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1561 {
1562     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1563     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1564     DWORD n_bytes_returned;
1565 
1566     if (0 == DeviceIoControl(
1567         reparse_point_handle,
1568         FSCTL_GET_REPARSE_POINT,
1569         NULL, 0, /* in buffer */
1570         target_buffer, sizeof(target_buffer),
1571         &n_bytes_returned,
1572         NULL)) /* we're not using OVERLAPPED_IO */
1573         return FALSE;
1574 
1575     if (reparse_tag)
1576         *reparse_tag = rdb->ReparseTag;
1577 
1578     return TRUE;
1579 }
1580 
1581 #endif /* MS_WINDOWS */
1582 
1583 /* Return a dictionary corresponding to the POSIX environment table */
1584 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1585 /* On Darwin/MacOSX a shared library or framework has no access to
1586 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1587 ** man environ(7).
1588 */
1589 #include <crt_externs.h>
1590 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1591 extern char **environ;
1592 #endif /* !_MSC_VER */
1593 
1594 static PyObject *
convertenviron(void)1595 convertenviron(void)
1596 {
1597     PyObject *d;
1598 #ifdef MS_WINDOWS
1599     wchar_t **e;
1600 #else
1601     char **e;
1602 #endif
1603 
1604     d = PyDict_New();
1605     if (d == NULL)
1606         return NULL;
1607 #ifdef MS_WINDOWS
1608     /* _wenviron must be initialized in this way if the program is started
1609        through main() instead of wmain(). */
1610     _wgetenv(L"");
1611     e = _wenviron;
1612 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1613     /* environ is not accessible as an extern in a shared object on OSX; use
1614        _NSGetEnviron to resolve it. The value changes if you add environment
1615        variables between calls to Py_Initialize, so don't cache the value. */
1616     e = *_NSGetEnviron();
1617 #else
1618     e = environ;
1619 #endif
1620     if (e == NULL)
1621         return d;
1622     for (; *e != NULL; e++) {
1623         PyObject *k;
1624         PyObject *v;
1625 #ifdef MS_WINDOWS
1626         const wchar_t *p = wcschr(*e, L'=');
1627 #else
1628         const char *p = strchr(*e, '=');
1629 #endif
1630         if (p == NULL)
1631             continue;
1632 #ifdef MS_WINDOWS
1633         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1634 #else
1635         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1636 #endif
1637         if (k == NULL) {
1638             Py_DECREF(d);
1639             return NULL;
1640         }
1641 #ifdef MS_WINDOWS
1642         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1643 #else
1644         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1645 #endif
1646         if (v == NULL) {
1647             Py_DECREF(k);
1648             Py_DECREF(d);
1649             return NULL;
1650         }
1651         if (PyDict_SetDefault(d, k, v) == NULL) {
1652             Py_DECREF(v);
1653             Py_DECREF(k);
1654             Py_DECREF(d);
1655             return NULL;
1656         }
1657         Py_DECREF(k);
1658         Py_DECREF(v);
1659     }
1660     return d;
1661 }
1662 
1663 /* Set a POSIX-specific error from errno, and return NULL */
1664 
1665 static PyObject *
posix_error(void)1666 posix_error(void)
1667 {
1668     return PyErr_SetFromErrno(PyExc_OSError);
1669 }
1670 
1671 #ifdef MS_WINDOWS
1672 static PyObject *
win32_error(const char * function,const char * filename)1673 win32_error(const char* function, const char* filename)
1674 {
1675     /* XXX We should pass the function name along in the future.
1676        (winreg.c also wants to pass the function name.)
1677        This would however require an additional param to the
1678        Windows error object, which is non-trivial.
1679     */
1680     errno = GetLastError();
1681     if (filename)
1682         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1683     else
1684         return PyErr_SetFromWindowsErr(errno);
1685 }
1686 
1687 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1688 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1689 {
1690     /* XXX - see win32_error for comments on 'function' */
1691     if (filename)
1692         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1693                     PyExc_OSError,
1694                     err,
1695                     filename);
1696     else
1697         return PyErr_SetFromWindowsErr(err);
1698 }
1699 
1700 static PyObject *
win32_error_object(const char * function,PyObject * filename)1701 win32_error_object(const char* function, PyObject* filename)
1702 {
1703     errno = GetLastError();
1704     return win32_error_object_err(function, filename, errno);
1705 }
1706 
1707 #endif /* MS_WINDOWS */
1708 
1709 static PyObject *
posix_path_object_error(PyObject * path)1710 posix_path_object_error(PyObject *path)
1711 {
1712     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1713 }
1714 
1715 static PyObject *
path_object_error(PyObject * path)1716 path_object_error(PyObject *path)
1717 {
1718 #ifdef MS_WINDOWS
1719     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1720                 PyExc_OSError, 0, path);
1721 #else
1722     return posix_path_object_error(path);
1723 #endif
1724 }
1725 
1726 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1727 path_object_error2(PyObject *path, PyObject *path2)
1728 {
1729 #ifdef MS_WINDOWS
1730     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1731                 PyExc_OSError, 0, path, path2);
1732 #else
1733     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1734 #endif
1735 }
1736 
1737 static PyObject *
path_error(path_t * path)1738 path_error(path_t *path)
1739 {
1740     return path_object_error(path->object);
1741 }
1742 
1743 static PyObject *
posix_path_error(path_t * path)1744 posix_path_error(path_t *path)
1745 {
1746     return posix_path_object_error(path->object);
1747 }
1748 
1749 static PyObject *
path_error2(path_t * path,path_t * path2)1750 path_error2(path_t *path, path_t *path2)
1751 {
1752     return path_object_error2(path->object, path2->object);
1753 }
1754 
1755 
1756 /* POSIX generic methods */
1757 
1758 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1759 posix_fildes_fd(int fd, int (*func)(int))
1760 {
1761     int res;
1762     int async_err = 0;
1763 
1764     do {
1765         Py_BEGIN_ALLOW_THREADS
1766         _Py_BEGIN_SUPPRESS_IPH
1767         res = (*func)(fd);
1768         _Py_END_SUPPRESS_IPH
1769         Py_END_ALLOW_THREADS
1770     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1771     if (res != 0)
1772         return (!async_err) ? posix_error() : NULL;
1773     Py_RETURN_NONE;
1774 }
1775 
1776 
1777 #ifdef MS_WINDOWS
1778 /* This is a reimplementation of the C library's chdir function,
1779    but one that produces Win32 errors instead of DOS error codes.
1780    chdir is essentially a wrapper around SetCurrentDirectory; however,
1781    it also needs to set "magic" environment variables indicating
1782    the per-drive current directory, which are of the form =<drive>: */
1783 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1784 win32_wchdir(LPCWSTR path)
1785 {
1786     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1787     int result;
1788     wchar_t env[4] = L"=x:";
1789 
1790     if(!SetCurrentDirectoryW(path))
1791         return FALSE;
1792     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1793     if (!result)
1794         return FALSE;
1795     if (result > Py_ARRAY_LENGTH(path_buf)) {
1796         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1797         if (!new_path) {
1798             SetLastError(ERROR_OUTOFMEMORY);
1799             return FALSE;
1800         }
1801         result = GetCurrentDirectoryW(result, new_path);
1802         if (!result) {
1803             PyMem_RawFree(new_path);
1804             return FALSE;
1805         }
1806     }
1807     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1808                             wcsncmp(new_path, L"//", 2) == 0);
1809     if (!is_unc_like_path) {
1810         env[1] = new_path[0];
1811         result = SetEnvironmentVariableW(env, new_path);
1812     }
1813     if (new_path != path_buf)
1814         PyMem_RawFree(new_path);
1815     return result ? TRUE : FALSE;
1816 }
1817 #endif
1818 
1819 #ifdef MS_WINDOWS
1820 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1821    - time stamps are restricted to second resolution
1822    - file modification times suffer from forth-and-back conversions between
1823      UTC and local time
1824    Therefore, we implement our own stat, based on the Win32 API directly.
1825 */
1826 #define HAVE_STAT_NSEC 1
1827 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1828 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1829 
1830 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1831 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1832                        BY_HANDLE_FILE_INFORMATION *info,
1833                        ULONG *reparse_tag)
1834 {
1835     memset(info, 0, sizeof(*info));
1836     info->dwFileAttributes = pFileData->dwFileAttributes;
1837     info->ftCreationTime   = pFileData->ftCreationTime;
1838     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1839     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1840     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1841     info->nFileSizeLow     = pFileData->nFileSizeLow;
1842 /*  info->nNumberOfLinks   = 1; */
1843     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1844         *reparse_tag = pFileData->dwReserved0;
1845     else
1846         *reparse_tag = 0;
1847 }
1848 
1849 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1850 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1851 {
1852     HANDLE hFindFile;
1853     WIN32_FIND_DATAW FileData;
1854     LPCWSTR filename = pszFile;
1855     size_t n = wcslen(pszFile);
1856     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1857         // cannot use PyMem_Malloc here because we do not hold the GIL
1858         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1859         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1860         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1861             ((LPWSTR)filename)[n] = L'\0';
1862         }
1863         if (!n || (n == 1 && filename[1] == L':')) {
1864             // Nothing left to query
1865             free((void *)filename);
1866             return FALSE;
1867         }
1868     }
1869     hFindFile = FindFirstFileW(filename, &FileData);
1870     if (pszFile != filename) {
1871         free((void *)filename);
1872     }
1873     if (hFindFile == INVALID_HANDLE_VALUE) {
1874         return FALSE;
1875     }
1876     FindClose(hFindFile);
1877     find_data_to_file_info(&FileData, info, reparse_tag);
1878     return TRUE;
1879 }
1880 
1881 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1882 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1883                  BOOL traverse)
1884 {
1885     HANDLE hFile;
1886     BY_HANDLE_FILE_INFORMATION fileInfo;
1887     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1888     DWORD fileType, error;
1889     BOOL isUnhandledTag = FALSE;
1890     int retval = 0;
1891 
1892     DWORD access = FILE_READ_ATTRIBUTES;
1893     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1894     if (!traverse) {
1895         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1896     }
1897 
1898     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1899     if (hFile == INVALID_HANDLE_VALUE) {
1900         /* Either the path doesn't exist, or the caller lacks access. */
1901         error = GetLastError();
1902         switch (error) {
1903         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1904         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1905             /* Try reading the parent directory. */
1906             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1907                 /* Cannot read the parent directory. */
1908                 SetLastError(error);
1909                 return -1;
1910             }
1911             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1912                 if (traverse ||
1913                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1914                     /* The stat call has to traverse but cannot, so fail. */
1915                     SetLastError(error);
1916                     return -1;
1917                 }
1918             }
1919             break;
1920 
1921         case ERROR_INVALID_PARAMETER:
1922             /* \\.\con requires read or write access. */
1923             hFile = CreateFileW(path, access | GENERIC_READ,
1924                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1925                         OPEN_EXISTING, flags, NULL);
1926             if (hFile == INVALID_HANDLE_VALUE) {
1927                 SetLastError(error);
1928                 return -1;
1929             }
1930             break;
1931 
1932         case ERROR_CANT_ACCESS_FILE:
1933             /* bpo37834: open unhandled reparse points if traverse fails. */
1934             if (traverse) {
1935                 traverse = FALSE;
1936                 isUnhandledTag = TRUE;
1937                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1938                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1939             }
1940             if (hFile == INVALID_HANDLE_VALUE) {
1941                 SetLastError(error);
1942                 return -1;
1943             }
1944             break;
1945 
1946         default:
1947             return -1;
1948         }
1949     }
1950 
1951     if (hFile != INVALID_HANDLE_VALUE) {
1952         /* Handle types other than files on disk. */
1953         fileType = GetFileType(hFile);
1954         if (fileType != FILE_TYPE_DISK) {
1955             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1956                 retval = -1;
1957                 goto cleanup;
1958             }
1959             DWORD fileAttributes = GetFileAttributesW(path);
1960             memset(result, 0, sizeof(*result));
1961             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1962                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1963                 /* \\.\pipe\ or \\.\mailslot\ */
1964                 result->st_mode = _S_IFDIR;
1965             } else if (fileType == FILE_TYPE_CHAR) {
1966                 /* \\.\nul */
1967                 result->st_mode = _S_IFCHR;
1968             } else if (fileType == FILE_TYPE_PIPE) {
1969                 /* \\.\pipe\spam */
1970                 result->st_mode = _S_IFIFO;
1971             }
1972             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1973             goto cleanup;
1974         }
1975 
1976         /* Query the reparse tag, and traverse a non-link. */
1977         if (!traverse) {
1978             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1979                     &tagInfo, sizeof(tagInfo))) {
1980                 /* Allow devices that do not support FileAttributeTagInfo. */
1981                 switch (GetLastError()) {
1982                 case ERROR_INVALID_PARAMETER:
1983                 case ERROR_INVALID_FUNCTION:
1984                 case ERROR_NOT_SUPPORTED:
1985                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
1986                     tagInfo.ReparseTag = 0;
1987                     break;
1988                 default:
1989                     retval = -1;
1990                     goto cleanup;
1991                 }
1992             } else if (tagInfo.FileAttributes &
1993                          FILE_ATTRIBUTE_REPARSE_POINT) {
1994                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1995                     if (isUnhandledTag) {
1996                         /* Traversing previously failed for either this link
1997                            or its target. */
1998                         SetLastError(ERROR_CANT_ACCESS_FILE);
1999                         retval = -1;
2000                         goto cleanup;
2001                     }
2002                 /* Traverse a non-link, but not if traversing already failed
2003                    for an unhandled tag. */
2004                 } else if (!isUnhandledTag) {
2005                     CloseHandle(hFile);
2006                     return win32_xstat_impl(path, result, TRUE);
2007                 }
2008             }
2009         }
2010 
2011         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
2012             switch (GetLastError()) {
2013             case ERROR_INVALID_PARAMETER:
2014             case ERROR_INVALID_FUNCTION:
2015             case ERROR_NOT_SUPPORTED:
2016                 /* Volumes and physical disks are block devices, e.g.
2017                    \\.\C: and \\.\PhysicalDrive0. */
2018                 memset(result, 0, sizeof(*result));
2019                 result->st_mode = 0x6000; /* S_IFBLK */
2020                 goto cleanup;
2021             }
2022             retval = -1;
2023             goto cleanup;
2024         }
2025     }
2026 
2027     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2028 
2029     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2030         /* Fix the file execute permissions. This hack sets S_IEXEC if
2031            the filename has an extension that is commonly used by files
2032            that CreateProcessW can execute. A real implementation calls
2033            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2034            AccessCheck to check for generic read, write, and execute
2035            access. */
2036         const wchar_t *fileExtension = wcsrchr(path, '.');
2037         if (fileExtension) {
2038             if (_wcsicmp(fileExtension, L".exe") == 0 ||
2039                 _wcsicmp(fileExtension, L".bat") == 0 ||
2040                 _wcsicmp(fileExtension, L".cmd") == 0 ||
2041                 _wcsicmp(fileExtension, L".com") == 0) {
2042                 result->st_mode |= 0111;
2043             }
2044         }
2045     }
2046 
2047 cleanup:
2048     if (hFile != INVALID_HANDLE_VALUE) {
2049         /* Preserve last error if we are failing */
2050         error = retval ? GetLastError() : 0;
2051         if (!CloseHandle(hFile)) {
2052             retval = -1;
2053         } else if (retval) {
2054             /* Restore last error */
2055             SetLastError(error);
2056         }
2057     }
2058 
2059     return retval;
2060 }
2061 
2062 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2063 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2064 {
2065     /* Protocol violation: we explicitly clear errno, instead of
2066        setting it to a POSIX error. Callers should use GetLastError. */
2067     int code = win32_xstat_impl(path, result, traverse);
2068     errno = 0;
2069     return code;
2070 }
2071 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2072 
2073    In Posix, stat automatically traverses symlinks and returns the stat
2074    structure for the target.  In Windows, the equivalent GetFileAttributes by
2075    default does not traverse symlinks and instead returns attributes for
2076    the symlink.
2077 
2078    Instead, we will open the file (which *does* traverse symlinks by default)
2079    and GetFileInformationByHandle(). */
2080 
2081 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2082 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2083 {
2084     return win32_xstat(path, result, FALSE);
2085 }
2086 
2087 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2088 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2089 {
2090     return win32_xstat(path, result, TRUE);
2091 }
2092 
2093 #endif /* MS_WINDOWS */
2094 
2095 PyDoc_STRVAR(stat_result__doc__,
2096 "stat_result: Result from stat, fstat, or lstat.\n\n\
2097 This object may be accessed either as a tuple of\n\
2098   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2099 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2100 \n\
2101 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2102 or st_flags, they are available as attributes only.\n\
2103 \n\
2104 See os.stat for more information.");
2105 
2106 static PyStructSequence_Field stat_result_fields[] = {
2107     {"st_mode",    "protection bits"},
2108     {"st_ino",     "inode"},
2109     {"st_dev",     "device"},
2110     {"st_nlink",   "number of hard links"},
2111     {"st_uid",     "user ID of owner"},
2112     {"st_gid",     "group ID of owner"},
2113     {"st_size",    "total size, in bytes"},
2114     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2115     {NULL,   "integer time of last access"},
2116     {NULL,   "integer time of last modification"},
2117     {NULL,   "integer time of last change"},
2118     {"st_atime",   "time of last access"},
2119     {"st_mtime",   "time of last modification"},
2120     {"st_ctime",   "time of last change"},
2121     {"st_atime_ns",   "time of last access in nanoseconds"},
2122     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2123     {"st_ctime_ns",   "time of last change in nanoseconds"},
2124 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2125     {"st_blksize", "blocksize for filesystem I/O"},
2126 #endif
2127 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2128     {"st_blocks",  "number of blocks allocated"},
2129 #endif
2130 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2131     {"st_rdev",    "device type (if inode device)"},
2132 #endif
2133 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2134     {"st_flags",   "user defined flags for file"},
2135 #endif
2136 #ifdef HAVE_STRUCT_STAT_ST_GEN
2137     {"st_gen",    "generation number"},
2138 #endif
2139 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2140     {"st_birthtime",   "time of creation"},
2141 #endif
2142 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2143     {"st_file_attributes", "Windows file attribute bits"},
2144 #endif
2145 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2146     {"st_fstype",  "Type of filesystem"},
2147 #endif
2148 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2149     {"st_reparse_tag", "Windows reparse tag"},
2150 #endif
2151     {0}
2152 };
2153 
2154 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2155 #define ST_BLKSIZE_IDX 16
2156 #else
2157 #define ST_BLKSIZE_IDX 15
2158 #endif
2159 
2160 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2161 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2162 #else
2163 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2164 #endif
2165 
2166 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2167 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2168 #else
2169 #define ST_RDEV_IDX ST_BLOCKS_IDX
2170 #endif
2171 
2172 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2173 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2174 #else
2175 #define ST_FLAGS_IDX ST_RDEV_IDX
2176 #endif
2177 
2178 #ifdef HAVE_STRUCT_STAT_ST_GEN
2179 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2180 #else
2181 #define ST_GEN_IDX ST_FLAGS_IDX
2182 #endif
2183 
2184 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2185 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2186 #else
2187 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2188 #endif
2189 
2190 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2191 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2192 #else
2193 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2194 #endif
2195 
2196 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2197 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2198 #else
2199 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2200 #endif
2201 
2202 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2203 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2204 #else
2205 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2206 #endif
2207 
2208 static PyStructSequence_Desc stat_result_desc = {
2209     "stat_result", /* name */
2210     stat_result__doc__, /* doc */
2211     stat_result_fields,
2212     10
2213 };
2214 
2215 PyDoc_STRVAR(statvfs_result__doc__,
2216 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2217 This object may be accessed either as a tuple of\n\
2218   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2219 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2220 \n\
2221 See os.statvfs for more information.");
2222 
2223 static PyStructSequence_Field statvfs_result_fields[] = {
2224     {"f_bsize",  },
2225     {"f_frsize", },
2226     {"f_blocks", },
2227     {"f_bfree",  },
2228     {"f_bavail", },
2229     {"f_files",  },
2230     {"f_ffree",  },
2231     {"f_favail", },
2232     {"f_flag",   },
2233     {"f_namemax",},
2234     {"f_fsid",   },
2235     {0}
2236 };
2237 
2238 static PyStructSequence_Desc statvfs_result_desc = {
2239     "statvfs_result", /* name */
2240     statvfs_result__doc__, /* doc */
2241     statvfs_result_fields,
2242     10
2243 };
2244 
2245 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2246 PyDoc_STRVAR(waitid_result__doc__,
2247 "waitid_result: Result from waitid.\n\n\
2248 This object may be accessed either as a tuple of\n\
2249   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2250 or via the attributes si_pid, si_uid, and so on.\n\
2251 \n\
2252 See os.waitid for more information.");
2253 
2254 static PyStructSequence_Field waitid_result_fields[] = {
2255     {"si_pid",  },
2256     {"si_uid", },
2257     {"si_signo", },
2258     {"si_status",  },
2259     {"si_code", },
2260     {0}
2261 };
2262 
2263 static PyStructSequence_Desc waitid_result_desc = {
2264     "waitid_result", /* name */
2265     waitid_result__doc__, /* doc */
2266     waitid_result_fields,
2267     5
2268 };
2269 #endif
2270 static newfunc structseq_new;
2271 
2272 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2273 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2274 {
2275     PyStructSequence *result;
2276     int i;
2277 
2278     result = (PyStructSequence*)structseq_new(type, args, kwds);
2279     if (!result)
2280         return NULL;
2281     /* If we have been initialized from a tuple,
2282        st_?time might be set to None. Initialize it
2283        from the int slots.  */
2284     for (i = 7; i <= 9; i++) {
2285         if (result->ob_item[i+3] == Py_None) {
2286             Py_DECREF(Py_None);
2287             Py_INCREF(result->ob_item[i]);
2288             result->ob_item[i+3] = result->ob_item[i];
2289         }
2290     }
2291     return (PyObject*)result;
2292 }
2293 
2294 static int
_posix_clear(PyObject * module)2295 _posix_clear(PyObject *module)
2296 {
2297     _posixstate *state = get_posix_state(module);
2298     Py_CLEAR(state->billion);
2299     Py_CLEAR(state->DirEntryType);
2300     Py_CLEAR(state->ScandirIteratorType);
2301 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2302     Py_CLEAR(state->SchedParamType);
2303 #endif
2304     Py_CLEAR(state->StatResultType);
2305     Py_CLEAR(state->StatVFSResultType);
2306     Py_CLEAR(state->TerminalSizeType);
2307     Py_CLEAR(state->TimesResultType);
2308     Py_CLEAR(state->UnameResultType);
2309 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2310     Py_CLEAR(state->WaitidResultType);
2311 #endif
2312 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2313     Py_CLEAR(state->struct_rusage);
2314 #endif
2315     Py_CLEAR(state->st_mode);
2316     return 0;
2317 }
2318 
2319 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2320 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2321 {
2322     _posixstate *state = get_posix_state(module);
2323     Py_VISIT(state->billion);
2324     Py_VISIT(state->DirEntryType);
2325     Py_VISIT(state->ScandirIteratorType);
2326 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2327     Py_VISIT(state->SchedParamType);
2328 #endif
2329     Py_VISIT(state->StatResultType);
2330     Py_VISIT(state->StatVFSResultType);
2331     Py_VISIT(state->TerminalSizeType);
2332     Py_VISIT(state->TimesResultType);
2333     Py_VISIT(state->UnameResultType);
2334 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2335     Py_VISIT(state->WaitidResultType);
2336 #endif
2337 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2338     Py_VISIT(state->struct_rusage);
2339 #endif
2340     Py_VISIT(state->st_mode);
2341     return 0;
2342 }
2343 
2344 static void
_posix_free(void * module)2345 _posix_free(void *module)
2346 {
2347    _posix_clear((PyObject *)module);
2348 }
2349 
2350 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2351 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2352 {
2353     PyObject *s = _PyLong_FromTime_t(sec);
2354     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2355     PyObject *s_in_ns = NULL;
2356     PyObject *ns_total = NULL;
2357     PyObject *float_s = NULL;
2358 
2359     if (!(s && ns_fractional))
2360         goto exit;
2361 
2362     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2363     if (!s_in_ns)
2364         goto exit;
2365 
2366     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2367     if (!ns_total)
2368         goto exit;
2369 
2370     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2371     if (!float_s) {
2372         goto exit;
2373     }
2374 
2375     PyStructSequence_SET_ITEM(v, index, s);
2376     PyStructSequence_SET_ITEM(v, index+3, float_s);
2377     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2378     s = NULL;
2379     float_s = NULL;
2380     ns_total = NULL;
2381 exit:
2382     Py_XDECREF(s);
2383     Py_XDECREF(ns_fractional);
2384     Py_XDECREF(s_in_ns);
2385     Py_XDECREF(ns_total);
2386     Py_XDECREF(float_s);
2387 }
2388 
2389 /* pack a system stat C structure into the Python stat tuple
2390    (used by posix_stat() and posix_fstat()) */
2391 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2392 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2393 {
2394     unsigned long ansec, mnsec, cnsec;
2395     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2396     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2397     if (v == NULL)
2398         return NULL;
2399 
2400     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2401     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(st->st_ino));
2402     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2403 #ifdef MS_WINDOWS
2404     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2405 #else
2406     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2407 #endif
2408     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2409 #if defined(MS_WINDOWS)
2410     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2411     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2412 #else
2413     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2414     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2415 #endif
2416     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(st->st_size));
2417     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2418 
2419 #if defined(HAVE_STAT_TV_NSEC)
2420     ansec = st->st_atim.tv_nsec;
2421     mnsec = st->st_mtim.tv_nsec;
2422     cnsec = st->st_ctim.tv_nsec;
2423 #elif defined(HAVE_STAT_TV_NSEC2)
2424     ansec = st->st_atimespec.tv_nsec;
2425     mnsec = st->st_mtimespec.tv_nsec;
2426     cnsec = st->st_ctimespec.tv_nsec;
2427 #elif defined(HAVE_STAT_NSEC)
2428     ansec = st->st_atime_nsec;
2429     mnsec = st->st_mtime_nsec;
2430     cnsec = st->st_ctime_nsec;
2431 #else
2432     ansec = mnsec = cnsec = 0;
2433 #endif
2434     fill_time(module, v, 7, st->st_atime, ansec);
2435     fill_time(module, v, 8, st->st_mtime, mnsec);
2436     fill_time(module, v, 9, st->st_ctime, cnsec);
2437 
2438 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2439     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2440                               PyLong_FromLong((long)st->st_blksize));
2441 #endif
2442 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2443     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2444                               PyLong_FromLong((long)st->st_blocks));
2445 #endif
2446 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2447     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2448                               PyLong_FromLong((long)st->st_rdev));
2449 #endif
2450 #ifdef HAVE_STRUCT_STAT_ST_GEN
2451     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2452                               PyLong_FromLong((long)st->st_gen));
2453 #endif
2454 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2455     {
2456       PyObject *val;
2457       unsigned long bsec,bnsec;
2458       bsec = (long)st->st_birthtime;
2459 #ifdef HAVE_STAT_TV_NSEC2
2460       bnsec = st->st_birthtimespec.tv_nsec;
2461 #else
2462       bnsec = 0;
2463 #endif
2464       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2465       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2466                                 val);
2467     }
2468 #endif
2469 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2470     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2471                               PyLong_FromLong((long)st->st_flags));
2472 #endif
2473 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2474     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2475                               PyLong_FromUnsignedLong(st->st_file_attributes));
2476 #endif
2477 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2478    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2479                               PyUnicode_FromString(st->st_fstype));
2480 #endif
2481 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2482     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2483                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2484 #endif
2485 
2486     if (PyErr_Occurred()) {
2487         Py_DECREF(v);
2488         return NULL;
2489     }
2490 
2491     return v;
2492 }
2493 
2494 /* POSIX methods */
2495 
2496 
2497 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2498 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2499               int dir_fd, int follow_symlinks)
2500 {
2501     STRUCT_STAT st;
2502     int result;
2503 
2504 #ifdef HAVE_FSTATAT
2505     int fstatat_unavailable = 0;
2506 #endif
2507 
2508 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2509     if (follow_symlinks_specified(function_name, follow_symlinks))
2510         return NULL;
2511 #endif
2512 
2513     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2514         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2515         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2516         return NULL;
2517 
2518     Py_BEGIN_ALLOW_THREADS
2519     if (path->fd != -1)
2520         result = FSTAT(path->fd, &st);
2521 #ifdef MS_WINDOWS
2522     else if (follow_symlinks)
2523         result = win32_stat(path->wide, &st);
2524     else
2525         result = win32_lstat(path->wide, &st);
2526 #else
2527     else
2528 #if defined(HAVE_LSTAT)
2529     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2530         result = LSTAT(path->narrow, &st);
2531     else
2532 #endif /* HAVE_LSTAT */
2533 #ifdef HAVE_FSTATAT
2534     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2535         if (HAVE_FSTATAT_RUNTIME) {
2536             result = fstatat(dir_fd, path->narrow, &st,
2537                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2538 
2539         } else {
2540             fstatat_unavailable = 1;
2541         }
2542     } else
2543 #endif /* HAVE_FSTATAT */
2544         result = STAT(path->narrow, &st);
2545 #endif /* MS_WINDOWS */
2546     Py_END_ALLOW_THREADS
2547 
2548 #ifdef HAVE_FSTATAT
2549     if (fstatat_unavailable) {
2550         argument_unavailable_error("stat", "dir_fd");
2551         return NULL;
2552     }
2553 #endif
2554 
2555     if (result != 0) {
2556         return path_error(path);
2557     }
2558 
2559     return _pystat_fromstructstat(module, &st);
2560 }
2561 
2562 /*[python input]
2563 
2564 for s in """
2565 
2566 FACCESSAT
2567 FCHMODAT
2568 FCHOWNAT
2569 FSTATAT
2570 LINKAT
2571 MKDIRAT
2572 MKFIFOAT
2573 MKNODAT
2574 OPENAT
2575 READLINKAT
2576 SYMLINKAT
2577 UNLINKAT
2578 
2579 """.strip().split():
2580     s = s.strip()
2581     print("""
2582 #ifdef HAVE_{s}
2583     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2584 #else
2585     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2586 #endif
2587 """.rstrip().format(s=s))
2588 
2589 for s in """
2590 
2591 FCHDIR
2592 FCHMOD
2593 FCHOWN
2594 FDOPENDIR
2595 FEXECVE
2596 FPATHCONF
2597 FSTATVFS
2598 FTRUNCATE
2599 
2600 """.strip().split():
2601     s = s.strip()
2602     print("""
2603 #ifdef HAVE_{s}
2604     #define PATH_HAVE_{s} 1
2605 #else
2606     #define PATH_HAVE_{s} 0
2607 #endif
2608 
2609 """.rstrip().format(s=s))
2610 [python start generated code]*/
2611 
2612 #ifdef HAVE_FACCESSAT
2613     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2614 #else
2615     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2616 #endif
2617 
2618 #ifdef HAVE_FCHMODAT
2619     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2620 #else
2621     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2622 #endif
2623 
2624 #ifdef HAVE_FCHOWNAT
2625     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2626 #else
2627     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2628 #endif
2629 
2630 #ifdef HAVE_FSTATAT
2631     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2632 #else
2633     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2634 #endif
2635 
2636 #ifdef HAVE_LINKAT
2637     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2638 #else
2639     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2640 #endif
2641 
2642 #ifdef HAVE_MKDIRAT
2643     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2644 #else
2645     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2646 #endif
2647 
2648 #ifdef HAVE_MKFIFOAT
2649     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2650 #else
2651     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2652 #endif
2653 
2654 #ifdef HAVE_MKNODAT
2655     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2656 #else
2657     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2658 #endif
2659 
2660 #ifdef HAVE_OPENAT
2661     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2662 #else
2663     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2664 #endif
2665 
2666 #ifdef HAVE_READLINKAT
2667     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2668 #else
2669     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2670 #endif
2671 
2672 #ifdef HAVE_SYMLINKAT
2673     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2674 #else
2675     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2676 #endif
2677 
2678 #ifdef HAVE_UNLINKAT
2679     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2680 #else
2681     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2682 #endif
2683 
2684 #ifdef HAVE_FCHDIR
2685     #define PATH_HAVE_FCHDIR 1
2686 #else
2687     #define PATH_HAVE_FCHDIR 0
2688 #endif
2689 
2690 #ifdef HAVE_FCHMOD
2691     #define PATH_HAVE_FCHMOD 1
2692 #else
2693     #define PATH_HAVE_FCHMOD 0
2694 #endif
2695 
2696 #ifdef HAVE_FCHOWN
2697     #define PATH_HAVE_FCHOWN 1
2698 #else
2699     #define PATH_HAVE_FCHOWN 0
2700 #endif
2701 
2702 #ifdef HAVE_FDOPENDIR
2703     #define PATH_HAVE_FDOPENDIR 1
2704 #else
2705     #define PATH_HAVE_FDOPENDIR 0
2706 #endif
2707 
2708 #ifdef HAVE_FEXECVE
2709     #define PATH_HAVE_FEXECVE 1
2710 #else
2711     #define PATH_HAVE_FEXECVE 0
2712 #endif
2713 
2714 #ifdef HAVE_FPATHCONF
2715     #define PATH_HAVE_FPATHCONF 1
2716 #else
2717     #define PATH_HAVE_FPATHCONF 0
2718 #endif
2719 
2720 #ifdef HAVE_FSTATVFS
2721     #define PATH_HAVE_FSTATVFS 1
2722 #else
2723     #define PATH_HAVE_FSTATVFS 0
2724 #endif
2725 
2726 #ifdef HAVE_FTRUNCATE
2727     #define PATH_HAVE_FTRUNCATE 1
2728 #else
2729     #define PATH_HAVE_FTRUNCATE 0
2730 #endif
2731 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2732 
2733 #ifdef MS_WINDOWS
2734     #undef PATH_HAVE_FTRUNCATE
2735     #define PATH_HAVE_FTRUNCATE 1
2736 #endif
2737 
2738 /*[python input]
2739 
2740 class path_t_converter(CConverter):
2741 
2742     type = "path_t"
2743     impl_by_reference = True
2744     parse_by_reference = True
2745 
2746     converter = 'path_converter'
2747 
2748     def converter_init(self, *, allow_fd=False, nullable=False):
2749         # right now path_t doesn't support default values.
2750         # to support a default value, you'll need to override initialize().
2751         if self.default not in (unspecified, None):
2752             fail("Can't specify a default to the path_t converter!")
2753 
2754         if self.c_default not in (None, 'Py_None'):
2755             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2756 
2757         self.nullable = nullable
2758         self.allow_fd = allow_fd
2759 
2760     def pre_render(self):
2761         def strify(value):
2762             if isinstance(value, str):
2763                 return value
2764             return str(int(bool(value)))
2765 
2766         # add self.py_name here when merging with posixmodule conversion
2767         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2768             self.function.name,
2769             self.name,
2770             strify(self.nullable),
2771             strify(self.allow_fd),
2772             )
2773 
2774     def cleanup(self):
2775         return "path_cleanup(&" + self.name + ");\n"
2776 
2777 
2778 class dir_fd_converter(CConverter):
2779     type = 'int'
2780 
2781     def converter_init(self, requires=None):
2782         if self.default in (unspecified, None):
2783             self.c_default = 'DEFAULT_DIR_FD'
2784         if isinstance(requires, str):
2785             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2786         else:
2787             self.converter = 'dir_fd_converter'
2788 
2789 class uid_t_converter(CConverter):
2790     type = "uid_t"
2791     converter = '_Py_Uid_Converter'
2792 
2793 class gid_t_converter(CConverter):
2794     type = "gid_t"
2795     converter = '_Py_Gid_Converter'
2796 
2797 class dev_t_converter(CConverter):
2798     type = 'dev_t'
2799     converter = '_Py_Dev_Converter'
2800 
2801 class dev_t_return_converter(unsigned_long_return_converter):
2802     type = 'dev_t'
2803     conversion_fn = '_PyLong_FromDev'
2804     unsigned_cast = '(dev_t)'
2805 
2806 class FSConverter_converter(CConverter):
2807     type = 'PyObject *'
2808     converter = 'PyUnicode_FSConverter'
2809     def converter_init(self):
2810         if self.default is not unspecified:
2811             fail("FSConverter_converter does not support default values")
2812         self.c_default = 'NULL'
2813 
2814     def cleanup(self):
2815         return "Py_XDECREF(" + self.name + ");\n"
2816 
2817 class pid_t_converter(CConverter):
2818     type = 'pid_t'
2819     format_unit = '" _Py_PARSE_PID "'
2820 
2821 class idtype_t_converter(int_converter):
2822     type = 'idtype_t'
2823 
2824 class id_t_converter(CConverter):
2825     type = 'id_t'
2826     format_unit = '" _Py_PARSE_PID "'
2827 
2828 class intptr_t_converter(CConverter):
2829     type = 'intptr_t'
2830     format_unit = '" _Py_PARSE_INTPTR "'
2831 
2832 class Py_off_t_converter(CConverter):
2833     type = 'Py_off_t'
2834     converter = 'Py_off_t_converter'
2835 
2836 class Py_off_t_return_converter(long_return_converter):
2837     type = 'Py_off_t'
2838     conversion_fn = 'PyLong_FromPy_off_t'
2839 
2840 class path_confname_converter(CConverter):
2841     type="int"
2842     converter="conv_path_confname"
2843 
2844 class confstr_confname_converter(path_confname_converter):
2845     converter='conv_confstr_confname'
2846 
2847 class sysconf_confname_converter(path_confname_converter):
2848     converter="conv_sysconf_confname"
2849 
2850 [python start generated code]*/
2851 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2852 
2853 /*[clinic input]
2854 
2855 os.stat
2856 
2857     path : path_t(allow_fd=True)
2858         Path to be examined; can be string, bytes, a path-like object or
2859         open-file-descriptor int.
2860 
2861     *
2862 
2863     dir_fd : dir_fd(requires='fstatat') = None
2864         If not None, it should be a file descriptor open to a directory,
2865         and path should be a relative string; path will then be relative to
2866         that directory.
2867 
2868     follow_symlinks: bool = True
2869         If False, and the last element of the path is a symbolic link,
2870         stat will examine the symbolic link itself instead of the file
2871         the link points to.
2872 
2873 Perform a stat system call on the given path.
2874 
2875 dir_fd and follow_symlinks may not be implemented
2876   on your platform.  If they are unavailable, using them will raise a
2877   NotImplementedError.
2878 
2879 It's an error to use dir_fd or follow_symlinks when specifying path as
2880   an open file descriptor.
2881 
2882 [clinic start generated code]*/
2883 
2884 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2885 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2886 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2887 {
2888     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2889 }
2890 
2891 
2892 /*[clinic input]
2893 os.lstat
2894 
2895     path : path_t
2896 
2897     *
2898 
2899     dir_fd : dir_fd(requires='fstatat') = None
2900 
2901 Perform a stat system call on the given path, without following symbolic links.
2902 
2903 Like stat(), but do not follow symbolic links.
2904 Equivalent to stat(path, follow_symlinks=False).
2905 [clinic start generated code]*/
2906 
2907 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2908 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2909 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2910 {
2911     int follow_symlinks = 0;
2912     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2913 }
2914 
2915 
2916 /*[clinic input]
2917 os.access -> bool
2918 
2919     path: path_t
2920         Path to be tested; can be string, bytes, or a path-like object.
2921 
2922     mode: int
2923         Operating-system mode bitfield.  Can be F_OK to test existence,
2924         or the inclusive-OR of R_OK, W_OK, and X_OK.
2925 
2926     *
2927 
2928     dir_fd : dir_fd(requires='faccessat') = None
2929         If not None, it should be a file descriptor open to a directory,
2930         and path should be relative; path will then be relative to that
2931         directory.
2932 
2933     effective_ids: bool = False
2934         If True, access will use the effective uid/gid instead of
2935         the real uid/gid.
2936 
2937     follow_symlinks: bool = True
2938         If False, and the last element of the path is a symbolic link,
2939         access will examine the symbolic link itself instead of the file
2940         the link points to.
2941 
2942 Use the real uid/gid to test for access to a path.
2943 
2944 {parameters}
2945 dir_fd, effective_ids, and follow_symlinks may not be implemented
2946   on your platform.  If they are unavailable, using them will raise a
2947   NotImplementedError.
2948 
2949 Note that most operations will use the effective uid/gid, therefore this
2950   routine can be used in a suid/sgid environment to test if the invoking user
2951   has the specified access to the path.
2952 
2953 [clinic start generated code]*/
2954 
2955 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2956 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2957                int effective_ids, int follow_symlinks)
2958 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2959 {
2960     int return_value;
2961 
2962 #ifdef MS_WINDOWS
2963     DWORD attr;
2964 #else
2965     int result;
2966 #endif
2967 
2968 #ifdef HAVE_FACCESSAT
2969     int faccessat_unavailable = 0;
2970 #endif
2971 
2972 #ifndef HAVE_FACCESSAT
2973     if (follow_symlinks_specified("access", follow_symlinks))
2974         return -1;
2975 
2976     if (effective_ids) {
2977         argument_unavailable_error("access", "effective_ids");
2978         return -1;
2979     }
2980 #endif
2981 
2982 #ifdef MS_WINDOWS
2983     Py_BEGIN_ALLOW_THREADS
2984     attr = GetFileAttributesW(path->wide);
2985     Py_END_ALLOW_THREADS
2986 
2987     /*
2988      * Access is possible if
2989      *   * we didn't get a -1, and
2990      *     * write access wasn't requested,
2991      *     * or the file isn't read-only,
2992      *     * or it's a directory.
2993      * (Directories cannot be read-only on Windows.)
2994     */
2995     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
2996             (!(mode & 2) ||
2997             !(attr & FILE_ATTRIBUTE_READONLY) ||
2998             (attr & FILE_ATTRIBUTE_DIRECTORY));
2999 #else
3000 
3001     Py_BEGIN_ALLOW_THREADS
3002 #ifdef HAVE_FACCESSAT
3003     if ((dir_fd != DEFAULT_DIR_FD) ||
3004         effective_ids ||
3005         !follow_symlinks) {
3006 
3007         if (HAVE_FACCESSAT_RUNTIME) {
3008             int flags = 0;
3009             if (!follow_symlinks)
3010                 flags |= AT_SYMLINK_NOFOLLOW;
3011             if (effective_ids)
3012                 flags |= AT_EACCESS;
3013             result = faccessat(dir_fd, path->narrow, mode, flags);
3014         } else {
3015             faccessat_unavailable = 1;
3016         }
3017     }
3018     else
3019 #endif
3020         result = access(path->narrow, mode);
3021     Py_END_ALLOW_THREADS
3022 
3023 #ifdef HAVE_FACCESSAT
3024     if (faccessat_unavailable) {
3025         if (dir_fd != DEFAULT_DIR_FD) {
3026             argument_unavailable_error("access", "dir_fd");
3027             return -1;
3028         }
3029         if (follow_symlinks_specified("access", follow_symlinks))
3030             return -1;
3031 
3032         if (effective_ids) {
3033             argument_unavailable_error("access", "effective_ids");
3034             return -1;
3035         }
3036         /* should be unreachable */
3037         return -1;
3038     }
3039 #endif
3040     return_value = !result;
3041 #endif
3042 
3043     return return_value;
3044 }
3045 
3046 #ifndef F_OK
3047 #define F_OK 0
3048 #endif
3049 #ifndef R_OK
3050 #define R_OK 4
3051 #endif
3052 #ifndef W_OK
3053 #define W_OK 2
3054 #endif
3055 #ifndef X_OK
3056 #define X_OK 1
3057 #endif
3058 
3059 
3060 #ifdef HAVE_TTYNAME
3061 /*[clinic input]
3062 os.ttyname
3063 
3064     fd: int
3065         Integer file descriptor handle.
3066 
3067     /
3068 
3069 Return the name of the terminal device connected to 'fd'.
3070 [clinic start generated code]*/
3071 
3072 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3073 os_ttyname_impl(PyObject *module, int fd)
3074 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3075 {
3076 
3077     long size = sysconf(_SC_TTY_NAME_MAX);
3078     if (size == -1) {
3079         return posix_error();
3080     }
3081     char *buffer = (char *)PyMem_RawMalloc(size);
3082     if (buffer == NULL) {
3083         return PyErr_NoMemory();
3084     }
3085     int ret = ttyname_r(fd, buffer, size);
3086     if (ret != 0) {
3087         PyMem_RawFree(buffer);
3088         errno = ret;
3089         return posix_error();
3090     }
3091     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3092     PyMem_RawFree(buffer);
3093     return res;
3094 }
3095 #endif
3096 
3097 #ifdef HAVE_CTERMID
3098 /*[clinic input]
3099 os.ctermid
3100 
3101 Return the name of the controlling terminal for this process.
3102 [clinic start generated code]*/
3103 
3104 static PyObject *
os_ctermid_impl(PyObject * module)3105 os_ctermid_impl(PyObject *module)
3106 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3107 {
3108     char *ret;
3109     char buffer[L_ctermid];
3110 
3111 #ifdef USE_CTERMID_R
3112     ret = ctermid_r(buffer);
3113 #else
3114     ret = ctermid(buffer);
3115 #endif
3116     if (ret == NULL)
3117         return posix_error();
3118     return PyUnicode_DecodeFSDefault(buffer);
3119 }
3120 #endif /* HAVE_CTERMID */
3121 
3122 
3123 /*[clinic input]
3124 os.chdir
3125 
3126     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3127 
3128 Change the current working directory to the specified path.
3129 
3130 path may always be specified as a string.
3131 On some platforms, path may also be specified as an open file descriptor.
3132   If this functionality is unavailable, using it raises an exception.
3133 [clinic start generated code]*/
3134 
3135 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3136 os_chdir_impl(PyObject *module, path_t *path)
3137 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3138 {
3139     int result;
3140 
3141     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3142         return NULL;
3143     }
3144 
3145     Py_BEGIN_ALLOW_THREADS
3146 #ifdef MS_WINDOWS
3147     /* on unix, success = 0, on windows, success = !0 */
3148     result = !win32_wchdir(path->wide);
3149 #else
3150 #ifdef HAVE_FCHDIR
3151     if (path->fd != -1)
3152         result = fchdir(path->fd);
3153     else
3154 #endif
3155         result = chdir(path->narrow);
3156 #endif
3157     Py_END_ALLOW_THREADS
3158 
3159     if (result) {
3160         return path_error(path);
3161     }
3162 
3163     Py_RETURN_NONE;
3164 }
3165 
3166 
3167 #ifdef HAVE_FCHDIR
3168 /*[clinic input]
3169 os.fchdir
3170 
3171     fd: fildes
3172 
3173 Change to the directory of the given file descriptor.
3174 
3175 fd must be opened on a directory, not a file.
3176 Equivalent to os.chdir(fd).
3177 
3178 [clinic start generated code]*/
3179 
3180 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3181 os_fchdir_impl(PyObject *module, int fd)
3182 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3183 {
3184     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3185         return NULL;
3186     }
3187     return posix_fildes_fd(fd, fchdir);
3188 }
3189 #endif /* HAVE_FCHDIR */
3190 
3191 
3192 /*[clinic input]
3193 os.chmod
3194 
3195     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3196         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3197         On some platforms, path may also be specified as an open file descriptor.
3198         If this functionality is unavailable, using it raises an exception.
3199 
3200     mode: int
3201         Operating-system mode bitfield.
3202 
3203     *
3204 
3205     dir_fd : dir_fd(requires='fchmodat') = None
3206         If not None, it should be a file descriptor open to a directory,
3207         and path should be relative; path will then be relative to that
3208         directory.
3209 
3210     follow_symlinks: bool = True
3211         If False, and the last element of the path is a symbolic link,
3212         chmod will modify the symbolic link itself instead of the file
3213         the link points to.
3214 
3215 Change the access permissions of a file.
3216 
3217 It is an error to use dir_fd or follow_symlinks when specifying path as
3218   an open file descriptor.
3219 dir_fd and follow_symlinks may not be implemented on your platform.
3220   If they are unavailable, using them will raise a NotImplementedError.
3221 
3222 [clinic start generated code]*/
3223 
3224 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3225 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3226               int follow_symlinks)
3227 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3228 {
3229     int result;
3230 
3231 #ifdef MS_WINDOWS
3232     DWORD attr;
3233 #endif
3234 
3235 #ifdef HAVE_FCHMODAT
3236     int fchmodat_nofollow_unsupported = 0;
3237     int fchmodat_unsupported = 0;
3238 #endif
3239 
3240 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3241     if (follow_symlinks_specified("chmod", follow_symlinks))
3242         return NULL;
3243 #endif
3244 
3245     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3246                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3247         return NULL;
3248     }
3249 
3250 #ifdef MS_WINDOWS
3251     Py_BEGIN_ALLOW_THREADS
3252     attr = GetFileAttributesW(path->wide);
3253     if (attr == INVALID_FILE_ATTRIBUTES)
3254         result = 0;
3255     else {
3256         if (mode & _S_IWRITE)
3257             attr &= ~FILE_ATTRIBUTE_READONLY;
3258         else
3259             attr |= FILE_ATTRIBUTE_READONLY;
3260         result = SetFileAttributesW(path->wide, attr);
3261     }
3262     Py_END_ALLOW_THREADS
3263 
3264     if (!result) {
3265         return path_error(path);
3266     }
3267 #else /* MS_WINDOWS */
3268     Py_BEGIN_ALLOW_THREADS
3269 #ifdef HAVE_FCHMOD
3270     if (path->fd != -1)
3271         result = fchmod(path->fd, mode);
3272     else
3273 #endif /* HAVE_CHMOD */
3274 #ifdef HAVE_LCHMOD
3275     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3276         result = lchmod(path->narrow, mode);
3277     else
3278 #endif /* HAVE_LCHMOD */
3279 #ifdef HAVE_FCHMODAT
3280     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3281         if (HAVE_FCHMODAT_RUNTIME) {
3282             /*
3283              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3284              * The documentation specifically shows how to use it,
3285              * and then says it isn't implemented yet.
3286              * (true on linux with glibc 2.15, and openindiana 3.x)
3287              *
3288              * Once it is supported, os.chmod will automatically
3289              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3290              * Until then, we need to be careful what exception we raise.
3291              */
3292             result = fchmodat(dir_fd, path->narrow, mode,
3293                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3294             /*
3295              * But wait!  We can't throw the exception without allowing threads,
3296              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3297              */
3298             fchmodat_nofollow_unsupported =
3299                              result &&
3300                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3301                              !follow_symlinks;
3302         } else {
3303             fchmodat_unsupported = 1;
3304             fchmodat_nofollow_unsupported = 1;
3305 
3306             result = -1;
3307         }
3308     }
3309     else
3310 #endif /* HAVE_FHCMODAT */
3311         result = chmod(path->narrow, mode);
3312     Py_END_ALLOW_THREADS
3313 
3314     if (result) {
3315 #ifdef HAVE_FCHMODAT
3316         if (fchmodat_unsupported) {
3317             if (dir_fd != DEFAULT_DIR_FD) {
3318                 argument_unavailable_error("chmod", "dir_fd");
3319                 return NULL;
3320             }
3321         }
3322 
3323         if (fchmodat_nofollow_unsupported) {
3324             if (dir_fd != DEFAULT_DIR_FD)
3325                 dir_fd_and_follow_symlinks_invalid("chmod",
3326                                                    dir_fd, follow_symlinks);
3327             else
3328                 follow_symlinks_specified("chmod", follow_symlinks);
3329             return NULL;
3330         }
3331         else
3332 #endif /* HAVE_FCHMODAT */
3333         return path_error(path);
3334     }
3335 #endif /* MS_WINDOWS */
3336 
3337     Py_RETURN_NONE;
3338 }
3339 
3340 
3341 #ifdef HAVE_FCHMOD
3342 /*[clinic input]
3343 os.fchmod
3344 
3345     fd: int
3346     mode: int
3347 
3348 Change the access permissions of the file given by file descriptor fd.
3349 
3350 Equivalent to os.chmod(fd, mode).
3351 [clinic start generated code]*/
3352 
3353 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3354 os_fchmod_impl(PyObject *module, int fd, int mode)
3355 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3356 {
3357     int res;
3358     int async_err = 0;
3359 
3360     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3361         return NULL;
3362     }
3363 
3364     do {
3365         Py_BEGIN_ALLOW_THREADS
3366         res = fchmod(fd, mode);
3367         Py_END_ALLOW_THREADS
3368     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3369     if (res != 0)
3370         return (!async_err) ? posix_error() : NULL;
3371 
3372     Py_RETURN_NONE;
3373 }
3374 #endif /* HAVE_FCHMOD */
3375 
3376 
3377 #ifdef HAVE_LCHMOD
3378 /*[clinic input]
3379 os.lchmod
3380 
3381     path: path_t
3382     mode: int
3383 
3384 Change the access permissions of a file, without following symbolic links.
3385 
3386 If path is a symlink, this affects the link itself rather than the target.
3387 Equivalent to chmod(path, mode, follow_symlinks=False)."
3388 [clinic start generated code]*/
3389 
3390 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3391 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3392 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3393 {
3394     int res;
3395     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3396         return NULL;
3397     }
3398     Py_BEGIN_ALLOW_THREADS
3399     res = lchmod(path->narrow, mode);
3400     Py_END_ALLOW_THREADS
3401     if (res < 0) {
3402         path_error(path);
3403         return NULL;
3404     }
3405     Py_RETURN_NONE;
3406 }
3407 #endif /* HAVE_LCHMOD */
3408 
3409 
3410 #ifdef HAVE_CHFLAGS
3411 /*[clinic input]
3412 os.chflags
3413 
3414     path: path_t
3415     flags: unsigned_long(bitwise=True)
3416     follow_symlinks: bool=True
3417 
3418 Set file flags.
3419 
3420 If follow_symlinks is False, and the last element of the path is a symbolic
3421   link, chflags will change flags on the symbolic link itself instead of the
3422   file the link points to.
3423 follow_symlinks may not be implemented on your platform.  If it is
3424 unavailable, using it will raise a NotImplementedError.
3425 
3426 [clinic start generated code]*/
3427 
3428 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3429 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3430                 int follow_symlinks)
3431 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3432 {
3433     int result;
3434 
3435 #ifndef HAVE_LCHFLAGS
3436     if (follow_symlinks_specified("chflags", follow_symlinks))
3437         return NULL;
3438 #endif
3439 
3440     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3441         return NULL;
3442     }
3443 
3444     Py_BEGIN_ALLOW_THREADS
3445 #ifdef HAVE_LCHFLAGS
3446     if (!follow_symlinks)
3447         result = lchflags(path->narrow, flags);
3448     else
3449 #endif
3450         result = chflags(path->narrow, flags);
3451     Py_END_ALLOW_THREADS
3452 
3453     if (result)
3454         return path_error(path);
3455 
3456     Py_RETURN_NONE;
3457 }
3458 #endif /* HAVE_CHFLAGS */
3459 
3460 
3461 #ifdef HAVE_LCHFLAGS
3462 /*[clinic input]
3463 os.lchflags
3464 
3465     path: path_t
3466     flags: unsigned_long(bitwise=True)
3467 
3468 Set file flags.
3469 
3470 This function will not follow symbolic links.
3471 Equivalent to chflags(path, flags, follow_symlinks=False).
3472 [clinic start generated code]*/
3473 
3474 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3475 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3476 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3477 {
3478     int res;
3479     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3480         return NULL;
3481     }
3482     Py_BEGIN_ALLOW_THREADS
3483     res = lchflags(path->narrow, flags);
3484     Py_END_ALLOW_THREADS
3485     if (res < 0) {
3486         return path_error(path);
3487     }
3488     Py_RETURN_NONE;
3489 }
3490 #endif /* HAVE_LCHFLAGS */
3491 
3492 
3493 #ifdef HAVE_CHROOT
3494 /*[clinic input]
3495 os.chroot
3496     path: path_t
3497 
3498 Change root directory to path.
3499 
3500 [clinic start generated code]*/
3501 
3502 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3503 os_chroot_impl(PyObject *module, path_t *path)
3504 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3505 {
3506     int res;
3507     Py_BEGIN_ALLOW_THREADS
3508     res = chroot(path->narrow);
3509     Py_END_ALLOW_THREADS
3510     if (res < 0)
3511         return path_error(path);
3512     Py_RETURN_NONE;
3513 }
3514 #endif /* HAVE_CHROOT */
3515 
3516 
3517 #ifdef HAVE_FSYNC
3518 /*[clinic input]
3519 os.fsync
3520 
3521     fd: fildes
3522 
3523 Force write of fd to disk.
3524 [clinic start generated code]*/
3525 
3526 static PyObject *
os_fsync_impl(PyObject * module,int fd)3527 os_fsync_impl(PyObject *module, int fd)
3528 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3529 {
3530     return posix_fildes_fd(fd, fsync);
3531 }
3532 #endif /* HAVE_FSYNC */
3533 
3534 
3535 #ifdef HAVE_SYNC
3536 /*[clinic input]
3537 os.sync
3538 
3539 Force write of everything to disk.
3540 [clinic start generated code]*/
3541 
3542 static PyObject *
os_sync_impl(PyObject * module)3543 os_sync_impl(PyObject *module)
3544 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3545 {
3546     Py_BEGIN_ALLOW_THREADS
3547     sync();
3548     Py_END_ALLOW_THREADS
3549     Py_RETURN_NONE;
3550 }
3551 #endif /* HAVE_SYNC */
3552 
3553 
3554 #ifdef HAVE_FDATASYNC
3555 #ifdef __hpux
3556 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3557 #endif
3558 
3559 /*[clinic input]
3560 os.fdatasync
3561 
3562     fd: fildes
3563 
3564 Force write of fd to disk without forcing update of metadata.
3565 [clinic start generated code]*/
3566 
3567 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3568 os_fdatasync_impl(PyObject *module, int fd)
3569 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3570 {
3571     return posix_fildes_fd(fd, fdatasync);
3572 }
3573 #endif /* HAVE_FDATASYNC */
3574 
3575 
3576 #ifdef HAVE_CHOWN
3577 /*[clinic input]
3578 os.chown
3579 
3580     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3581         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3582 
3583     uid: uid_t
3584 
3585     gid: gid_t
3586 
3587     *
3588 
3589     dir_fd : dir_fd(requires='fchownat') = None
3590         If not None, it should be a file descriptor open to a directory,
3591         and path should be relative; path will then be relative to that
3592         directory.
3593 
3594     follow_symlinks: bool = True
3595         If False, and the last element of the path is a symbolic link,
3596         stat will examine the symbolic link itself instead of the file
3597         the link points to.
3598 
3599 Change the owner and group id of path to the numeric uid and gid.\
3600 
3601 path may always be specified as a string.
3602 On some platforms, path may also be specified as an open file descriptor.
3603   If this functionality is unavailable, using it raises an exception.
3604 If dir_fd is not None, it should be a file descriptor open to a directory,
3605   and path should be relative; path will then be relative to that directory.
3606 If follow_symlinks is False, and the last element of the path is a symbolic
3607   link, chown will modify the symbolic link itself instead of the file the
3608   link points to.
3609 It is an error to use dir_fd or follow_symlinks when specifying path as
3610   an open file descriptor.
3611 dir_fd and follow_symlinks may not be implemented on your platform.
3612   If they are unavailable, using them will raise a NotImplementedError.
3613 
3614 [clinic start generated code]*/
3615 
3616 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3617 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3618               int dir_fd, int follow_symlinks)
3619 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3620 {
3621     int result;
3622 
3623 #if defined(HAVE_FCHOWNAT)
3624     int fchownat_unsupported = 0;
3625 #endif
3626 
3627 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3628     if (follow_symlinks_specified("chown", follow_symlinks))
3629         return NULL;
3630 #endif
3631     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3632         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3633         return NULL;
3634 
3635     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3636                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3637         return NULL;
3638     }
3639 
3640     Py_BEGIN_ALLOW_THREADS
3641 #ifdef HAVE_FCHOWN
3642     if (path->fd != -1)
3643         result = fchown(path->fd, uid, gid);
3644     else
3645 #endif
3646 #ifdef HAVE_LCHOWN
3647     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3648         result = lchown(path->narrow, uid, gid);
3649     else
3650 #endif
3651 #ifdef HAVE_FCHOWNAT
3652     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3653       if (HAVE_FCHOWNAT_RUNTIME) {
3654         result = fchownat(dir_fd, path->narrow, uid, gid,
3655                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3656       } else {
3657          fchownat_unsupported = 1;
3658       }
3659     } else
3660 #endif
3661         result = chown(path->narrow, uid, gid);
3662     Py_END_ALLOW_THREADS
3663 
3664 #ifdef HAVE_FCHOWNAT
3665     if (fchownat_unsupported) {
3666         /* This would be incorrect if the current platform
3667          * doesn't support lchown.
3668          */
3669         argument_unavailable_error(NULL, "dir_fd");
3670         return NULL;
3671     }
3672 #endif
3673 
3674     if (result)
3675         return path_error(path);
3676 
3677     Py_RETURN_NONE;
3678 }
3679 #endif /* HAVE_CHOWN */
3680 
3681 
3682 #ifdef HAVE_FCHOWN
3683 /*[clinic input]
3684 os.fchown
3685 
3686     fd: int
3687     uid: uid_t
3688     gid: gid_t
3689 
3690 Change the owner and group id of the file specified by file descriptor.
3691 
3692 Equivalent to os.chown(fd, uid, gid).
3693 
3694 [clinic start generated code]*/
3695 
3696 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3697 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3698 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3699 {
3700     int res;
3701     int async_err = 0;
3702 
3703     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3704         return NULL;
3705     }
3706 
3707     do {
3708         Py_BEGIN_ALLOW_THREADS
3709         res = fchown(fd, uid, gid);
3710         Py_END_ALLOW_THREADS
3711     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3712     if (res != 0)
3713         return (!async_err) ? posix_error() : NULL;
3714 
3715     Py_RETURN_NONE;
3716 }
3717 #endif /* HAVE_FCHOWN */
3718 
3719 
3720 #ifdef HAVE_LCHOWN
3721 /*[clinic input]
3722 os.lchown
3723 
3724     path : path_t
3725     uid: uid_t
3726     gid: gid_t
3727 
3728 Change the owner and group id of path to the numeric uid and gid.
3729 
3730 This function will not follow symbolic links.
3731 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3732 [clinic start generated code]*/
3733 
3734 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3735 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3736 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3737 {
3738     int res;
3739     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3740         return NULL;
3741     }
3742     Py_BEGIN_ALLOW_THREADS
3743     res = lchown(path->narrow, uid, gid);
3744     Py_END_ALLOW_THREADS
3745     if (res < 0) {
3746         return path_error(path);
3747     }
3748     Py_RETURN_NONE;
3749 }
3750 #endif /* HAVE_LCHOWN */
3751 
3752 
3753 static PyObject *
posix_getcwd(int use_bytes)3754 posix_getcwd(int use_bytes)
3755 {
3756 #ifdef MS_WINDOWS
3757     wchar_t wbuf[MAXPATHLEN];
3758     wchar_t *wbuf2 = wbuf;
3759     DWORD len;
3760 
3761     Py_BEGIN_ALLOW_THREADS
3762     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3763     /* If the buffer is large enough, len does not include the
3764        terminating \0. If the buffer is too small, len includes
3765        the space needed for the terminator. */
3766     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3767         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3768             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3769         }
3770         else {
3771             wbuf2 = NULL;
3772         }
3773         if (wbuf2) {
3774             len = GetCurrentDirectoryW(len, wbuf2);
3775         }
3776     }
3777     Py_END_ALLOW_THREADS
3778 
3779     if (!wbuf2) {
3780         PyErr_NoMemory();
3781         return NULL;
3782     }
3783     if (!len) {
3784         if (wbuf2 != wbuf)
3785             PyMem_RawFree(wbuf2);
3786         return PyErr_SetFromWindowsErr(0);
3787     }
3788 
3789     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3790     if (wbuf2 != wbuf) {
3791         PyMem_RawFree(wbuf2);
3792     }
3793 
3794     if (use_bytes) {
3795         if (resobj == NULL) {
3796             return NULL;
3797         }
3798         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3799     }
3800 
3801     return resobj;
3802 #else
3803     const size_t chunk = 1024;
3804 
3805     char *buf = NULL;
3806     char *cwd = NULL;
3807     size_t buflen = 0;
3808 
3809     Py_BEGIN_ALLOW_THREADS
3810     do {
3811         char *newbuf;
3812         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3813             buflen += chunk;
3814             newbuf = PyMem_RawRealloc(buf, buflen);
3815         }
3816         else {
3817             newbuf = NULL;
3818         }
3819         if (newbuf == NULL) {
3820             PyMem_RawFree(buf);
3821             buf = NULL;
3822             break;
3823         }
3824         buf = newbuf;
3825 
3826         cwd = getcwd(buf, buflen);
3827     } while (cwd == NULL && errno == ERANGE);
3828     Py_END_ALLOW_THREADS
3829 
3830     if (buf == NULL) {
3831         return PyErr_NoMemory();
3832     }
3833     if (cwd == NULL) {
3834         PyMem_RawFree(buf);
3835         return posix_error();
3836     }
3837 
3838     PyObject *obj;
3839     if (use_bytes) {
3840         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3841     }
3842     else {
3843         obj = PyUnicode_DecodeFSDefault(buf);
3844     }
3845     PyMem_RawFree(buf);
3846 
3847     return obj;
3848 #endif   /* !MS_WINDOWS */
3849 }
3850 
3851 
3852 /*[clinic input]
3853 os.getcwd
3854 
3855 Return a unicode string representing the current working directory.
3856 [clinic start generated code]*/
3857 
3858 static PyObject *
os_getcwd_impl(PyObject * module)3859 os_getcwd_impl(PyObject *module)
3860 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3861 {
3862     return posix_getcwd(0);
3863 }
3864 
3865 
3866 /*[clinic input]
3867 os.getcwdb
3868 
3869 Return a bytes string representing the current working directory.
3870 [clinic start generated code]*/
3871 
3872 static PyObject *
os_getcwdb_impl(PyObject * module)3873 os_getcwdb_impl(PyObject *module)
3874 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3875 {
3876     return posix_getcwd(1);
3877 }
3878 
3879 
3880 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3881 #define HAVE_LINK 1
3882 #endif
3883 
3884 #ifdef HAVE_LINK
3885 /*[clinic input]
3886 
3887 os.link
3888 
3889     src : path_t
3890     dst : path_t
3891     *
3892     src_dir_fd : dir_fd = None
3893     dst_dir_fd : dir_fd = None
3894     follow_symlinks: bool = True
3895 
3896 Create a hard link to a file.
3897 
3898 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3899   descriptor open to a directory, and the respective path string (src or dst)
3900   should be relative; the path will then be relative to that directory.
3901 If follow_symlinks is False, and the last element of src is a symbolic
3902   link, link will create a link to the symbolic link itself instead of the
3903   file the link points to.
3904 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3905   platform.  If they are unavailable, using them will raise a
3906   NotImplementedError.
3907 [clinic start generated code]*/
3908 
3909 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3910 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3911              int dst_dir_fd, int follow_symlinks)
3912 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3913 {
3914 #ifdef MS_WINDOWS
3915     BOOL result = FALSE;
3916 #else
3917     int result;
3918 #endif
3919 #if defined(HAVE_LINKAT)
3920     int linkat_unavailable = 0;
3921 #endif
3922 
3923 #ifndef HAVE_LINKAT
3924     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3925         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3926         return NULL;
3927     }
3928 #endif
3929 
3930 #ifndef MS_WINDOWS
3931     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3932         PyErr_SetString(PyExc_NotImplementedError,
3933                         "link: src and dst must be the same type");
3934         return NULL;
3935     }
3936 #endif
3937 
3938     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3939                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3940                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3941         return NULL;
3942     }
3943 
3944 #ifdef MS_WINDOWS
3945     Py_BEGIN_ALLOW_THREADS
3946     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3947     Py_END_ALLOW_THREADS
3948 
3949     if (!result)
3950         return path_error2(src, dst);
3951 #else
3952     Py_BEGIN_ALLOW_THREADS
3953 #ifdef HAVE_LINKAT
3954     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3955         (dst_dir_fd != DEFAULT_DIR_FD) ||
3956         (!follow_symlinks)) {
3957 
3958         if (HAVE_LINKAT_RUNTIME) {
3959 
3960             result = linkat(src_dir_fd, src->narrow,
3961                 dst_dir_fd, dst->narrow,
3962                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3963 
3964         }
3965 #ifdef __APPLE__
3966         else {
3967             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3968                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3969                 result = link(src->narrow, dst->narrow);
3970             } else {
3971                 linkat_unavailable = 1;
3972             }
3973         }
3974 #endif
3975     }
3976     else
3977 #endif /* HAVE_LINKAT */
3978         result = link(src->narrow, dst->narrow);
3979     Py_END_ALLOW_THREADS
3980 
3981 #ifdef HAVE_LINKAT
3982     if (linkat_unavailable) {
3983         /* Either or both dir_fd arguments were specified */
3984         if (src_dir_fd  != DEFAULT_DIR_FD) {
3985             argument_unavailable_error("link", "src_dir_fd");
3986         } else {
3987             argument_unavailable_error("link", "dst_dir_fd");
3988         }
3989         return NULL;
3990     }
3991 #endif
3992 
3993     if (result)
3994         return path_error2(src, dst);
3995 #endif /* MS_WINDOWS */
3996 
3997     Py_RETURN_NONE;
3998 }
3999 #endif
4000 
4001 
4002 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4003 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)4004 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4005 {
4006     PyObject *v;
4007     HANDLE hFindFile = INVALID_HANDLE_VALUE;
4008     BOOL result;
4009     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4010     /* only claim to have space for MAX_PATH */
4011     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4012     wchar_t *wnamebuf = NULL;
4013 
4014     WIN32_FIND_DATAW wFileData;
4015     const wchar_t *po_wchars;
4016 
4017     if (!path->wide) { /* Default arg: "." */
4018         po_wchars = L".";
4019         len = 1;
4020     } else {
4021         po_wchars = path->wide;
4022         len = wcslen(path->wide);
4023     }
4024     /* The +5 is so we can append "\\*.*\0" */
4025     wnamebuf = PyMem_New(wchar_t, len + 5);
4026     if (!wnamebuf) {
4027         PyErr_NoMemory();
4028         goto exit;
4029     }
4030     wcscpy(wnamebuf, po_wchars);
4031     if (len > 0) {
4032         wchar_t wch = wnamebuf[len-1];
4033         if (wch != SEP && wch != ALTSEP && wch != L':')
4034             wnamebuf[len++] = SEP;
4035         wcscpy(wnamebuf + len, L"*.*");
4036     }
4037     if ((list = PyList_New(0)) == NULL) {
4038         goto exit;
4039     }
4040     Py_BEGIN_ALLOW_THREADS
4041     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4042     Py_END_ALLOW_THREADS
4043     if (hFindFile == INVALID_HANDLE_VALUE) {
4044         int error = GetLastError();
4045         if (error == ERROR_FILE_NOT_FOUND)
4046             goto exit;
4047         Py_DECREF(list);
4048         list = path_error(path);
4049         goto exit;
4050     }
4051     do {
4052         /* Skip over . and .. */
4053         if (wcscmp(wFileData.cFileName, L".") != 0 &&
4054             wcscmp(wFileData.cFileName, L"..") != 0) {
4055             v = PyUnicode_FromWideChar(wFileData.cFileName,
4056                                        wcslen(wFileData.cFileName));
4057             if (path->narrow && v) {
4058                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4059             }
4060             if (v == NULL) {
4061                 Py_DECREF(list);
4062                 list = NULL;
4063                 break;
4064             }
4065             if (PyList_Append(list, v) != 0) {
4066                 Py_DECREF(v);
4067                 Py_DECREF(list);
4068                 list = NULL;
4069                 break;
4070             }
4071             Py_DECREF(v);
4072         }
4073         Py_BEGIN_ALLOW_THREADS
4074         result = FindNextFileW(hFindFile, &wFileData);
4075         Py_END_ALLOW_THREADS
4076         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4077            it got to the end of the directory. */
4078         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4079             Py_DECREF(list);
4080             list = path_error(path);
4081             goto exit;
4082         }
4083     } while (result == TRUE);
4084 
4085 exit:
4086     if (hFindFile != INVALID_HANDLE_VALUE) {
4087         if (FindClose(hFindFile) == FALSE) {
4088             if (list != NULL) {
4089                 Py_DECREF(list);
4090                 list = path_error(path);
4091             }
4092         }
4093     }
4094     PyMem_Free(wnamebuf);
4095 
4096     return list;
4097 }  /* end of _listdir_windows_no_opendir */
4098 
4099 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4100 
4101 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4102 _posix_listdir(path_t *path, PyObject *list)
4103 {
4104     PyObject *v;
4105     DIR *dirp = NULL;
4106     struct dirent *ep;
4107     int return_str; /* if false, return bytes */
4108 #ifdef HAVE_FDOPENDIR
4109     int fd = -1;
4110 #endif
4111 
4112     errno = 0;
4113 #ifdef HAVE_FDOPENDIR
4114     if (path->fd != -1) {
4115       if (HAVE_FDOPENDIR_RUNTIME) {
4116         /* closedir() closes the FD, so we duplicate it */
4117         fd = _Py_dup(path->fd);
4118         if (fd == -1)
4119             return NULL;
4120 
4121         return_str = 1;
4122 
4123         Py_BEGIN_ALLOW_THREADS
4124         dirp = fdopendir(fd);
4125         Py_END_ALLOW_THREADS
4126       } else {
4127         PyErr_SetString(PyExc_TypeError,
4128             "listdir: path should be string, bytes, os.PathLike or None, not int");
4129         return NULL;
4130       }
4131     }
4132     else
4133 #endif
4134     {
4135         const char *name;
4136         if (path->narrow) {
4137             name = path->narrow;
4138             /* only return bytes if they specified a bytes-like object */
4139             return_str = !PyObject_CheckBuffer(path->object);
4140         }
4141         else {
4142             name = ".";
4143             return_str = 1;
4144         }
4145 
4146         Py_BEGIN_ALLOW_THREADS
4147         dirp = opendir(name);
4148         Py_END_ALLOW_THREADS
4149     }
4150 
4151     if (dirp == NULL) {
4152         list = path_error(path);
4153 #ifdef HAVE_FDOPENDIR
4154         if (fd != -1) {
4155             Py_BEGIN_ALLOW_THREADS
4156             close(fd);
4157             Py_END_ALLOW_THREADS
4158         }
4159 #endif
4160         goto exit;
4161     }
4162     if ((list = PyList_New(0)) == NULL) {
4163         goto exit;
4164     }
4165     for (;;) {
4166         errno = 0;
4167         Py_BEGIN_ALLOW_THREADS
4168         ep = readdir(dirp);
4169         Py_END_ALLOW_THREADS
4170         if (ep == NULL) {
4171             if (errno == 0) {
4172                 break;
4173             } else {
4174                 Py_DECREF(list);
4175                 list = path_error(path);
4176                 goto exit;
4177             }
4178         }
4179         if (ep->d_name[0] == '.' &&
4180             (NAMLEN(ep) == 1 ||
4181              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4182             continue;
4183         if (return_str)
4184             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4185         else
4186             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4187         if (v == NULL) {
4188             Py_CLEAR(list);
4189             break;
4190         }
4191         if (PyList_Append(list, v) != 0) {
4192             Py_DECREF(v);
4193             Py_CLEAR(list);
4194             break;
4195         }
4196         Py_DECREF(v);
4197     }
4198 
4199 exit:
4200     if (dirp != NULL) {
4201         Py_BEGIN_ALLOW_THREADS
4202 #ifdef HAVE_FDOPENDIR
4203         if (fd > -1)
4204             rewinddir(dirp);
4205 #endif
4206         closedir(dirp);
4207         Py_END_ALLOW_THREADS
4208     }
4209 
4210     return list;
4211 }  /* end of _posix_listdir */
4212 #endif  /* which OS */
4213 
4214 
4215 /*[clinic input]
4216 os.listdir
4217 
4218     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4219 
4220 Return a list containing the names of the files in the directory.
4221 
4222 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4223   the filenames returned will also be bytes; in all other circumstances
4224   the filenames returned will be str.
4225 If path is None, uses the path='.'.
4226 On some platforms, path may also be specified as an open file descriptor;\
4227   the file descriptor must refer to a directory.
4228   If this functionality is unavailable, using it raises NotImplementedError.
4229 
4230 The list is in arbitrary order.  It does not include the special
4231 entries '.' and '..' even if they are present in the directory.
4232 
4233 
4234 [clinic start generated code]*/
4235 
4236 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4237 os_listdir_impl(PyObject *module, path_t *path)
4238 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4239 {
4240     if (PySys_Audit("os.listdir", "O",
4241                     path->object ? path->object : Py_None) < 0) {
4242         return NULL;
4243     }
4244 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4245     return _listdir_windows_no_opendir(path, NULL);
4246 #else
4247     return _posix_listdir(path, NULL);
4248 #endif
4249 }
4250 
4251 #ifdef MS_WINDOWS
4252 /* A helper function for abspath on win32 */
4253 /*[clinic input]
4254 os._getfullpathname
4255 
4256     path: path_t
4257     /
4258 
4259 [clinic start generated code]*/
4260 
4261 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4262 os__getfullpathname_impl(PyObject *module, path_t *path)
4263 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4264 {
4265     wchar_t *abspath;
4266 
4267     /* _Py_abspath() is implemented with GetFullPathNameW() on Windows */
4268     if (_Py_abspath(path->wide, &abspath) < 0) {
4269         return win32_error_object("GetFullPathNameW", path->object);
4270     }
4271     if (abspath == NULL) {
4272         return PyErr_NoMemory();
4273     }
4274 
4275     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4276     PyMem_RawFree(abspath);
4277     if (str == NULL) {
4278         return NULL;
4279     }
4280     if (path->narrow) {
4281         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4282     }
4283     return str;
4284 }
4285 
4286 
4287 /*[clinic input]
4288 os._getfinalpathname
4289 
4290     path: path_t
4291     /
4292 
4293 A helper function for samepath on windows.
4294 [clinic start generated code]*/
4295 
4296 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4297 os__getfinalpathname_impl(PyObject *module, path_t *path)
4298 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4299 {
4300     HANDLE hFile;
4301     wchar_t buf[MAXPATHLEN], *target_path = buf;
4302     int buf_size = Py_ARRAY_LENGTH(buf);
4303     int result_length;
4304     PyObject *result;
4305 
4306     Py_BEGIN_ALLOW_THREADS
4307     hFile = CreateFileW(
4308         path->wide,
4309         0, /* desired access */
4310         0, /* share mode */
4311         NULL, /* security attributes */
4312         OPEN_EXISTING,
4313         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4314         FILE_FLAG_BACKUP_SEMANTICS,
4315         NULL);
4316     Py_END_ALLOW_THREADS
4317 
4318     if (hFile == INVALID_HANDLE_VALUE) {
4319         return win32_error_object("CreateFileW", path->object);
4320     }
4321 
4322     /* We have a good handle to the target, use it to determine the
4323        target path name. */
4324     while (1) {
4325         Py_BEGIN_ALLOW_THREADS
4326         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4327                                                   buf_size, VOLUME_NAME_DOS);
4328         Py_END_ALLOW_THREADS
4329 
4330         if (!result_length) {
4331             result = win32_error_object("GetFinalPathNameByHandleW",
4332                                          path->object);
4333             goto cleanup;
4334         }
4335 
4336         if (result_length < buf_size) {
4337             break;
4338         }
4339 
4340         wchar_t *tmp;
4341         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4342                             result_length * sizeof(*tmp));
4343         if (!tmp) {
4344             result = PyErr_NoMemory();
4345             goto cleanup;
4346         }
4347 
4348         buf_size = result_length;
4349         target_path = tmp;
4350     }
4351 
4352     result = PyUnicode_FromWideChar(target_path, result_length);
4353     if (result && path->narrow) {
4354         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4355     }
4356 
4357 cleanup:
4358     if (target_path != buf) {
4359         PyMem_Free(target_path);
4360     }
4361     CloseHandle(hFile);
4362     return result;
4363 }
4364 
4365 
4366 /*[clinic input]
4367 os._getvolumepathname
4368 
4369     path: path_t
4370 
4371 A helper function for ismount on Win32.
4372 [clinic start generated code]*/
4373 
4374 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4375 os__getvolumepathname_impl(PyObject *module, path_t *path)
4376 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4377 {
4378     PyObject *result;
4379     wchar_t *mountpath=NULL;
4380     size_t buflen;
4381     BOOL ret;
4382 
4383     /* Volume path should be shorter than entire path */
4384     buflen = Py_MAX(path->length, MAX_PATH);
4385 
4386     if (buflen > PY_DWORD_MAX) {
4387         PyErr_SetString(PyExc_OverflowError, "path too long");
4388         return NULL;
4389     }
4390 
4391     mountpath = PyMem_New(wchar_t, buflen);
4392     if (mountpath == NULL)
4393         return PyErr_NoMemory();
4394 
4395     Py_BEGIN_ALLOW_THREADS
4396     ret = GetVolumePathNameW(path->wide, mountpath,
4397                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4398     Py_END_ALLOW_THREADS
4399 
4400     if (!ret) {
4401         result = win32_error_object("_getvolumepathname", path->object);
4402         goto exit;
4403     }
4404     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4405     if (path->narrow)
4406         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4407 
4408 exit:
4409     PyMem_Free(mountpath);
4410     return result;
4411 }
4412 
4413 
4414 /*[clinic input]
4415 os._path_splitroot
4416 
4417     path: path_t
4418 
4419 Removes everything after the root on Win32.
4420 [clinic start generated code]*/
4421 
4422 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4423 os__path_splitroot_impl(PyObject *module, path_t *path)
4424 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4425 {
4426     wchar_t *buffer;
4427     wchar_t *end;
4428     PyObject *result = NULL;
4429     HRESULT ret;
4430 
4431     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4432     if (!buffer) {
4433         return NULL;
4434     }
4435     wcscpy(buffer, path->wide);
4436     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4437         *p = L'\\';
4438     }
4439 
4440     Py_BEGIN_ALLOW_THREADS
4441     ret = PathCchSkipRoot(buffer, &end);
4442     Py_END_ALLOW_THREADS
4443     if (FAILED(ret)) {
4444         result = Py_BuildValue("sO", "", path->object);
4445     } else if (end != buffer) {
4446         size_t rootLen = (size_t)(end - buffer);
4447         result = Py_BuildValue("NN",
4448             PyUnicode_FromWideChar(path->wide, rootLen),
4449             PyUnicode_FromWideChar(path->wide + rootLen, -1)
4450         );
4451     } else {
4452         result = Py_BuildValue("Os", path->object, "");
4453     }
4454     PyMem_Free(buffer);
4455 
4456     return result;
4457 }
4458 
4459 
4460 #endif /* MS_WINDOWS */
4461 
4462 
4463 /*[clinic input]
4464 os.mkdir
4465 
4466     path : path_t
4467 
4468     mode: int = 0o777
4469 
4470     *
4471 
4472     dir_fd : dir_fd(requires='mkdirat') = None
4473 
4474 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4475 
4476 Create a directory.
4477 
4478 If dir_fd is not None, it should be a file descriptor open to a directory,
4479   and path should be relative; path will then be relative to that directory.
4480 dir_fd may not be implemented on your platform.
4481   If it is unavailable, using it will raise a NotImplementedError.
4482 
4483 The mode argument is ignored on Windows.
4484 [clinic start generated code]*/
4485 
4486 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4487 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4488 /*[clinic end generated code: output=a70446903abe821f input=e965f68377e9b1ce]*/
4489 {
4490     int result;
4491 #ifdef HAVE_MKDIRAT
4492     int mkdirat_unavailable = 0;
4493 #endif
4494 
4495     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4496                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4497         return NULL;
4498     }
4499 
4500 #ifdef MS_WINDOWS
4501     Py_BEGIN_ALLOW_THREADS
4502     result = CreateDirectoryW(path->wide, NULL);
4503     Py_END_ALLOW_THREADS
4504 
4505     if (!result)
4506         return path_error(path);
4507 #else
4508     Py_BEGIN_ALLOW_THREADS
4509 #if HAVE_MKDIRAT
4510     if (dir_fd != DEFAULT_DIR_FD) {
4511       if (HAVE_MKDIRAT_RUNTIME) {
4512         result = mkdirat(dir_fd, path->narrow, mode);
4513 
4514       } else {
4515         mkdirat_unavailable = 1;
4516       }
4517     } else
4518 #endif
4519 #if defined(__WATCOMC__) && !defined(__QNX__)
4520         result = mkdir(path->narrow);
4521 #else
4522         result = mkdir(path->narrow, mode);
4523 #endif
4524     Py_END_ALLOW_THREADS
4525 
4526 #if HAVE_MKDIRAT
4527     if (mkdirat_unavailable) {
4528         argument_unavailable_error(NULL, "dir_fd");
4529         return NULL;
4530     }
4531 #endif
4532 
4533     if (result < 0)
4534         return path_error(path);
4535 #endif /* MS_WINDOWS */
4536     Py_RETURN_NONE;
4537 }
4538 
4539 
4540 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4541 #if defined(HAVE_SYS_RESOURCE_H)
4542 #include <sys/resource.h>
4543 #endif
4544 
4545 
4546 #ifdef HAVE_NICE
4547 /*[clinic input]
4548 os.nice
4549 
4550     increment: int
4551     /
4552 
4553 Add increment to the priority of process and return the new priority.
4554 [clinic start generated code]*/
4555 
4556 static PyObject *
os_nice_impl(PyObject * module,int increment)4557 os_nice_impl(PyObject *module, int increment)
4558 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4559 {
4560     int value;
4561 
4562     /* There are two flavours of 'nice': one that returns the new
4563        priority (as required by almost all standards out there) and the
4564        Linux/FreeBSD one, which returns '0' on success and advices
4565        the use of getpriority() to get the new priority.
4566 
4567        If we are of the nice family that returns the new priority, we
4568        need to clear errno before the call, and check if errno is filled
4569        before calling posix_error() on a returnvalue of -1, because the
4570        -1 may be the actual new priority! */
4571 
4572     errno = 0;
4573     value = nice(increment);
4574 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4575     if (value == 0)
4576         value = getpriority(PRIO_PROCESS, 0);
4577 #endif
4578     if (value == -1 && errno != 0)
4579         /* either nice() or getpriority() returned an error */
4580         return posix_error();
4581     return PyLong_FromLong((long) value);
4582 }
4583 #endif /* HAVE_NICE */
4584 
4585 
4586 #ifdef HAVE_GETPRIORITY
4587 /*[clinic input]
4588 os.getpriority
4589 
4590     which: int
4591     who: int
4592 
4593 Return program scheduling priority.
4594 [clinic start generated code]*/
4595 
4596 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4597 os_getpriority_impl(PyObject *module, int which, int who)
4598 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4599 {
4600     int retval;
4601 
4602     errno = 0;
4603     retval = getpriority(which, who);
4604     if (errno != 0)
4605         return posix_error();
4606     return PyLong_FromLong((long)retval);
4607 }
4608 #endif /* HAVE_GETPRIORITY */
4609 
4610 
4611 #ifdef HAVE_SETPRIORITY
4612 /*[clinic input]
4613 os.setpriority
4614 
4615     which: int
4616     who: int
4617     priority: int
4618 
4619 Set program scheduling priority.
4620 [clinic start generated code]*/
4621 
4622 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4623 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4624 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4625 {
4626     int retval;
4627 
4628     retval = setpriority(which, who, priority);
4629     if (retval == -1)
4630         return posix_error();
4631     Py_RETURN_NONE;
4632 }
4633 #endif /* HAVE_SETPRIORITY */
4634 
4635 
4636 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4637 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4638 {
4639     const char *function_name = is_replace ? "replace" : "rename";
4640     int dir_fd_specified;
4641 
4642 #ifdef HAVE_RENAMEAT
4643     int renameat_unavailable = 0;
4644 #endif
4645 
4646 #ifdef MS_WINDOWS
4647     BOOL result;
4648     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4649 #else
4650     int result;
4651 #endif
4652 
4653     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4654                        (dst_dir_fd != DEFAULT_DIR_FD);
4655 #ifndef HAVE_RENAMEAT
4656     if (dir_fd_specified) {
4657         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4658         return NULL;
4659     }
4660 #endif
4661 
4662     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4663                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4664                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4665         return NULL;
4666     }
4667 
4668 #ifdef MS_WINDOWS
4669     Py_BEGIN_ALLOW_THREADS
4670     result = MoveFileExW(src->wide, dst->wide, flags);
4671     Py_END_ALLOW_THREADS
4672 
4673     if (!result)
4674         return path_error2(src, dst);
4675 
4676 #else
4677     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4678         PyErr_Format(PyExc_ValueError,
4679                      "%s: src and dst must be the same type", function_name);
4680         return NULL;
4681     }
4682 
4683     Py_BEGIN_ALLOW_THREADS
4684 #ifdef HAVE_RENAMEAT
4685     if (dir_fd_specified) {
4686         if (HAVE_RENAMEAT_RUNTIME) {
4687             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4688         } else {
4689             renameat_unavailable = 1;
4690         }
4691     } else
4692 #endif
4693     result = rename(src->narrow, dst->narrow);
4694     Py_END_ALLOW_THREADS
4695 
4696 
4697 #ifdef HAVE_RENAMEAT
4698     if (renameat_unavailable) {
4699         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4700         return NULL;
4701     }
4702 #endif
4703 
4704     if (result)
4705         return path_error2(src, dst);
4706 #endif
4707     Py_RETURN_NONE;
4708 }
4709 
4710 
4711 /*[clinic input]
4712 os.rename
4713 
4714     src : path_t
4715     dst : path_t
4716     *
4717     src_dir_fd : dir_fd = None
4718     dst_dir_fd : dir_fd = None
4719 
4720 Rename a file or directory.
4721 
4722 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4723   descriptor open to a directory, and the respective path string (src or dst)
4724   should be relative; the path will then be relative to that directory.
4725 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4726   If they are unavailable, using them will raise a NotImplementedError.
4727 [clinic start generated code]*/
4728 
4729 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4730 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4731                int dst_dir_fd)
4732 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4733 {
4734     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4735 }
4736 
4737 
4738 /*[clinic input]
4739 os.replace = os.rename
4740 
4741 Rename a file or directory, overwriting the destination.
4742 
4743 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4744   descriptor open to a directory, and the respective path string (src or dst)
4745   should be relative; the path will then be relative to that directory.
4746 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4747   If they are unavailable, using them will raise a NotImplementedError.
4748 [clinic start generated code]*/
4749 
4750 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4751 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4752                 int dst_dir_fd)
4753 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4754 {
4755     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4756 }
4757 
4758 
4759 /*[clinic input]
4760 os.rmdir
4761 
4762     path: path_t
4763     *
4764     dir_fd: dir_fd(requires='unlinkat') = None
4765 
4766 Remove a directory.
4767 
4768 If dir_fd is not None, it should be a file descriptor open to a directory,
4769   and path should be relative; path will then be relative to that directory.
4770 dir_fd may not be implemented on your platform.
4771   If it is unavailable, using it will raise a NotImplementedError.
4772 [clinic start generated code]*/
4773 
4774 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4775 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4776 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4777 {
4778     int result;
4779 #ifdef HAVE_UNLINKAT
4780     int unlinkat_unavailable = 0;
4781 #endif
4782 
4783     if (PySys_Audit("os.rmdir", "Oi", path->object,
4784                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4785         return NULL;
4786     }
4787 
4788     Py_BEGIN_ALLOW_THREADS
4789 #ifdef MS_WINDOWS
4790     /* Windows, success=1, UNIX, success=0 */
4791     result = !RemoveDirectoryW(path->wide);
4792 #else
4793 #ifdef HAVE_UNLINKAT
4794     if (dir_fd != DEFAULT_DIR_FD) {
4795       if (HAVE_UNLINKAT_RUNTIME) {
4796         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4797       } else {
4798         unlinkat_unavailable = 1;
4799         result = -1;
4800       }
4801     } else
4802 #endif
4803         result = rmdir(path->narrow);
4804 #endif
4805     Py_END_ALLOW_THREADS
4806 
4807 #ifdef HAVE_UNLINKAT
4808     if (unlinkat_unavailable) {
4809         argument_unavailable_error("rmdir", "dir_fd");
4810         return NULL;
4811     }
4812 #endif
4813 
4814     if (result)
4815         return path_error(path);
4816 
4817     Py_RETURN_NONE;
4818 }
4819 
4820 
4821 #ifdef HAVE_SYSTEM
4822 #ifdef MS_WINDOWS
4823 /*[clinic input]
4824 os.system -> long
4825 
4826     command: Py_UNICODE
4827 
4828 Execute the command in a subshell.
4829 [clinic start generated code]*/
4830 
4831 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4832 os_system_impl(PyObject *module, const Py_UNICODE *command)
4833 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4834 {
4835     long result;
4836 
4837     if (PySys_Audit("os.system", "(u)", command) < 0) {
4838         return -1;
4839     }
4840 
4841     Py_BEGIN_ALLOW_THREADS
4842     _Py_BEGIN_SUPPRESS_IPH
4843     result = _wsystem(command);
4844     _Py_END_SUPPRESS_IPH
4845     Py_END_ALLOW_THREADS
4846     return result;
4847 }
4848 #else /* MS_WINDOWS */
4849 /*[clinic input]
4850 os.system -> long
4851 
4852     command: FSConverter
4853 
4854 Execute the command in a subshell.
4855 [clinic start generated code]*/
4856 
4857 static long
os_system_impl(PyObject * module,PyObject * command)4858 os_system_impl(PyObject *module, PyObject *command)
4859 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4860 {
4861     long result;
4862     const char *bytes = PyBytes_AsString(command);
4863 
4864     if (PySys_Audit("os.system", "(O)", command) < 0) {
4865         return -1;
4866     }
4867 
4868     Py_BEGIN_ALLOW_THREADS
4869     result = system(bytes);
4870     Py_END_ALLOW_THREADS
4871     return result;
4872 }
4873 #endif
4874 #endif /* HAVE_SYSTEM */
4875 
4876 
4877 /*[clinic input]
4878 os.umask
4879 
4880     mask: int
4881     /
4882 
4883 Set the current numeric umask and return the previous umask.
4884 [clinic start generated code]*/
4885 
4886 static PyObject *
os_umask_impl(PyObject * module,int mask)4887 os_umask_impl(PyObject *module, int mask)
4888 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4889 {
4890     int i = (int)umask(mask);
4891     if (i < 0)
4892         return posix_error();
4893     return PyLong_FromLong((long)i);
4894 }
4895 
4896 #ifdef MS_WINDOWS
4897 
4898 /* override the default DeleteFileW behavior so that directory
4899 symlinks can be removed with this function, the same as with
4900 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)4901 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
4902 {
4903     WIN32_FILE_ATTRIBUTE_DATA info;
4904     WIN32_FIND_DATAW find_data;
4905     HANDLE find_data_handle;
4906     int is_directory = 0;
4907     int is_link = 0;
4908 
4909     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
4910         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
4911 
4912         /* Get WIN32_FIND_DATA structure for the path to determine if
4913            it is a symlink */
4914         if(is_directory &&
4915            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
4916             find_data_handle = FindFirstFileW(lpFileName, &find_data);
4917 
4918             if(find_data_handle != INVALID_HANDLE_VALUE) {
4919                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
4920                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
4921                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
4922                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
4923                 FindClose(find_data_handle);
4924             }
4925         }
4926     }
4927 
4928     if (is_directory && is_link)
4929         return RemoveDirectoryW(lpFileName);
4930 
4931     return DeleteFileW(lpFileName);
4932 }
4933 #endif /* MS_WINDOWS */
4934 
4935 
4936 /*[clinic input]
4937 os.unlink
4938 
4939     path: path_t
4940     *
4941     dir_fd: dir_fd(requires='unlinkat')=None
4942 
4943 Remove a file (same as remove()).
4944 
4945 If dir_fd is not None, it should be a file descriptor open to a directory,
4946   and path should be relative; path will then be relative to that directory.
4947 dir_fd may not be implemented on your platform.
4948   If it is unavailable, using it will raise a NotImplementedError.
4949 
4950 [clinic start generated code]*/
4951 
4952 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)4953 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
4954 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
4955 {
4956     int result;
4957 #ifdef HAVE_UNLINKAT
4958     int unlinkat_unavailable = 0;
4959 #endif
4960 
4961     if (PySys_Audit("os.remove", "Oi", path->object,
4962                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4963         return NULL;
4964     }
4965 
4966     Py_BEGIN_ALLOW_THREADS
4967     _Py_BEGIN_SUPPRESS_IPH
4968 #ifdef MS_WINDOWS
4969     /* Windows, success=1, UNIX, success=0 */
4970     result = !Py_DeleteFileW(path->wide);
4971 #else
4972 #ifdef HAVE_UNLINKAT
4973     if (dir_fd != DEFAULT_DIR_FD) {
4974       if (HAVE_UNLINKAT_RUNTIME) {
4975 
4976         result = unlinkat(dir_fd, path->narrow, 0);
4977       } else {
4978         unlinkat_unavailable = 1;
4979       }
4980     } else
4981 #endif /* HAVE_UNLINKAT */
4982         result = unlink(path->narrow);
4983 #endif
4984     _Py_END_SUPPRESS_IPH
4985     Py_END_ALLOW_THREADS
4986 
4987 #ifdef HAVE_UNLINKAT
4988     if (unlinkat_unavailable) {
4989         argument_unavailable_error(NULL, "dir_fd");
4990         return NULL;
4991     }
4992 #endif
4993 
4994     if (result)
4995         return path_error(path);
4996 
4997     Py_RETURN_NONE;
4998 }
4999 
5000 
5001 /*[clinic input]
5002 os.remove = os.unlink
5003 
5004 Remove a file (same as unlink()).
5005 
5006 If dir_fd is not None, it should be a file descriptor open to a directory,
5007   and path should be relative; path will then be relative to that directory.
5008 dir_fd may not be implemented on your platform.
5009   If it is unavailable, using it will raise a NotImplementedError.
5010 [clinic start generated code]*/
5011 
5012 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5013 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5014 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5015 {
5016     return os_unlink_impl(module, path, dir_fd);
5017 }
5018 
5019 
5020 static PyStructSequence_Field uname_result_fields[] = {
5021     {"sysname",    "operating system name"},
5022     {"nodename",   "name of machine on network (implementation-defined)"},
5023     {"release",    "operating system release"},
5024     {"version",    "operating system version"},
5025     {"machine",    "hardware identifier"},
5026     {NULL}
5027 };
5028 
5029 PyDoc_STRVAR(uname_result__doc__,
5030 "uname_result: Result from os.uname().\n\n\
5031 This object may be accessed either as a tuple of\n\
5032   (sysname, nodename, release, version, machine),\n\
5033 or via the attributes sysname, nodename, release, version, and machine.\n\
5034 \n\
5035 See os.uname for more information.");
5036 
5037 static PyStructSequence_Desc uname_result_desc = {
5038     MODNAME ".uname_result", /* name */
5039     uname_result__doc__, /* doc */
5040     uname_result_fields,
5041     5
5042 };
5043 
5044 #ifdef HAVE_UNAME
5045 /*[clinic input]
5046 os.uname
5047 
5048 Return an object identifying the current operating system.
5049 
5050 The object behaves like a named tuple with the following fields:
5051   (sysname, nodename, release, version, machine)
5052 
5053 [clinic start generated code]*/
5054 
5055 static PyObject *
os_uname_impl(PyObject * module)5056 os_uname_impl(PyObject *module)
5057 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5058 {
5059     struct utsname u;
5060     int res;
5061     PyObject *value;
5062 
5063     Py_BEGIN_ALLOW_THREADS
5064     res = uname(&u);
5065     Py_END_ALLOW_THREADS
5066     if (res < 0)
5067         return posix_error();
5068 
5069     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5070     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5071     if (value == NULL)
5072         return NULL;
5073 
5074 #define SET(i, field) \
5075     { \
5076     PyObject *o = PyUnicode_DecodeFSDefault(field); \
5077     if (!o) { \
5078         Py_DECREF(value); \
5079         return NULL; \
5080     } \
5081     PyStructSequence_SET_ITEM(value, i, o); \
5082     } \
5083 
5084     SET(0, u.sysname);
5085     SET(1, u.nodename);
5086     SET(2, u.release);
5087     SET(3, u.version);
5088     SET(4, u.machine);
5089 
5090 #undef SET
5091 
5092     return value;
5093 }
5094 #endif /* HAVE_UNAME */
5095 
5096 
5097 
5098 typedef struct {
5099     int    now;
5100     time_t atime_s;
5101     long   atime_ns;
5102     time_t mtime_s;
5103     long   mtime_ns;
5104 } utime_t;
5105 
5106 /*
5107  * these macros assume that "ut" is a pointer to a utime_t
5108  * they also intentionally leak the declaration of a pointer named "time"
5109  */
5110 #define UTIME_TO_TIMESPEC \
5111     struct timespec ts[2]; \
5112     struct timespec *time; \
5113     if (ut->now) \
5114         time = NULL; \
5115     else { \
5116         ts[0].tv_sec = ut->atime_s; \
5117         ts[0].tv_nsec = ut->atime_ns; \
5118         ts[1].tv_sec = ut->mtime_s; \
5119         ts[1].tv_nsec = ut->mtime_ns; \
5120         time = ts; \
5121     } \
5122 
5123 #define UTIME_TO_TIMEVAL \
5124     struct timeval tv[2]; \
5125     struct timeval *time; \
5126     if (ut->now) \
5127         time = NULL; \
5128     else { \
5129         tv[0].tv_sec = ut->atime_s; \
5130         tv[0].tv_usec = ut->atime_ns / 1000; \
5131         tv[1].tv_sec = ut->mtime_s; \
5132         tv[1].tv_usec = ut->mtime_ns / 1000; \
5133         time = tv; \
5134     } \
5135 
5136 #define UTIME_TO_UTIMBUF \
5137     struct utimbuf u; \
5138     struct utimbuf *time; \
5139     if (ut->now) \
5140         time = NULL; \
5141     else { \
5142         u.actime = ut->atime_s; \
5143         u.modtime = ut->mtime_s; \
5144         time = &u; \
5145     }
5146 
5147 #define UTIME_TO_TIME_T \
5148     time_t timet[2]; \
5149     time_t *time; \
5150     if (ut->now) \
5151         time = NULL; \
5152     else { \
5153         timet[0] = ut->atime_s; \
5154         timet[1] = ut->mtime_s; \
5155         time = timet; \
5156     } \
5157 
5158 
5159 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5160 
5161 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5162 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5163 {
5164 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5165     if (HAVE_UTIMENSAT_RUNTIME) {
5166         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5167         UTIME_TO_TIMESPEC;
5168         return utimensat(dir_fd, path, time, flags);
5169     }  else {
5170         errno = ENOSYS;
5171         return -1;
5172     }
5173 #elif defined(HAVE_UTIMENSAT)
5174     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5175     UTIME_TO_TIMESPEC;
5176     return utimensat(dir_fd, path, time, flags);
5177 #elif defined(HAVE_FUTIMESAT)
5178     UTIME_TO_TIMEVAL;
5179     /*
5180      * follow_symlinks will never be false here;
5181      * we only allow !follow_symlinks and dir_fd together
5182      * if we have utimensat()
5183      */
5184     assert(follow_symlinks);
5185     return futimesat(dir_fd, path, time);
5186 #endif
5187 }
5188 
5189     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5190 #else
5191     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5192 #endif
5193 
5194 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5195 
5196 static int
utime_fd(utime_t * ut,int fd)5197 utime_fd(utime_t *ut, int fd)
5198 {
5199 #ifdef HAVE_FUTIMENS
5200 
5201     if (HAVE_FUTIMENS_RUNTIME) {
5202 
5203     UTIME_TO_TIMESPEC;
5204     return futimens(fd, time);
5205 
5206     } else
5207 #ifndef HAVE_FUTIMES
5208     {
5209         /* Not sure if this can happen */
5210         PyErr_SetString(
5211             PyExc_RuntimeError,
5212             "neither futimens nor futimes are supported"
5213             " on this system");
5214         return -1;
5215     }
5216 #endif
5217 
5218 #endif
5219 #ifdef HAVE_FUTIMES
5220     {
5221     UTIME_TO_TIMEVAL;
5222     return futimes(fd, time);
5223     }
5224 #endif
5225 }
5226 
5227     #define PATH_UTIME_HAVE_FD 1
5228 #else
5229     #define PATH_UTIME_HAVE_FD 0
5230 #endif
5231 
5232 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5233 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5234 #endif
5235 
5236 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5237 
5238 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5239 utime_nofollow_symlinks(utime_t *ut, const char *path)
5240 {
5241 #ifdef HAVE_UTIMENSAT
5242     if (HAVE_UTIMENSAT_RUNTIME) {
5243         UTIME_TO_TIMESPEC;
5244         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5245     } else
5246 #ifndef HAVE_LUTIMES
5247     {
5248         /* Not sure if this can happen */
5249         PyErr_SetString(
5250             PyExc_RuntimeError,
5251             "neither utimensat nor lutimes are supported"
5252             " on this system");
5253         return -1;
5254     }
5255 #endif
5256 #endif
5257 
5258 #ifdef HAVE_LUTIMES
5259     {
5260     UTIME_TO_TIMEVAL;
5261     return lutimes(path, time);
5262     }
5263 #endif
5264 }
5265 
5266 #endif
5267 
5268 #ifndef MS_WINDOWS
5269 
5270 static int
utime_default(utime_t * ut,const char * path)5271 utime_default(utime_t *ut, const char *path)
5272 {
5273 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5274     if (HAVE_UTIMENSAT_RUNTIME) {
5275         UTIME_TO_TIMESPEC;
5276         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5277     } else {
5278         UTIME_TO_TIMEVAL;
5279         return utimes(path, time);
5280     }
5281 #elif defined(HAVE_UTIMENSAT)
5282     UTIME_TO_TIMESPEC;
5283     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5284 #elif defined(HAVE_UTIMES)
5285     UTIME_TO_TIMEVAL;
5286     return utimes(path, time);
5287 #elif defined(HAVE_UTIME_H)
5288     UTIME_TO_UTIMBUF;
5289     return utime(path, time);
5290 #else
5291     UTIME_TO_TIME_T;
5292     return utime(path, time);
5293 #endif
5294 }
5295 
5296 #endif
5297 
5298 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5299 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5300 {
5301     int result = 0;
5302     PyObject *divmod;
5303     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5304     if (!divmod)
5305         goto exit;
5306     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5307         PyErr_Format(PyExc_TypeError,
5308                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5309                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5310         goto exit;
5311     }
5312     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5313     if ((*s == -1) && PyErr_Occurred())
5314         goto exit;
5315     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5316     if ((*ns == -1) && PyErr_Occurred())
5317         goto exit;
5318 
5319     result = 1;
5320 exit:
5321     Py_XDECREF(divmod);
5322     return result;
5323 }
5324 
5325 
5326 /*[clinic input]
5327 os.utime
5328 
5329     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5330     times: object = None
5331     *
5332     ns: object = NULL
5333     dir_fd: dir_fd(requires='futimensat') = None
5334     follow_symlinks: bool=True
5335 
5336 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5337 
5338 Set the access and modified time of path.
5339 
5340 path may always be specified as a string.
5341 On some platforms, path may also be specified as an open file descriptor.
5342   If this functionality is unavailable, using it raises an exception.
5343 
5344 If times is not None, it must be a tuple (atime, mtime);
5345     atime and mtime should be expressed as float seconds since the epoch.
5346 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5347     atime_ns and mtime_ns should be expressed as integer nanoseconds
5348     since the epoch.
5349 If times is None and ns is unspecified, utime uses the current time.
5350 Specifying tuples for both times and ns is an error.
5351 
5352 If dir_fd is not None, it should be a file descriptor open to a directory,
5353   and path should be relative; path will then be relative to that directory.
5354 If follow_symlinks is False, and the last element of the path is a symbolic
5355   link, utime will modify the symbolic link itself instead of the file the
5356   link points to.
5357 It is an error to use dir_fd or follow_symlinks when specifying path
5358   as an open file descriptor.
5359 dir_fd and follow_symlinks may not be available on your platform.
5360   If they are unavailable, using them will raise a NotImplementedError.
5361 
5362 [clinic start generated code]*/
5363 
5364 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5365 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5366               int dir_fd, int follow_symlinks)
5367 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5368 {
5369 #ifdef MS_WINDOWS
5370     HANDLE hFile;
5371     FILETIME atime, mtime;
5372 #else
5373     int result;
5374 #endif
5375 
5376     utime_t utime;
5377 
5378     memset(&utime, 0, sizeof(utime_t));
5379 
5380     if (times != Py_None && ns) {
5381         PyErr_SetString(PyExc_ValueError,
5382                      "utime: you may specify either 'times'"
5383                      " or 'ns' but not both");
5384         return NULL;
5385     }
5386 
5387     if (times != Py_None) {
5388         time_t a_sec, m_sec;
5389         long a_nsec, m_nsec;
5390         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5391             PyErr_SetString(PyExc_TypeError,
5392                          "utime: 'times' must be either"
5393                          " a tuple of two ints or None");
5394             return NULL;
5395         }
5396         utime.now = 0;
5397         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5398                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5399             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5400                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5401             return NULL;
5402         }
5403         utime.atime_s = a_sec;
5404         utime.atime_ns = a_nsec;
5405         utime.mtime_s = m_sec;
5406         utime.mtime_ns = m_nsec;
5407     }
5408     else if (ns) {
5409         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5410             PyErr_SetString(PyExc_TypeError,
5411                          "utime: 'ns' must be a tuple of two ints");
5412             return NULL;
5413         }
5414         utime.now = 0;
5415         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5416                                       &utime.atime_s, &utime.atime_ns) ||
5417             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5418                                        &utime.mtime_s, &utime.mtime_ns)) {
5419             return NULL;
5420         }
5421     }
5422     else {
5423         /* times and ns are both None/unspecified. use "now". */
5424         utime.now = 1;
5425     }
5426 
5427 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5428     if (follow_symlinks_specified("utime", follow_symlinks))
5429         return NULL;
5430 #endif
5431 
5432     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5433         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5434         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5435         return NULL;
5436 
5437 #if !defined(HAVE_UTIMENSAT)
5438     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5439         PyErr_SetString(PyExc_ValueError,
5440                      "utime: cannot use dir_fd and follow_symlinks "
5441                      "together on this platform");
5442         return NULL;
5443     }
5444 #endif
5445 
5446     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5447                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5448         return NULL;
5449     }
5450 
5451 #ifdef MS_WINDOWS
5452     Py_BEGIN_ALLOW_THREADS
5453     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5454                         NULL, OPEN_EXISTING,
5455                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5456     Py_END_ALLOW_THREADS
5457     if (hFile == INVALID_HANDLE_VALUE) {
5458         path_error(path);
5459         return NULL;
5460     }
5461 
5462     if (utime.now) {
5463         GetSystemTimeAsFileTime(&mtime);
5464         atime = mtime;
5465     }
5466     else {
5467         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5468         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5469     }
5470     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5471         /* Avoid putting the file name into the error here,
5472            as that may confuse the user into believing that
5473            something is wrong with the file, when it also
5474            could be the time stamp that gives a problem. */
5475         PyErr_SetFromWindowsErr(0);
5476         CloseHandle(hFile);
5477         return NULL;
5478     }
5479     CloseHandle(hFile);
5480 #else /* MS_WINDOWS */
5481     Py_BEGIN_ALLOW_THREADS
5482 
5483 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5484     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5485         result = utime_nofollow_symlinks(&utime, path->narrow);
5486     else
5487 #endif
5488 
5489 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5490     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5491         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5492 
5493     } else
5494 #endif
5495 
5496 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5497     if (path->fd != -1)
5498         result = utime_fd(&utime, path->fd);
5499     else
5500 #endif
5501 
5502     result = utime_default(&utime, path->narrow);
5503 
5504     Py_END_ALLOW_THREADS
5505 
5506 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5507     /* See utime_dir_fd implementation */
5508     if (result == -1 && errno == ENOSYS) {
5509         argument_unavailable_error(NULL, "dir_fd");
5510         return NULL;
5511     }
5512 #endif
5513 
5514     if (result < 0) {
5515         /* see previous comment about not putting filename in error here */
5516         posix_error();
5517         return NULL;
5518     }
5519 
5520 #endif /* MS_WINDOWS */
5521 
5522     Py_RETURN_NONE;
5523 }
5524 
5525 /* Process operations */
5526 
5527 
5528 /*[clinic input]
5529 os._exit
5530 
5531     status: int
5532 
5533 Exit to the system with specified status, without normal exit processing.
5534 [clinic start generated code]*/
5535 
5536 static PyObject *
os__exit_impl(PyObject * module,int status)5537 os__exit_impl(PyObject *module, int status)
5538 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5539 {
5540     _exit(status);
5541     return NULL; /* Make gcc -Wall happy */
5542 }
5543 
5544 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5545 #define EXECV_CHAR wchar_t
5546 #else
5547 #define EXECV_CHAR char
5548 #endif
5549 
5550 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5551 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5552 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5553 {
5554     Py_ssize_t i;
5555     for (i = 0; i < count; i++)
5556         PyMem_Free(array[i]);
5557     PyMem_Free(array);
5558 }
5559 
5560 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5561 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5562 {
5563     Py_ssize_t size;
5564     PyObject *ub;
5565     int result = 0;
5566 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5567     if (!PyUnicode_FSDecoder(o, &ub))
5568         return 0;
5569     *out = PyUnicode_AsWideCharString(ub, &size);
5570     if (*out)
5571         result = 1;
5572 #else
5573     if (!PyUnicode_FSConverter(o, &ub))
5574         return 0;
5575     size = PyBytes_GET_SIZE(ub);
5576     *out = PyMem_Malloc(size + 1);
5577     if (*out) {
5578         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5579         result = 1;
5580     } else
5581         PyErr_NoMemory();
5582 #endif
5583     Py_DECREF(ub);
5584     return result;
5585 }
5586 #endif
5587 
5588 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5589 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5590 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5591 {
5592     Py_ssize_t i, pos, envc;
5593     PyObject *keys=NULL, *vals=NULL;
5594     PyObject *key, *val, *key2, *val2, *keyval;
5595     EXECV_CHAR **envlist;
5596 
5597     i = PyMapping_Size(env);
5598     if (i < 0)
5599         return NULL;
5600     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5601     if (envlist == NULL) {
5602         PyErr_NoMemory();
5603         return NULL;
5604     }
5605     envc = 0;
5606     keys = PyMapping_Keys(env);
5607     if (!keys)
5608         goto error;
5609     vals = PyMapping_Values(env);
5610     if (!vals)
5611         goto error;
5612     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5613         PyErr_Format(PyExc_TypeError,
5614                      "env.keys() or env.values() is not a list");
5615         goto error;
5616     }
5617 
5618     for (pos = 0; pos < i; pos++) {
5619         key = PyList_GetItem(keys, pos);
5620         val = PyList_GetItem(vals, pos);
5621         if (!key || !val)
5622             goto error;
5623 
5624 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5625         if (!PyUnicode_FSDecoder(key, &key2))
5626             goto error;
5627         if (!PyUnicode_FSDecoder(val, &val2)) {
5628             Py_DECREF(key2);
5629             goto error;
5630         }
5631         /* Search from index 1 because on Windows starting '=' is allowed for
5632            defining hidden environment variables. */
5633         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5634             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5635         {
5636             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5637             Py_DECREF(key2);
5638             Py_DECREF(val2);
5639             goto error;
5640         }
5641         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5642 #else
5643         if (!PyUnicode_FSConverter(key, &key2))
5644             goto error;
5645         if (!PyUnicode_FSConverter(val, &val2)) {
5646             Py_DECREF(key2);
5647             goto error;
5648         }
5649         if (PyBytes_GET_SIZE(key2) == 0 ||
5650             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5651         {
5652             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5653             Py_DECREF(key2);
5654             Py_DECREF(val2);
5655             goto error;
5656         }
5657         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5658                                              PyBytes_AS_STRING(val2));
5659 #endif
5660         Py_DECREF(key2);
5661         Py_DECREF(val2);
5662         if (!keyval)
5663             goto error;
5664 
5665         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5666             Py_DECREF(keyval);
5667             goto error;
5668         }
5669 
5670         Py_DECREF(keyval);
5671     }
5672     Py_DECREF(vals);
5673     Py_DECREF(keys);
5674 
5675     envlist[envc] = 0;
5676     *envc_ptr = envc;
5677     return envlist;
5678 
5679 error:
5680     Py_XDECREF(keys);
5681     Py_XDECREF(vals);
5682     free_string_array(envlist, envc);
5683     return NULL;
5684 }
5685 
5686 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5687 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5688 {
5689     int i;
5690     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5691     if (argvlist == NULL) {
5692         PyErr_NoMemory();
5693         return NULL;
5694     }
5695     for (i = 0; i < *argc; i++) {
5696         PyObject* item = PySequence_ITEM(argv, i);
5697         if (item == NULL)
5698             goto fail;
5699         if (!fsconvert_strdup(item, &argvlist[i])) {
5700             Py_DECREF(item);
5701             goto fail;
5702         }
5703         Py_DECREF(item);
5704     }
5705     argvlist[*argc] = NULL;
5706     return argvlist;
5707 fail:
5708     *argc = i;
5709     free_string_array(argvlist, *argc);
5710     return NULL;
5711 }
5712 
5713 #endif
5714 
5715 
5716 #ifdef HAVE_EXECV
5717 /*[clinic input]
5718 os.execv
5719 
5720     path: path_t
5721         Path of executable file.
5722     argv: object
5723         Tuple or list of strings.
5724     /
5725 
5726 Execute an executable path with arguments, replacing current process.
5727 [clinic start generated code]*/
5728 
5729 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5730 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5731 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5732 {
5733     EXECV_CHAR **argvlist;
5734     Py_ssize_t argc;
5735 
5736     /* execv has two arguments: (path, argv), where
5737        argv is a list or tuple of strings. */
5738 
5739     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5740         PyErr_SetString(PyExc_TypeError,
5741                         "execv() arg 2 must be a tuple or list");
5742         return NULL;
5743     }
5744     argc = PySequence_Size(argv);
5745     if (argc < 1) {
5746         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5747         return NULL;
5748     }
5749 
5750     argvlist = parse_arglist(argv, &argc);
5751     if (argvlist == NULL) {
5752         return NULL;
5753     }
5754     if (!argvlist[0][0]) {
5755         PyErr_SetString(PyExc_ValueError,
5756             "execv() arg 2 first element cannot be empty");
5757         free_string_array(argvlist, argc);
5758         return NULL;
5759     }
5760 
5761     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5762         free_string_array(argvlist, argc);
5763         return NULL;
5764     }
5765 
5766     _Py_BEGIN_SUPPRESS_IPH
5767 #ifdef HAVE_WEXECV
5768     _wexecv(path->wide, argvlist);
5769 #else
5770     execv(path->narrow, argvlist);
5771 #endif
5772     _Py_END_SUPPRESS_IPH
5773 
5774     /* If we get here it's definitely an error */
5775 
5776     free_string_array(argvlist, argc);
5777     return posix_error();
5778 }
5779 
5780 
5781 /*[clinic input]
5782 os.execve
5783 
5784     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5785         Path of executable file.
5786     argv: object
5787         Tuple or list of strings.
5788     env: object
5789         Dictionary of strings mapping to strings.
5790 
5791 Execute an executable path with arguments, replacing current process.
5792 [clinic start generated code]*/
5793 
5794 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5795 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5796 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5797 {
5798     EXECV_CHAR **argvlist = NULL;
5799     EXECV_CHAR **envlist;
5800     Py_ssize_t argc, envc;
5801 
5802     /* execve has three arguments: (path, argv, env), where
5803        argv is a list or tuple of strings and env is a dictionary
5804        like posix.environ. */
5805 
5806     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5807         PyErr_SetString(PyExc_TypeError,
5808                         "execve: argv must be a tuple or list");
5809         goto fail_0;
5810     }
5811     argc = PySequence_Size(argv);
5812     if (argc < 1) {
5813         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5814         return NULL;
5815     }
5816 
5817     if (!PyMapping_Check(env)) {
5818         PyErr_SetString(PyExc_TypeError,
5819                         "execve: environment must be a mapping object");
5820         goto fail_0;
5821     }
5822 
5823     argvlist = parse_arglist(argv, &argc);
5824     if (argvlist == NULL) {
5825         goto fail_0;
5826     }
5827     if (!argvlist[0][0]) {
5828         PyErr_SetString(PyExc_ValueError,
5829             "execve: argv first element cannot be empty");
5830         goto fail_0;
5831     }
5832 
5833     envlist = parse_envlist(env, &envc);
5834     if (envlist == NULL)
5835         goto fail_0;
5836 
5837     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5838         goto fail_1;
5839     }
5840 
5841     _Py_BEGIN_SUPPRESS_IPH
5842 #ifdef HAVE_FEXECVE
5843     if (path->fd > -1)
5844         fexecve(path->fd, argvlist, envlist);
5845     else
5846 #endif
5847 #ifdef HAVE_WEXECV
5848         _wexecve(path->wide, argvlist, envlist);
5849 #else
5850         execve(path->narrow, argvlist, envlist);
5851 #endif
5852     _Py_END_SUPPRESS_IPH
5853 
5854     /* If we get here it's definitely an error */
5855 
5856     posix_path_error(path);
5857   fail_1:
5858     free_string_array(envlist, envc);
5859   fail_0:
5860     if (argvlist)
5861         free_string_array(argvlist, argc);
5862     return NULL;
5863 }
5864 
5865 #endif /* HAVE_EXECV */
5866 
5867 #ifdef HAVE_POSIX_SPAWN
5868 
5869 enum posix_spawn_file_actions_identifier {
5870     POSIX_SPAWN_OPEN,
5871     POSIX_SPAWN_CLOSE,
5872     POSIX_SPAWN_DUP2
5873 };
5874 
5875 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5876 static int
5877 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5878 #endif
5879 
5880 static int
parse_posix_spawn_flags(PyObject * module,const char * func_name,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler,posix_spawnattr_t * attrp)5881 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5882                         int resetids, int setsid, PyObject *setsigmask,
5883                         PyObject *setsigdef, PyObject *scheduler,
5884                         posix_spawnattr_t *attrp)
5885 {
5886     long all_flags = 0;
5887 
5888     errno = posix_spawnattr_init(attrp);
5889     if (errno) {
5890         posix_error();
5891         return -1;
5892     }
5893 
5894     if (setpgroup) {
5895         pid_t pgid = PyLong_AsPid(setpgroup);
5896         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5897             goto fail;
5898         }
5899         errno = posix_spawnattr_setpgroup(attrp, pgid);
5900         if (errno) {
5901             posix_error();
5902             goto fail;
5903         }
5904         all_flags |= POSIX_SPAWN_SETPGROUP;
5905     }
5906 
5907     if (resetids) {
5908         all_flags |= POSIX_SPAWN_RESETIDS;
5909     }
5910 
5911     if (setsid) {
5912 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5913         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
5914 #endif
5915 #ifdef POSIX_SPAWN_SETSID
5916         all_flags |= POSIX_SPAWN_SETSID;
5917 #elif defined(POSIX_SPAWN_SETSID_NP)
5918         all_flags |= POSIX_SPAWN_SETSID_NP;
5919 #else
5920         argument_unavailable_error(func_name, "setsid");
5921         return -1;
5922 #endif
5923 
5924 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
5925         } else {
5926             argument_unavailable_error(func_name, "setsid");
5927             return -1;
5928         }
5929 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
5930 
5931     }
5932 
5933 #ifdef HAVE_SIGSET_T
5934    if (setsigmask) {
5935         sigset_t set;
5936         if (!_Py_Sigset_Converter(setsigmask, &set)) {
5937             goto fail;
5938         }
5939         errno = posix_spawnattr_setsigmask(attrp, &set);
5940         if (errno) {
5941             posix_error();
5942             goto fail;
5943         }
5944         all_flags |= POSIX_SPAWN_SETSIGMASK;
5945     }
5946 
5947     if (setsigdef) {
5948         sigset_t set;
5949         if (!_Py_Sigset_Converter(setsigdef, &set)) {
5950             goto fail;
5951         }
5952         errno = posix_spawnattr_setsigdefault(attrp, &set);
5953         if (errno) {
5954             posix_error();
5955             goto fail;
5956         }
5957         all_flags |= POSIX_SPAWN_SETSIGDEF;
5958     }
5959 #else
5960     if (setsigmask || setsigdef) {
5961         PyErr_SetString(PyExc_NotImplementedError,
5962                         "sigset is not supported on this platform");
5963         goto fail;
5964     }
5965 #endif
5966 
5967     if (scheduler) {
5968 #ifdef POSIX_SPAWN_SETSCHEDULER
5969         PyObject *py_schedpolicy;
5970         PyObject *schedparam_obj;
5971         struct sched_param schedparam;
5972 
5973         if (!PyArg_ParseTuple(scheduler, "OO"
5974                         ";A scheduler tuple must have two elements",
5975                         &py_schedpolicy, &schedparam_obj)) {
5976             goto fail;
5977         }
5978         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
5979             goto fail;
5980         }
5981         if (py_schedpolicy != Py_None) {
5982             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
5983 
5984             if (schedpolicy == -1 && PyErr_Occurred()) {
5985                 goto fail;
5986             }
5987             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
5988             if (errno) {
5989                 posix_error();
5990                 goto fail;
5991             }
5992             all_flags |= POSIX_SPAWN_SETSCHEDULER;
5993         }
5994         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
5995         if (errno) {
5996             posix_error();
5997             goto fail;
5998         }
5999         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6000 #else
6001         PyErr_SetString(PyExc_NotImplementedError,
6002                 "The scheduler option is not supported in this system.");
6003         goto fail;
6004 #endif
6005     }
6006 
6007     errno = posix_spawnattr_setflags(attrp, all_flags);
6008     if (errno) {
6009         posix_error();
6010         goto fail;
6011     }
6012 
6013     return 0;
6014 
6015 fail:
6016     (void)posix_spawnattr_destroy(attrp);
6017     return -1;
6018 }
6019 
6020 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6021 parse_file_actions(PyObject *file_actions,
6022                    posix_spawn_file_actions_t *file_actionsp,
6023                    PyObject *temp_buffer)
6024 {
6025     PyObject *seq;
6026     PyObject *file_action = NULL;
6027     PyObject *tag_obj;
6028 
6029     seq = PySequence_Fast(file_actions,
6030                           "file_actions must be a sequence or None");
6031     if (seq == NULL) {
6032         return -1;
6033     }
6034 
6035     errno = posix_spawn_file_actions_init(file_actionsp);
6036     if (errno) {
6037         posix_error();
6038         Py_DECREF(seq);
6039         return -1;
6040     }
6041 
6042     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6043         file_action = PySequence_Fast_GET_ITEM(seq, i);
6044         Py_INCREF(file_action);
6045         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6046             PyErr_SetString(PyExc_TypeError,
6047                 "Each file_actions element must be a non-empty tuple");
6048             goto fail;
6049         }
6050         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6051         if (tag == -1 && PyErr_Occurred()) {
6052             goto fail;
6053         }
6054 
6055         /* Populate the file_actions object */
6056         switch (tag) {
6057             case POSIX_SPAWN_OPEN: {
6058                 int fd, oflag;
6059                 PyObject *path;
6060                 unsigned long mode;
6061                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6062                         ";A open file_action tuple must have 5 elements",
6063                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
6064                         &oflag, &mode))
6065                 {
6066                     goto fail;
6067                 }
6068                 if (PyList_Append(temp_buffer, path)) {
6069                     Py_DECREF(path);
6070                     goto fail;
6071                 }
6072                 errno = posix_spawn_file_actions_addopen(file_actionsp,
6073                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6074                 Py_DECREF(path);
6075                 if (errno) {
6076                     posix_error();
6077                     goto fail;
6078                 }
6079                 break;
6080             }
6081             case POSIX_SPAWN_CLOSE: {
6082                 int fd;
6083                 if (!PyArg_ParseTuple(file_action, "Oi"
6084                         ";A close file_action tuple must have 2 elements",
6085                         &tag_obj, &fd))
6086                 {
6087                     goto fail;
6088                 }
6089                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6090                 if (errno) {
6091                     posix_error();
6092                     goto fail;
6093                 }
6094                 break;
6095             }
6096             case POSIX_SPAWN_DUP2: {
6097                 int fd1, fd2;
6098                 if (!PyArg_ParseTuple(file_action, "Oii"
6099                         ";A dup2 file_action tuple must have 3 elements",
6100                         &tag_obj, &fd1, &fd2))
6101                 {
6102                     goto fail;
6103                 }
6104                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6105                                                          fd1, fd2);
6106                 if (errno) {
6107                     posix_error();
6108                     goto fail;
6109                 }
6110                 break;
6111             }
6112             default: {
6113                 PyErr_SetString(PyExc_TypeError,
6114                                 "Unknown file_actions identifier");
6115                 goto fail;
6116             }
6117         }
6118         Py_DECREF(file_action);
6119     }
6120 
6121     Py_DECREF(seq);
6122     return 0;
6123 
6124 fail:
6125     Py_DECREF(seq);
6126     Py_DECREF(file_action);
6127     (void)posix_spawn_file_actions_destroy(file_actionsp);
6128     return -1;
6129 }
6130 
6131 
6132 static PyObject *
py_posix_spawn(int use_posix_spawnp,PyObject * module,path_t * path,PyObject * argv,PyObject * env,PyObject * file_actions,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler)6133 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6134                PyObject *env, PyObject *file_actions,
6135                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6136                PyObject *setsigdef, PyObject *scheduler)
6137 {
6138     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6139     EXECV_CHAR **argvlist = NULL;
6140     EXECV_CHAR **envlist = NULL;
6141     posix_spawn_file_actions_t file_actions_buf;
6142     posix_spawn_file_actions_t *file_actionsp = NULL;
6143     posix_spawnattr_t attr;
6144     posix_spawnattr_t *attrp = NULL;
6145     Py_ssize_t argc, envc;
6146     PyObject *result = NULL;
6147     PyObject *temp_buffer = NULL;
6148     pid_t pid;
6149     int err_code;
6150 
6151     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6152        argv is a list or tuple of strings and env is a dictionary
6153        like posix.environ. */
6154 
6155     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6156         PyErr_Format(PyExc_TypeError,
6157                      "%s: argv must be a tuple or list", func_name);
6158         goto exit;
6159     }
6160     argc = PySequence_Size(argv);
6161     if (argc < 1) {
6162         PyErr_Format(PyExc_ValueError,
6163                      "%s: argv must not be empty", func_name);
6164         return NULL;
6165     }
6166 
6167     if (!PyMapping_Check(env)) {
6168         PyErr_Format(PyExc_TypeError,
6169                      "%s: environment must be a mapping object", func_name);
6170         goto exit;
6171     }
6172 
6173     argvlist = parse_arglist(argv, &argc);
6174     if (argvlist == NULL) {
6175         goto exit;
6176     }
6177     if (!argvlist[0][0]) {
6178         PyErr_Format(PyExc_ValueError,
6179                      "%s: argv first element cannot be empty", func_name);
6180         goto exit;
6181     }
6182 
6183     envlist = parse_envlist(env, &envc);
6184     if (envlist == NULL) {
6185         goto exit;
6186     }
6187 
6188     if (file_actions != NULL && file_actions != Py_None) {
6189         /* There is a bug in old versions of glibc that makes some of the
6190          * helper functions for manipulating file actions not copy the provided
6191          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6192          * copy the value of path for some old versions of glibc (<2.20).
6193          * The use of temp_buffer here is a workaround that keeps the
6194          * python objects that own the buffers alive until posix_spawn gets called.
6195          * Check https://bugs.python.org/issue33630 and
6196          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6197         temp_buffer = PyList_New(0);
6198         if (!temp_buffer) {
6199             goto exit;
6200         }
6201         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6202             goto exit;
6203         }
6204         file_actionsp = &file_actions_buf;
6205     }
6206 
6207     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6208                                 setsigmask, setsigdef, scheduler, &attr)) {
6209         goto exit;
6210     }
6211     attrp = &attr;
6212 
6213     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6214         goto exit;
6215     }
6216 
6217     _Py_BEGIN_SUPPRESS_IPH
6218 #ifdef HAVE_POSIX_SPAWNP
6219     if (use_posix_spawnp) {
6220         err_code = posix_spawnp(&pid, path->narrow,
6221                                 file_actionsp, attrp, argvlist, envlist);
6222     }
6223     else
6224 #endif /* HAVE_POSIX_SPAWNP */
6225     {
6226         err_code = posix_spawn(&pid, path->narrow,
6227                                file_actionsp, attrp, argvlist, envlist);
6228     }
6229     _Py_END_SUPPRESS_IPH
6230 
6231     if (err_code) {
6232         errno = err_code;
6233         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6234         goto exit;
6235     }
6236 #ifdef _Py_MEMORY_SANITIZER
6237     __msan_unpoison(&pid, sizeof(pid));
6238 #endif
6239     result = PyLong_FromPid(pid);
6240 
6241 exit:
6242     if (file_actionsp) {
6243         (void)posix_spawn_file_actions_destroy(file_actionsp);
6244     }
6245     if (attrp) {
6246         (void)posix_spawnattr_destroy(attrp);
6247     }
6248     if (envlist) {
6249         free_string_array(envlist, envc);
6250     }
6251     if (argvlist) {
6252         free_string_array(argvlist, argc);
6253     }
6254     Py_XDECREF(temp_buffer);
6255     return result;
6256 }
6257 
6258 
6259 /*[clinic input]
6260 
6261 os.posix_spawn
6262     path: path_t
6263         Path of executable file.
6264     argv: object
6265         Tuple or list of strings.
6266     env: object
6267         Dictionary of strings mapping to strings.
6268     /
6269     *
6270     file_actions: object(c_default='NULL') = ()
6271         A sequence of file action tuples.
6272     setpgroup: object = NULL
6273         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6274     resetids: bool(accept={int}) = False
6275         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6276     setsid: bool(accept={int}) = False
6277         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6278     setsigmask: object(c_default='NULL') = ()
6279         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6280     setsigdef: object(c_default='NULL') = ()
6281         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6282     scheduler: object = NULL
6283         A tuple with the scheduler policy (optional) and parameters.
6284 
6285 Execute the program specified by path in a new process.
6286 [clinic start generated code]*/
6287 
6288 static PyObject *
os_posix_spawn_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env,PyObject * file_actions,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler)6289 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6290                     PyObject *env, PyObject *file_actions,
6291                     PyObject *setpgroup, int resetids, int setsid,
6292                     PyObject *setsigmask, PyObject *setsigdef,
6293                     PyObject *scheduler)
6294 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6295 {
6296     return py_posix_spawn(0, module, path, argv, env, file_actions,
6297                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6298                           scheduler);
6299 }
6300  #endif /* HAVE_POSIX_SPAWN */
6301 
6302 
6303 
6304 #ifdef HAVE_POSIX_SPAWNP
6305 /*[clinic input]
6306 
6307 os.posix_spawnp
6308     path: path_t
6309         Path of executable file.
6310     argv: object
6311         Tuple or list of strings.
6312     env: object
6313         Dictionary of strings mapping to strings.
6314     /
6315     *
6316     file_actions: object(c_default='NULL') = ()
6317         A sequence of file action tuples.
6318     setpgroup: object = NULL
6319         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6320     resetids: bool(accept={int}) = False
6321         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6322     setsid: bool(accept={int}) = False
6323         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6324     setsigmask: object(c_default='NULL') = ()
6325         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6326     setsigdef: object(c_default='NULL') = ()
6327         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6328     scheduler: object = NULL
6329         A tuple with the scheduler policy (optional) and parameters.
6330 
6331 Execute the program specified by path in a new process.
6332 [clinic start generated code]*/
6333 
6334 static PyObject *
os_posix_spawnp_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env,PyObject * file_actions,PyObject * setpgroup,int resetids,int setsid,PyObject * setsigmask,PyObject * setsigdef,PyObject * scheduler)6335 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6336                      PyObject *env, PyObject *file_actions,
6337                      PyObject *setpgroup, int resetids, int setsid,
6338                      PyObject *setsigmask, PyObject *setsigdef,
6339                      PyObject *scheduler)
6340 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6341 {
6342     return py_posix_spawn(1, module, path, argv, env, file_actions,
6343                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6344                           scheduler);
6345 }
6346 #endif /* HAVE_POSIX_SPAWNP */
6347 
6348 #ifdef HAVE_RTPSPAWN
6349 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6350 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6351                const char  *envp[])
6352 {
6353      RTP_ID rtpid;
6354      int status;
6355      pid_t res;
6356      int async_err = 0;
6357 
6358      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6359         uStackSize=0 cannot be used, the default stack size is too small for
6360         Python. */
6361      if (envp) {
6362          rtpid = rtpSpawn(rtpFileName, argv, envp,
6363                           100, 0x1000000, 0, VX_FP_TASK);
6364      }
6365      else {
6366          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6367                           100, 0x1000000, 0, VX_FP_TASK);
6368      }
6369      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6370          do {
6371              res = waitpid((pid_t)rtpid, &status, 0);
6372          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6373 
6374          if (res < 0)
6375              return RTP_ID_ERROR;
6376          return ((intptr_t)status);
6377      }
6378      return ((intptr_t)rtpid);
6379 }
6380 #endif
6381 
6382 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6383 /*[clinic input]
6384 os.spawnv
6385 
6386     mode: int
6387         Mode of process creation.
6388     path: path_t
6389         Path of executable file.
6390     argv: object
6391         Tuple or list of strings.
6392     /
6393 
6394 Execute the program specified by path in a new process.
6395 [clinic start generated code]*/
6396 
6397 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6398 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6399 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6400 {
6401     EXECV_CHAR **argvlist;
6402     int i;
6403     Py_ssize_t argc;
6404     intptr_t spawnval;
6405     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6406 
6407     /* spawnv has three arguments: (mode, path, argv), where
6408        argv is a list or tuple of strings. */
6409 
6410     if (PyList_Check(argv)) {
6411         argc = PyList_Size(argv);
6412         getitem = PyList_GetItem;
6413     }
6414     else if (PyTuple_Check(argv)) {
6415         argc = PyTuple_Size(argv);
6416         getitem = PyTuple_GetItem;
6417     }
6418     else {
6419         PyErr_SetString(PyExc_TypeError,
6420                         "spawnv() arg 2 must be a tuple or list");
6421         return NULL;
6422     }
6423     if (argc == 0) {
6424         PyErr_SetString(PyExc_ValueError,
6425             "spawnv() arg 2 cannot be empty");
6426         return NULL;
6427     }
6428 
6429     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6430     if (argvlist == NULL) {
6431         return PyErr_NoMemory();
6432     }
6433     for (i = 0; i < argc; i++) {
6434         if (!fsconvert_strdup((*getitem)(argv, i),
6435                               &argvlist[i])) {
6436             free_string_array(argvlist, i);
6437             PyErr_SetString(
6438                 PyExc_TypeError,
6439                 "spawnv() arg 2 must contain only strings");
6440             return NULL;
6441         }
6442         if (i == 0 && !argvlist[0][0]) {
6443             free_string_array(argvlist, i + 1);
6444             PyErr_SetString(
6445                 PyExc_ValueError,
6446                 "spawnv() arg 2 first element cannot be empty");
6447             return NULL;
6448         }
6449     }
6450     argvlist[argc] = NULL;
6451 
6452 #if !defined(HAVE_RTPSPAWN)
6453     if (mode == _OLD_P_OVERLAY)
6454         mode = _P_OVERLAY;
6455 #endif
6456 
6457     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6458                     Py_None) < 0) {
6459         free_string_array(argvlist, argc);
6460         return NULL;
6461     }
6462 
6463     Py_BEGIN_ALLOW_THREADS
6464     _Py_BEGIN_SUPPRESS_IPH
6465 #ifdef HAVE_WSPAWNV
6466     spawnval = _wspawnv(mode, path->wide, argvlist);
6467 #elif defined(HAVE_RTPSPAWN)
6468     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6469 #else
6470     spawnval = _spawnv(mode, path->narrow, argvlist);
6471 #endif
6472     _Py_END_SUPPRESS_IPH
6473     Py_END_ALLOW_THREADS
6474 
6475     free_string_array(argvlist, argc);
6476 
6477     if (spawnval == -1)
6478         return posix_error();
6479     else
6480         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6481 }
6482 
6483 /*[clinic input]
6484 os.spawnve
6485 
6486     mode: int
6487         Mode of process creation.
6488     path: path_t
6489         Path of executable file.
6490     argv: object
6491         Tuple or list of strings.
6492     env: object
6493         Dictionary of strings mapping to strings.
6494     /
6495 
6496 Execute the program specified by path in a new process.
6497 [clinic start generated code]*/
6498 
6499 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6500 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6501                 PyObject *env)
6502 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6503 {
6504     EXECV_CHAR **argvlist;
6505     EXECV_CHAR **envlist;
6506     PyObject *res = NULL;
6507     Py_ssize_t argc, i, envc;
6508     intptr_t spawnval;
6509     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6510     Py_ssize_t lastarg = 0;
6511 
6512     /* spawnve has four arguments: (mode, path, argv, env), where
6513        argv is a list or tuple of strings and env is a dictionary
6514        like posix.environ. */
6515 
6516     if (PyList_Check(argv)) {
6517         argc = PyList_Size(argv);
6518         getitem = PyList_GetItem;
6519     }
6520     else if (PyTuple_Check(argv)) {
6521         argc = PyTuple_Size(argv);
6522         getitem = PyTuple_GetItem;
6523     }
6524     else {
6525         PyErr_SetString(PyExc_TypeError,
6526                         "spawnve() arg 2 must be a tuple or list");
6527         goto fail_0;
6528     }
6529     if (argc == 0) {
6530         PyErr_SetString(PyExc_ValueError,
6531             "spawnve() arg 2 cannot be empty");
6532         goto fail_0;
6533     }
6534     if (!PyMapping_Check(env)) {
6535         PyErr_SetString(PyExc_TypeError,
6536                         "spawnve() arg 3 must be a mapping object");
6537         goto fail_0;
6538     }
6539 
6540     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6541     if (argvlist == NULL) {
6542         PyErr_NoMemory();
6543         goto fail_0;
6544     }
6545     for (i = 0; i < argc; i++) {
6546         if (!fsconvert_strdup((*getitem)(argv, i),
6547                               &argvlist[i]))
6548         {
6549             lastarg = i;
6550             goto fail_1;
6551         }
6552         if (i == 0 && !argvlist[0][0]) {
6553             lastarg = i + 1;
6554             PyErr_SetString(
6555                 PyExc_ValueError,
6556                 "spawnv() arg 2 first element cannot be empty");
6557             goto fail_1;
6558         }
6559     }
6560     lastarg = argc;
6561     argvlist[argc] = NULL;
6562 
6563     envlist = parse_envlist(env, &envc);
6564     if (envlist == NULL)
6565         goto fail_1;
6566 
6567 #if !defined(HAVE_RTPSPAWN)
6568     if (mode == _OLD_P_OVERLAY)
6569         mode = _P_OVERLAY;
6570 #endif
6571 
6572     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6573         goto fail_2;
6574     }
6575 
6576     Py_BEGIN_ALLOW_THREADS
6577     _Py_BEGIN_SUPPRESS_IPH
6578 #ifdef HAVE_WSPAWNV
6579     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6580 #elif defined(HAVE_RTPSPAWN)
6581     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6582                            (const char **)envlist);
6583 #else
6584     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6585 #endif
6586     _Py_END_SUPPRESS_IPH
6587     Py_END_ALLOW_THREADS
6588 
6589     if (spawnval == -1)
6590         (void) posix_error();
6591     else
6592         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6593 
6594   fail_2:
6595     while (--envc >= 0) {
6596         PyMem_Free(envlist[envc]);
6597     }
6598     PyMem_Free(envlist);
6599   fail_1:
6600     free_string_array(argvlist, lastarg);
6601   fail_0:
6602     return res;
6603 }
6604 
6605 #endif /* HAVE_SPAWNV */
6606 
6607 #ifdef HAVE_FORK
6608 
6609 /* Helper function to validate arguments.
6610    Returns 0 on success.  non-zero on failure with a TypeError raised.
6611    If obj is non-NULL it must be callable.  */
6612 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6613 check_null_or_callable(PyObject *obj, const char* obj_name)
6614 {
6615     if (obj && !PyCallable_Check(obj)) {
6616         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6617                      obj_name, _PyType_Name(Py_TYPE(obj)));
6618         return -1;
6619     }
6620     return 0;
6621 }
6622 
6623 /*[clinic input]
6624 os.register_at_fork
6625 
6626     *
6627     before: object=NULL
6628         A callable to be called in the parent before the fork() syscall.
6629     after_in_child: object=NULL
6630         A callable to be called in the child after fork().
6631     after_in_parent: object=NULL
6632         A callable to be called in the parent after fork().
6633 
6634 Register callables to be called when forking a new process.
6635 
6636 'before' callbacks are called in reverse order.
6637 'after_in_child' and 'after_in_parent' callbacks are called in order.
6638 
6639 [clinic start generated code]*/
6640 
6641 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6642 os_register_at_fork_impl(PyObject *module, PyObject *before,
6643                          PyObject *after_in_child, PyObject *after_in_parent)
6644 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6645 {
6646     PyInterpreterState *interp;
6647 
6648     if (!before && !after_in_child && !after_in_parent) {
6649         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6650         return NULL;
6651     }
6652     if (check_null_or_callable(before, "before") ||
6653         check_null_or_callable(after_in_child, "after_in_child") ||
6654         check_null_or_callable(after_in_parent, "after_in_parent")) {
6655         return NULL;
6656     }
6657     interp = _PyInterpreterState_GET();
6658 
6659     if (register_at_forker(&interp->before_forkers, before)) {
6660         return NULL;
6661     }
6662     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6663         return NULL;
6664     }
6665     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6666         return NULL;
6667     }
6668     Py_RETURN_NONE;
6669 }
6670 #endif /* HAVE_FORK */
6671 
6672 
6673 #ifdef HAVE_FORK1
6674 /*[clinic input]
6675 os.fork1
6676 
6677 Fork a child process with a single multiplexed (i.e., not bound) thread.
6678 
6679 Return 0 to child process and PID of child to parent process.
6680 [clinic start generated code]*/
6681 
6682 static PyObject *
os_fork1_impl(PyObject * module)6683 os_fork1_impl(PyObject *module)
6684 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6685 {
6686     pid_t pid;
6687 
6688     if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
6689         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6690         return NULL;
6691     }
6692     PyOS_BeforeFork();
6693     pid = fork1();
6694     if (pid == 0) {
6695         /* child: this clobbers and resets the import lock. */
6696         PyOS_AfterFork_Child();
6697     } else {
6698         /* parent: release the import lock. */
6699         PyOS_AfterFork_Parent();
6700     }
6701     if (pid == -1)
6702         return posix_error();
6703     return PyLong_FromPid(pid);
6704 }
6705 #endif /* HAVE_FORK1 */
6706 
6707 
6708 #ifdef HAVE_FORK
6709 /*[clinic input]
6710 os.fork
6711 
6712 Fork a child process.
6713 
6714 Return 0 to child process and PID of child to parent process.
6715 [clinic start generated code]*/
6716 
6717 static PyObject *
os_fork_impl(PyObject * module)6718 os_fork_impl(PyObject *module)
6719 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6720 {
6721     pid_t pid;
6722     PyInterpreterState *interp = _PyInterpreterState_GET();
6723     if (interp->config._isolated_interpreter) {
6724         PyErr_SetString(PyExc_RuntimeError,
6725                         "fork not supported for isolated subinterpreters");
6726         return NULL;
6727     }
6728     if (PySys_Audit("os.fork", NULL) < 0) {
6729         return NULL;
6730     }
6731     PyOS_BeforeFork();
6732     pid = fork();
6733     if (pid == 0) {
6734         /* child: this clobbers and resets the import lock. */
6735         PyOS_AfterFork_Child();
6736     } else {
6737         /* parent: release the import lock. */
6738         PyOS_AfterFork_Parent();
6739     }
6740     if (pid == -1)
6741         return posix_error();
6742     return PyLong_FromPid(pid);
6743 }
6744 #endif /* HAVE_FORK */
6745 
6746 
6747 #ifdef HAVE_SCHED_H
6748 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6749 /*[clinic input]
6750 os.sched_get_priority_max
6751 
6752     policy: int
6753 
6754 Get the maximum scheduling priority for policy.
6755 [clinic start generated code]*/
6756 
6757 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6758 os_sched_get_priority_max_impl(PyObject *module, int policy)
6759 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6760 {
6761     int max;
6762 
6763     max = sched_get_priority_max(policy);
6764     if (max < 0)
6765         return posix_error();
6766     return PyLong_FromLong(max);
6767 }
6768 
6769 
6770 /*[clinic input]
6771 os.sched_get_priority_min
6772 
6773     policy: int
6774 
6775 Get the minimum scheduling priority for policy.
6776 [clinic start generated code]*/
6777 
6778 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6779 os_sched_get_priority_min_impl(PyObject *module, int policy)
6780 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6781 {
6782     int min = sched_get_priority_min(policy);
6783     if (min < 0)
6784         return posix_error();
6785     return PyLong_FromLong(min);
6786 }
6787 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6788 
6789 
6790 #ifdef HAVE_SCHED_SETSCHEDULER
6791 /*[clinic input]
6792 os.sched_getscheduler
6793     pid: pid_t
6794     /
6795 
6796 Get the scheduling policy for the process identified by pid.
6797 
6798 Passing 0 for pid returns the scheduling policy for the calling process.
6799 [clinic start generated code]*/
6800 
6801 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6802 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6803 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6804 {
6805     int policy;
6806 
6807     policy = sched_getscheduler(pid);
6808     if (policy < 0)
6809         return posix_error();
6810     return PyLong_FromLong(policy);
6811 }
6812 #endif /* HAVE_SCHED_SETSCHEDULER */
6813 
6814 
6815 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6816 /*[clinic input]
6817 class os.sched_param "PyObject *" "SchedParamType"
6818 
6819 @classmethod
6820 os.sched_param.__new__
6821 
6822     sched_priority: object
6823         A scheduling parameter.
6824 
6825 Currently has only one field: sched_priority
6826 [clinic start generated code]*/
6827 
6828 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6829 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6830 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6831 {
6832     PyObject *res;
6833 
6834     res = PyStructSequence_New(type);
6835     if (!res)
6836         return NULL;
6837     Py_INCREF(sched_priority);
6838     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6839     return res;
6840 }
6841 
6842 PyDoc_VAR(os_sched_param__doc__);
6843 
6844 static PyStructSequence_Field sched_param_fields[] = {
6845     {"sched_priority", "the scheduling priority"},
6846     {0}
6847 };
6848 
6849 static PyStructSequence_Desc sched_param_desc = {
6850     "sched_param", /* name */
6851     os_sched_param__doc__, /* doc */
6852     sched_param_fields,
6853     1
6854 };
6855 
6856 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6857 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6858 {
6859     long priority;
6860 
6861     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6862         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6863         return 0;
6864     }
6865     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6866     if (priority == -1 && PyErr_Occurred())
6867         return 0;
6868     if (priority > INT_MAX || priority < INT_MIN) {
6869         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6870         return 0;
6871     }
6872     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6873     return 1;
6874 }
6875 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6876 
6877 
6878 #ifdef HAVE_SCHED_SETSCHEDULER
6879 /*[clinic input]
6880 os.sched_setscheduler
6881 
6882     pid: pid_t
6883     policy: int
6884     param as param_obj: object
6885     /
6886 
6887 Set the scheduling policy for the process identified by pid.
6888 
6889 If pid is 0, the calling process is changed.
6890 param is an instance of sched_param.
6891 [clinic start generated code]*/
6892 
6893 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6894 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6895                            PyObject *param_obj)
6896 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6897 {
6898     struct sched_param param;
6899     if (!convert_sched_param(module, param_obj, &param)) {
6900         return NULL;
6901     }
6902 
6903     /*
6904     ** sched_setscheduler() returns 0 in Linux, but the previous
6905     ** scheduling policy under Solaris/Illumos, and others.
6906     ** On error, -1 is returned in all Operating Systems.
6907     */
6908     if (sched_setscheduler(pid, policy, &param) == -1)
6909         return posix_error();
6910     Py_RETURN_NONE;
6911 }
6912 #endif  /* HAVE_SCHED_SETSCHEDULER*/
6913 
6914 
6915 #ifdef HAVE_SCHED_SETPARAM
6916 /*[clinic input]
6917 os.sched_getparam
6918     pid: pid_t
6919     /
6920 
6921 Returns scheduling parameters for the process identified by pid.
6922 
6923 If pid is 0, returns parameters for the calling process.
6924 Return value is an instance of sched_param.
6925 [clinic start generated code]*/
6926 
6927 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)6928 os_sched_getparam_impl(PyObject *module, pid_t pid)
6929 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
6930 {
6931     struct sched_param param;
6932     PyObject *result;
6933     PyObject *priority;
6934 
6935     if (sched_getparam(pid, &param))
6936         return posix_error();
6937     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
6938     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
6939     if (!result)
6940         return NULL;
6941     priority = PyLong_FromLong(param.sched_priority);
6942     if (!priority) {
6943         Py_DECREF(result);
6944         return NULL;
6945     }
6946     PyStructSequence_SET_ITEM(result, 0, priority);
6947     return result;
6948 }
6949 
6950 
6951 /*[clinic input]
6952 os.sched_setparam
6953     pid: pid_t
6954     param as param_obj: object
6955     /
6956 
6957 Set scheduling parameters for the process identified by pid.
6958 
6959 If pid is 0, sets parameters for the calling process.
6960 param should be an instance of sched_param.
6961 [clinic start generated code]*/
6962 
6963 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)6964 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
6965 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
6966 {
6967     struct sched_param param;
6968     if (!convert_sched_param(module, param_obj, &param)) {
6969         return NULL;
6970     }
6971 
6972     if (sched_setparam(pid, &param))
6973         return posix_error();
6974     Py_RETURN_NONE;
6975 }
6976 #endif /* HAVE_SCHED_SETPARAM */
6977 
6978 
6979 #ifdef HAVE_SCHED_RR_GET_INTERVAL
6980 /*[clinic input]
6981 os.sched_rr_get_interval -> double
6982     pid: pid_t
6983     /
6984 
6985 Return the round-robin quantum for the process identified by pid, in seconds.
6986 
6987 Value returned is a float.
6988 [clinic start generated code]*/
6989 
6990 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)6991 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
6992 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
6993 {
6994     struct timespec interval;
6995     if (sched_rr_get_interval(pid, &interval)) {
6996         posix_error();
6997         return -1.0;
6998     }
6999 #ifdef _Py_MEMORY_SANITIZER
7000     __msan_unpoison(&interval, sizeof(interval));
7001 #endif
7002     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7003 }
7004 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7005 
7006 
7007 /*[clinic input]
7008 os.sched_yield
7009 
7010 Voluntarily relinquish the CPU.
7011 [clinic start generated code]*/
7012 
7013 static PyObject *
os_sched_yield_impl(PyObject * module)7014 os_sched_yield_impl(PyObject *module)
7015 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7016 {
7017     if (sched_yield())
7018         return posix_error();
7019     Py_RETURN_NONE;
7020 }
7021 
7022 #ifdef HAVE_SCHED_SETAFFINITY
7023 /* The minimum number of CPUs allocated in a cpu_set_t */
7024 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7025 
7026 /*[clinic input]
7027 os.sched_setaffinity
7028     pid: pid_t
7029     mask : object
7030     /
7031 
7032 Set the CPU affinity of the process identified by pid to mask.
7033 
7034 mask should be an iterable of integers identifying CPUs.
7035 [clinic start generated code]*/
7036 
7037 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7038 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7039 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7040 {
7041     int ncpus;
7042     size_t setsize;
7043     cpu_set_t *cpu_set = NULL;
7044     PyObject *iterator = NULL, *item;
7045 
7046     iterator = PyObject_GetIter(mask);
7047     if (iterator == NULL)
7048         return NULL;
7049 
7050     ncpus = NCPUS_START;
7051     setsize = CPU_ALLOC_SIZE(ncpus);
7052     cpu_set = CPU_ALLOC(ncpus);
7053     if (cpu_set == NULL) {
7054         PyErr_NoMemory();
7055         goto error;
7056     }
7057     CPU_ZERO_S(setsize, cpu_set);
7058 
7059     while ((item = PyIter_Next(iterator))) {
7060         long cpu;
7061         if (!PyLong_Check(item)) {
7062             PyErr_Format(PyExc_TypeError,
7063                         "expected an iterator of ints, "
7064                         "but iterator yielded %R",
7065                         Py_TYPE(item));
7066             Py_DECREF(item);
7067             goto error;
7068         }
7069         cpu = PyLong_AsLong(item);
7070         Py_DECREF(item);
7071         if (cpu < 0) {
7072             if (!PyErr_Occurred())
7073                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7074             goto error;
7075         }
7076         if (cpu > INT_MAX - 1) {
7077             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7078             goto error;
7079         }
7080         if (cpu >= ncpus) {
7081             /* Grow CPU mask to fit the CPU number */
7082             int newncpus = ncpus;
7083             cpu_set_t *newmask;
7084             size_t newsetsize;
7085             while (newncpus <= cpu) {
7086                 if (newncpus > INT_MAX / 2)
7087                     newncpus = cpu + 1;
7088                 else
7089                     newncpus = newncpus * 2;
7090             }
7091             newmask = CPU_ALLOC(newncpus);
7092             if (newmask == NULL) {
7093                 PyErr_NoMemory();
7094                 goto error;
7095             }
7096             newsetsize = CPU_ALLOC_SIZE(newncpus);
7097             CPU_ZERO_S(newsetsize, newmask);
7098             memcpy(newmask, cpu_set, setsize);
7099             CPU_FREE(cpu_set);
7100             setsize = newsetsize;
7101             cpu_set = newmask;
7102             ncpus = newncpus;
7103         }
7104         CPU_SET_S(cpu, setsize, cpu_set);
7105     }
7106     if (PyErr_Occurred()) {
7107         goto error;
7108     }
7109     Py_CLEAR(iterator);
7110 
7111     if (sched_setaffinity(pid, setsize, cpu_set)) {
7112         posix_error();
7113         goto error;
7114     }
7115     CPU_FREE(cpu_set);
7116     Py_RETURN_NONE;
7117 
7118 error:
7119     if (cpu_set)
7120         CPU_FREE(cpu_set);
7121     Py_XDECREF(iterator);
7122     return NULL;
7123 }
7124 
7125 
7126 /*[clinic input]
7127 os.sched_getaffinity
7128     pid: pid_t
7129     /
7130 
7131 Return the affinity of the process identified by pid (or the current process if zero).
7132 
7133 The affinity is returned as a set of CPU identifiers.
7134 [clinic start generated code]*/
7135 
7136 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7137 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7138 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7139 {
7140     int cpu, ncpus, count;
7141     size_t setsize;
7142     cpu_set_t *mask = NULL;
7143     PyObject *res = NULL;
7144 
7145     ncpus = NCPUS_START;
7146     while (1) {
7147         setsize = CPU_ALLOC_SIZE(ncpus);
7148         mask = CPU_ALLOC(ncpus);
7149         if (mask == NULL)
7150             return PyErr_NoMemory();
7151         if (sched_getaffinity(pid, setsize, mask) == 0)
7152             break;
7153         CPU_FREE(mask);
7154         if (errno != EINVAL)
7155             return posix_error();
7156         if (ncpus > INT_MAX / 2) {
7157             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7158                             "a large enough CPU set");
7159             return NULL;
7160         }
7161         ncpus = ncpus * 2;
7162     }
7163 
7164     res = PySet_New(NULL);
7165     if (res == NULL)
7166         goto error;
7167     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7168         if (CPU_ISSET_S(cpu, setsize, mask)) {
7169             PyObject *cpu_num = PyLong_FromLong(cpu);
7170             --count;
7171             if (cpu_num == NULL)
7172                 goto error;
7173             if (PySet_Add(res, cpu_num)) {
7174                 Py_DECREF(cpu_num);
7175                 goto error;
7176             }
7177             Py_DECREF(cpu_num);
7178         }
7179     }
7180     CPU_FREE(mask);
7181     return res;
7182 
7183 error:
7184     if (mask)
7185         CPU_FREE(mask);
7186     Py_XDECREF(res);
7187     return NULL;
7188 }
7189 
7190 #endif /* HAVE_SCHED_SETAFFINITY */
7191 
7192 #endif /* HAVE_SCHED_H */
7193 
7194 
7195 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7196 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7197 #  define DEV_PTY_FILE "/dev/ptc"
7198 #  define HAVE_DEV_PTMX
7199 #else
7200 #  define DEV_PTY_FILE "/dev/ptmx"
7201 #endif
7202 
7203 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
7204 #ifdef HAVE_PTY_H
7205 #include <pty.h>
7206 #else
7207 #ifdef HAVE_LIBUTIL_H
7208 #include <libutil.h>
7209 #else
7210 #ifdef HAVE_UTIL_H
7211 #include <util.h>
7212 #endif /* HAVE_UTIL_H */
7213 #endif /* HAVE_LIBUTIL_H */
7214 #endif /* HAVE_PTY_H */
7215 #ifdef HAVE_STROPTS_H
7216 #include <stropts.h>
7217 #endif
7218 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */
7219 
7220 
7221 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7222 /*[clinic input]
7223 os.openpty
7224 
7225 Open a pseudo-terminal.
7226 
7227 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7228 for both the master and slave ends.
7229 [clinic start generated code]*/
7230 
7231 static PyObject *
os_openpty_impl(PyObject * module)7232 os_openpty_impl(PyObject *module)
7233 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7234 {
7235     int master_fd = -1, slave_fd = -1;
7236 #ifndef HAVE_OPENPTY
7237     char * slave_name;
7238 #endif
7239 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7240     PyOS_sighandler_t sig_saved;
7241 #if defined(__sun) && defined(__SVR4)
7242     extern char *ptsname(int fildes);
7243 #endif
7244 #endif
7245 
7246 #ifdef HAVE_OPENPTY
7247     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7248         goto posix_error;
7249 
7250     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7251         goto error;
7252     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7253         goto error;
7254 
7255 #elif defined(HAVE__GETPTY)
7256     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7257     if (slave_name == NULL)
7258         goto posix_error;
7259     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7260         goto error;
7261 
7262     slave_fd = _Py_open(slave_name, O_RDWR);
7263     if (slave_fd < 0)
7264         goto error;
7265 
7266 #else
7267     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7268     if (master_fd < 0)
7269         goto posix_error;
7270 
7271     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7272 
7273     /* change permission of slave */
7274     if (grantpt(master_fd) < 0) {
7275         PyOS_setsig(SIGCHLD, sig_saved);
7276         goto posix_error;
7277     }
7278 
7279     /* unlock slave */
7280     if (unlockpt(master_fd) < 0) {
7281         PyOS_setsig(SIGCHLD, sig_saved);
7282         goto posix_error;
7283     }
7284 
7285     PyOS_setsig(SIGCHLD, sig_saved);
7286 
7287     slave_name = ptsname(master_fd); /* get name of slave */
7288     if (slave_name == NULL)
7289         goto posix_error;
7290 
7291     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7292     if (slave_fd == -1)
7293         goto error;
7294 
7295     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7296         goto posix_error;
7297 
7298 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7299     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7300     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7301 #ifndef __hpux
7302     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7303 #endif /* __hpux */
7304 #endif /* HAVE_CYGWIN */
7305 #endif /* HAVE_OPENPTY */
7306 
7307     return Py_BuildValue("(ii)", master_fd, slave_fd);
7308 
7309 posix_error:
7310     posix_error();
7311 error:
7312     if (master_fd != -1)
7313         close(master_fd);
7314     if (slave_fd != -1)
7315         close(slave_fd);
7316     return NULL;
7317 }
7318 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7319 
7320 
7321 #ifdef HAVE_FORKPTY
7322 /*[clinic input]
7323 os.forkpty
7324 
7325 Fork a new process with a new pseudo-terminal as controlling tty.
7326 
7327 Returns a tuple of (pid, master_fd).
7328 Like fork(), return pid of 0 to the child process,
7329 and pid of child to the parent process.
7330 To both, return fd of newly opened pseudo-terminal.
7331 [clinic start generated code]*/
7332 
7333 static PyObject *
os_forkpty_impl(PyObject * module)7334 os_forkpty_impl(PyObject *module)
7335 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7336 {
7337     int master_fd = -1;
7338     pid_t pid;
7339 
7340     if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
7341         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7342         return NULL;
7343     }
7344     if (PySys_Audit("os.forkpty", NULL) < 0) {
7345         return NULL;
7346     }
7347     PyOS_BeforeFork();
7348     pid = forkpty(&master_fd, NULL, NULL, NULL);
7349     if (pid == 0) {
7350         /* child: this clobbers and resets the import lock. */
7351         PyOS_AfterFork_Child();
7352     } else {
7353         /* parent: release the import lock. */
7354         PyOS_AfterFork_Parent();
7355     }
7356     if (pid == -1)
7357         return posix_error();
7358     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7359 }
7360 #endif /* HAVE_FORKPTY */
7361 
7362 
7363 #ifdef HAVE_GETEGID
7364 /*[clinic input]
7365 os.getegid
7366 
7367 Return the current process's effective group id.
7368 [clinic start generated code]*/
7369 
7370 static PyObject *
os_getegid_impl(PyObject * module)7371 os_getegid_impl(PyObject *module)
7372 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7373 {
7374     return _PyLong_FromGid(getegid());
7375 }
7376 #endif /* HAVE_GETEGID */
7377 
7378 
7379 #ifdef HAVE_GETEUID
7380 /*[clinic input]
7381 os.geteuid
7382 
7383 Return the current process's effective user id.
7384 [clinic start generated code]*/
7385 
7386 static PyObject *
os_geteuid_impl(PyObject * module)7387 os_geteuid_impl(PyObject *module)
7388 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7389 {
7390     return _PyLong_FromUid(geteuid());
7391 }
7392 #endif /* HAVE_GETEUID */
7393 
7394 
7395 #ifdef HAVE_GETGID
7396 /*[clinic input]
7397 os.getgid
7398 
7399 Return the current process's group id.
7400 [clinic start generated code]*/
7401 
7402 static PyObject *
os_getgid_impl(PyObject * module)7403 os_getgid_impl(PyObject *module)
7404 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7405 {
7406     return _PyLong_FromGid(getgid());
7407 }
7408 #endif /* HAVE_GETGID */
7409 
7410 
7411 #ifdef HAVE_GETPID
7412 /*[clinic input]
7413 os.getpid
7414 
7415 Return the current process id.
7416 [clinic start generated code]*/
7417 
7418 static PyObject *
os_getpid_impl(PyObject * module)7419 os_getpid_impl(PyObject *module)
7420 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7421 {
7422     return PyLong_FromPid(getpid());
7423 }
7424 #endif /* HAVE_GETPID */
7425 
7426 #ifdef NGROUPS_MAX
7427 #define MAX_GROUPS NGROUPS_MAX
7428 #else
7429     /* defined to be 16 on Solaris7, so this should be a small number */
7430 #define MAX_GROUPS 64
7431 #endif
7432 
7433 #ifdef HAVE_GETGROUPLIST
7434 
7435 #ifdef __APPLE__
7436 /*[clinic input]
7437 os.getgrouplist
7438 
7439     user: str
7440         username to lookup
7441     group as basegid: int
7442         base group id of the user
7443     /
7444 
7445 Returns a list of groups to which a user belongs.
7446 [clinic start generated code]*/
7447 
7448 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7449 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7450 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7451 #else
7452 /*[clinic input]
7453 os.getgrouplist
7454 
7455     user: str
7456         username to lookup
7457     group as basegid: gid_t
7458         base group id of the user
7459     /
7460 
7461 Returns a list of groups to which a user belongs.
7462 [clinic start generated code]*/
7463 
7464 static PyObject *
7465 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7466 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7467 #endif
7468 {
7469     int i, ngroups;
7470     PyObject *list;
7471 #ifdef __APPLE__
7472     int *groups;
7473 #else
7474     gid_t *groups;
7475 #endif
7476 
7477     /*
7478      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7479      * number of supplimental groups a users can belong to.
7480      * We have to increment it by one because
7481      * getgrouplist() returns both the supplemental groups
7482      * and the primary group, i.e. all of the groups the
7483      * user belongs to.
7484      */
7485     ngroups = 1 + MAX_GROUPS;
7486 
7487     while (1) {
7488 #ifdef __APPLE__
7489         groups = PyMem_New(int, ngroups);
7490 #else
7491         groups = PyMem_New(gid_t, ngroups);
7492 #endif
7493         if (groups == NULL) {
7494             return PyErr_NoMemory();
7495         }
7496 
7497         int old_ngroups = ngroups;
7498         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7499             /* Success */
7500             break;
7501         }
7502 
7503         /* getgrouplist() fails if the group list is too small */
7504         PyMem_Free(groups);
7505 
7506         if (ngroups > old_ngroups) {
7507             /* If the group list is too small, the glibc implementation of
7508                getgrouplist() sets ngroups to the total number of groups and
7509                returns -1. */
7510         }
7511         else {
7512             /* Double the group list size */
7513             if (ngroups > INT_MAX / 2) {
7514                 return PyErr_NoMemory();
7515             }
7516             ngroups *= 2;
7517         }
7518 
7519         /* Retry getgrouplist() with a larger group list */
7520     }
7521 
7522 #ifdef _Py_MEMORY_SANITIZER
7523     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7524     __msan_unpoison(&ngroups, sizeof(ngroups));
7525     __msan_unpoison(groups, ngroups*sizeof(*groups));
7526 #endif
7527 
7528     list = PyList_New(ngroups);
7529     if (list == NULL) {
7530         PyMem_Free(groups);
7531         return NULL;
7532     }
7533 
7534     for (i = 0; i < ngroups; i++) {
7535 #ifdef __APPLE__
7536         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7537 #else
7538         PyObject *o = _PyLong_FromGid(groups[i]);
7539 #endif
7540         if (o == NULL) {
7541             Py_DECREF(list);
7542             PyMem_Free(groups);
7543             return NULL;
7544         }
7545         PyList_SET_ITEM(list, i, o);
7546     }
7547 
7548     PyMem_Free(groups);
7549 
7550     return list;
7551 }
7552 #endif /* HAVE_GETGROUPLIST */
7553 
7554 
7555 #ifdef HAVE_GETGROUPS
7556 /*[clinic input]
7557 os.getgroups
7558 
7559 Return list of supplemental group IDs for the process.
7560 [clinic start generated code]*/
7561 
7562 static PyObject *
os_getgroups_impl(PyObject * module)7563 os_getgroups_impl(PyObject *module)
7564 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7565 {
7566     PyObject *result = NULL;
7567     gid_t grouplist[MAX_GROUPS];
7568 
7569     /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
7570      * This is a helper variable to store the intermediate result when
7571      * that happens.
7572      *
7573      * To keep the code readable the OSX behaviour is unconditional,
7574      * according to the POSIX spec this should be safe on all unix-y
7575      * systems.
7576      */
7577     gid_t* alt_grouplist = grouplist;
7578     int n;
7579 
7580 #ifdef __APPLE__
7581     /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if
7582      * there are more groups than can fit in grouplist.  Therefore, on OS X
7583      * always first call getgroups with length 0 to get the actual number
7584      * of groups.
7585      */
7586     n = getgroups(0, NULL);
7587     if (n < 0) {
7588         return posix_error();
7589     } else if (n <= MAX_GROUPS) {
7590         /* groups will fit in existing array */
7591         alt_grouplist = grouplist;
7592     } else {
7593         alt_grouplist = PyMem_New(gid_t, n);
7594         if (alt_grouplist == NULL) {
7595             return PyErr_NoMemory();
7596         }
7597     }
7598 
7599     n = getgroups(n, alt_grouplist);
7600     if (n == -1) {
7601         if (alt_grouplist != grouplist) {
7602             PyMem_Free(alt_grouplist);
7603         }
7604         return posix_error();
7605     }
7606 #else
7607     n = getgroups(MAX_GROUPS, grouplist);
7608     if (n < 0) {
7609         if (errno == EINVAL) {
7610             n = getgroups(0, NULL);
7611             if (n == -1) {
7612                 return posix_error();
7613             }
7614             if (n == 0) {
7615                 /* Avoid malloc(0) */
7616                 alt_grouplist = grouplist;
7617             } else {
7618                 alt_grouplist = PyMem_New(gid_t, n);
7619                 if (alt_grouplist == NULL) {
7620                     return PyErr_NoMemory();
7621                 }
7622                 n = getgroups(n, alt_grouplist);
7623                 if (n == -1) {
7624                     PyMem_Free(alt_grouplist);
7625                     return posix_error();
7626                 }
7627             }
7628         } else {
7629             return posix_error();
7630         }
7631     }
7632 #endif
7633 
7634     result = PyList_New(n);
7635     if (result != NULL) {
7636         int i;
7637         for (i = 0; i < n; ++i) {
7638             PyObject *o = _PyLong_FromGid(alt_grouplist[i]);
7639             if (o == NULL) {
7640                 Py_DECREF(result);
7641                 result = NULL;
7642                 break;
7643             }
7644             PyList_SET_ITEM(result, i, o);
7645         }
7646     }
7647 
7648     if (alt_grouplist != grouplist) {
7649         PyMem_Free(alt_grouplist);
7650     }
7651 
7652     return result;
7653 }
7654 #endif /* HAVE_GETGROUPS */
7655 
7656 #ifdef HAVE_INITGROUPS
7657 #ifdef __APPLE__
7658 /*[clinic input]
7659 os.initgroups
7660 
7661     username as oname: FSConverter
7662     gid: int
7663     /
7664 
7665 Initialize the group access list.
7666 
7667 Call the system initgroups() to initialize the group access list with all of
7668 the groups of which the specified username is a member, plus the specified
7669 group id.
7670 [clinic start generated code]*/
7671 
7672 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7673 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7674 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7675 #else
7676 /*[clinic input]
7677 os.initgroups
7678 
7679     username as oname: FSConverter
7680     gid: gid_t
7681     /
7682 
7683 Initialize the group access list.
7684 
7685 Call the system initgroups() to initialize the group access list with all of
7686 the groups of which the specified username is a member, plus the specified
7687 group id.
7688 [clinic start generated code]*/
7689 
7690 static PyObject *
7691 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7692 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7693 #endif
7694 {
7695     const char *username = PyBytes_AS_STRING(oname);
7696 
7697     if (initgroups(username, gid) == -1)
7698         return PyErr_SetFromErrno(PyExc_OSError);
7699 
7700     Py_RETURN_NONE;
7701 }
7702 #endif /* HAVE_INITGROUPS */
7703 
7704 
7705 #ifdef HAVE_GETPGID
7706 /*[clinic input]
7707 os.getpgid
7708 
7709     pid: pid_t
7710 
7711 Call the system call getpgid(), and return the result.
7712 [clinic start generated code]*/
7713 
7714 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7715 os_getpgid_impl(PyObject *module, pid_t pid)
7716 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7717 {
7718     pid_t pgid = getpgid(pid);
7719     if (pgid < 0)
7720         return posix_error();
7721     return PyLong_FromPid(pgid);
7722 }
7723 #endif /* HAVE_GETPGID */
7724 
7725 
7726 #ifdef HAVE_GETPGRP
7727 /*[clinic input]
7728 os.getpgrp
7729 
7730 Return the current process group id.
7731 [clinic start generated code]*/
7732 
7733 static PyObject *
os_getpgrp_impl(PyObject * module)7734 os_getpgrp_impl(PyObject *module)
7735 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7736 {
7737 #ifdef GETPGRP_HAVE_ARG
7738     return PyLong_FromPid(getpgrp(0));
7739 #else /* GETPGRP_HAVE_ARG */
7740     return PyLong_FromPid(getpgrp());
7741 #endif /* GETPGRP_HAVE_ARG */
7742 }
7743 #endif /* HAVE_GETPGRP */
7744 
7745 
7746 #ifdef HAVE_SETPGRP
7747 /*[clinic input]
7748 os.setpgrp
7749 
7750 Make the current process the leader of its process group.
7751 [clinic start generated code]*/
7752 
7753 static PyObject *
os_setpgrp_impl(PyObject * module)7754 os_setpgrp_impl(PyObject *module)
7755 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7756 {
7757 #ifdef SETPGRP_HAVE_ARG
7758     if (setpgrp(0, 0) < 0)
7759 #else /* SETPGRP_HAVE_ARG */
7760     if (setpgrp() < 0)
7761 #endif /* SETPGRP_HAVE_ARG */
7762         return posix_error();
7763     Py_RETURN_NONE;
7764 }
7765 #endif /* HAVE_SETPGRP */
7766 
7767 #ifdef HAVE_GETPPID
7768 
7769 #ifdef MS_WINDOWS
7770 #include <tlhelp32.h>
7771 
7772 static PyObject*
win32_getppid()7773 win32_getppid()
7774 {
7775     HANDLE snapshot;
7776     pid_t mypid;
7777     PyObject* result = NULL;
7778     BOOL have_record;
7779     PROCESSENTRY32 pe;
7780 
7781     mypid = getpid(); /* This function never fails */
7782 
7783     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7784     if (snapshot == INVALID_HANDLE_VALUE)
7785         return PyErr_SetFromWindowsErr(GetLastError());
7786 
7787     pe.dwSize = sizeof(pe);
7788     have_record = Process32First(snapshot, &pe);
7789     while (have_record) {
7790         if (mypid == (pid_t)pe.th32ProcessID) {
7791             /* We could cache the ulong value in a static variable. */
7792             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7793             break;
7794         }
7795 
7796         have_record = Process32Next(snapshot, &pe);
7797     }
7798 
7799     /* If our loop exits and our pid was not found (result will be NULL)
7800      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7801      * error anyway, so let's raise it. */
7802     if (!result)
7803         result = PyErr_SetFromWindowsErr(GetLastError());
7804 
7805     CloseHandle(snapshot);
7806 
7807     return result;
7808 }
7809 #endif /*MS_WINDOWS*/
7810 
7811 
7812 /*[clinic input]
7813 os.getppid
7814 
7815 Return the parent's process id.
7816 
7817 If the parent process has already exited, Windows machines will still
7818 return its id; others systems will return the id of the 'init' process (1).
7819 [clinic start generated code]*/
7820 
7821 static PyObject *
os_getppid_impl(PyObject * module)7822 os_getppid_impl(PyObject *module)
7823 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7824 {
7825 #ifdef MS_WINDOWS
7826     return win32_getppid();
7827 #else
7828     return PyLong_FromPid(getppid());
7829 #endif
7830 }
7831 #endif /* HAVE_GETPPID */
7832 
7833 
7834 #ifdef HAVE_GETLOGIN
7835 /*[clinic input]
7836 os.getlogin
7837 
7838 Return the actual login name.
7839 [clinic start generated code]*/
7840 
7841 static PyObject *
os_getlogin_impl(PyObject * module)7842 os_getlogin_impl(PyObject *module)
7843 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7844 {
7845     PyObject *result = NULL;
7846 #ifdef MS_WINDOWS
7847     wchar_t user_name[UNLEN + 1];
7848     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7849 
7850     if (GetUserNameW(user_name, &num_chars)) {
7851         /* num_chars is the number of unicode chars plus null terminator */
7852         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7853     }
7854     else
7855         result = PyErr_SetFromWindowsErr(GetLastError());
7856 #else
7857     char *name;
7858     int old_errno = errno;
7859 
7860     errno = 0;
7861     name = getlogin();
7862     if (name == NULL) {
7863         if (errno)
7864             posix_error();
7865         else
7866             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7867     }
7868     else
7869         result = PyUnicode_DecodeFSDefault(name);
7870     errno = old_errno;
7871 #endif
7872     return result;
7873 }
7874 #endif /* HAVE_GETLOGIN */
7875 
7876 
7877 #ifdef HAVE_GETUID
7878 /*[clinic input]
7879 os.getuid
7880 
7881 Return the current process's user id.
7882 [clinic start generated code]*/
7883 
7884 static PyObject *
os_getuid_impl(PyObject * module)7885 os_getuid_impl(PyObject *module)
7886 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7887 {
7888     return _PyLong_FromUid(getuid());
7889 }
7890 #endif /* HAVE_GETUID */
7891 
7892 
7893 #ifdef MS_WINDOWS
7894 #define HAVE_KILL
7895 #endif /* MS_WINDOWS */
7896 
7897 #ifdef HAVE_KILL
7898 /*[clinic input]
7899 os.kill
7900 
7901     pid: pid_t
7902     signal: Py_ssize_t
7903     /
7904 
7905 Kill a process with a signal.
7906 [clinic start generated code]*/
7907 
7908 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)7909 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
7910 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
7911 {
7912     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
7913         return NULL;
7914     }
7915 #ifndef MS_WINDOWS
7916     if (kill(pid, (int)signal) == -1)
7917         return posix_error();
7918     Py_RETURN_NONE;
7919 #else /* !MS_WINDOWS */
7920     PyObject *result;
7921     DWORD sig = (DWORD)signal;
7922     DWORD err;
7923     HANDLE handle;
7924 
7925     /* Console processes which share a common console can be sent CTRL+C or
7926        CTRL+BREAK events, provided they handle said events. */
7927     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
7928         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
7929             err = GetLastError();
7930             PyErr_SetFromWindowsErr(err);
7931         }
7932         else
7933             Py_RETURN_NONE;
7934     }
7935 
7936     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
7937        attempt to open and terminate the process. */
7938     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
7939     if (handle == NULL) {
7940         err = GetLastError();
7941         return PyErr_SetFromWindowsErr(err);
7942     }
7943 
7944     if (TerminateProcess(handle, sig) == 0) {
7945         err = GetLastError();
7946         result = PyErr_SetFromWindowsErr(err);
7947     } else {
7948         Py_INCREF(Py_None);
7949         result = Py_None;
7950     }
7951 
7952     CloseHandle(handle);
7953     return result;
7954 #endif /* !MS_WINDOWS */
7955 }
7956 #endif /* HAVE_KILL */
7957 
7958 
7959 #ifdef HAVE_KILLPG
7960 /*[clinic input]
7961 os.killpg
7962 
7963     pgid: pid_t
7964     signal: int
7965     /
7966 
7967 Kill a process group with a signal.
7968 [clinic start generated code]*/
7969 
7970 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)7971 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
7972 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
7973 {
7974     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
7975         return NULL;
7976     }
7977     /* XXX some man pages make the `pgid` parameter an int, others
7978        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
7979        take the same type. Moreover, pid_t is always at least as wide as
7980        int (else compilation of this module fails), which is safe. */
7981     if (killpg(pgid, signal) == -1)
7982         return posix_error();
7983     Py_RETURN_NONE;
7984 }
7985 #endif /* HAVE_KILLPG */
7986 
7987 
7988 #ifdef HAVE_PLOCK
7989 #ifdef HAVE_SYS_LOCK_H
7990 #include <sys/lock.h>
7991 #endif
7992 
7993 /*[clinic input]
7994 os.plock
7995     op: int
7996     /
7997 
7998 Lock program segments into memory.");
7999 [clinic start generated code]*/
8000 
8001 static PyObject *
os_plock_impl(PyObject * module,int op)8002 os_plock_impl(PyObject *module, int op)
8003 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8004 {
8005     if (plock(op) == -1)
8006         return posix_error();
8007     Py_RETURN_NONE;
8008 }
8009 #endif /* HAVE_PLOCK */
8010 
8011 
8012 #ifdef HAVE_SETUID
8013 /*[clinic input]
8014 os.setuid
8015 
8016     uid: uid_t
8017     /
8018 
8019 Set the current process's user id.
8020 [clinic start generated code]*/
8021 
8022 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8023 os_setuid_impl(PyObject *module, uid_t uid)
8024 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8025 {
8026     if (setuid(uid) < 0)
8027         return posix_error();
8028     Py_RETURN_NONE;
8029 }
8030 #endif /* HAVE_SETUID */
8031 
8032 
8033 #ifdef HAVE_SETEUID
8034 /*[clinic input]
8035 os.seteuid
8036 
8037     euid: uid_t
8038     /
8039 
8040 Set the current process's effective user id.
8041 [clinic start generated code]*/
8042 
8043 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8044 os_seteuid_impl(PyObject *module, uid_t euid)
8045 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8046 {
8047     if (seteuid(euid) < 0)
8048         return posix_error();
8049     Py_RETURN_NONE;
8050 }
8051 #endif /* HAVE_SETEUID */
8052 
8053 
8054 #ifdef HAVE_SETEGID
8055 /*[clinic input]
8056 os.setegid
8057 
8058     egid: gid_t
8059     /
8060 
8061 Set the current process's effective group id.
8062 [clinic start generated code]*/
8063 
8064 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8065 os_setegid_impl(PyObject *module, gid_t egid)
8066 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8067 {
8068     if (setegid(egid) < 0)
8069         return posix_error();
8070     Py_RETURN_NONE;
8071 }
8072 #endif /* HAVE_SETEGID */
8073 
8074 
8075 #ifdef HAVE_SETREUID
8076 /*[clinic input]
8077 os.setreuid
8078 
8079     ruid: uid_t
8080     euid: uid_t
8081     /
8082 
8083 Set the current process's real and effective user ids.
8084 [clinic start generated code]*/
8085 
8086 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8087 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8088 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8089 {
8090     if (setreuid(ruid, euid) < 0) {
8091         return posix_error();
8092     } else {
8093         Py_RETURN_NONE;
8094     }
8095 }
8096 #endif /* HAVE_SETREUID */
8097 
8098 
8099 #ifdef HAVE_SETREGID
8100 /*[clinic input]
8101 os.setregid
8102 
8103     rgid: gid_t
8104     egid: gid_t
8105     /
8106 
8107 Set the current process's real and effective group ids.
8108 [clinic start generated code]*/
8109 
8110 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8111 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8112 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8113 {
8114     if (setregid(rgid, egid) < 0)
8115         return posix_error();
8116     Py_RETURN_NONE;
8117 }
8118 #endif /* HAVE_SETREGID */
8119 
8120 
8121 #ifdef HAVE_SETGID
8122 /*[clinic input]
8123 os.setgid
8124     gid: gid_t
8125     /
8126 
8127 Set the current process's group id.
8128 [clinic start generated code]*/
8129 
8130 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8131 os_setgid_impl(PyObject *module, gid_t gid)
8132 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8133 {
8134     if (setgid(gid) < 0)
8135         return posix_error();
8136     Py_RETURN_NONE;
8137 }
8138 #endif /* HAVE_SETGID */
8139 
8140 
8141 #ifdef HAVE_SETGROUPS
8142 /*[clinic input]
8143 os.setgroups
8144 
8145     groups: object
8146     /
8147 
8148 Set the groups of the current process to list.
8149 [clinic start generated code]*/
8150 
8151 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8152 os_setgroups(PyObject *module, PyObject *groups)
8153 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8154 {
8155     Py_ssize_t i, len;
8156     gid_t grouplist[MAX_GROUPS];
8157 
8158     if (!PySequence_Check(groups)) {
8159         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8160         return NULL;
8161     }
8162     len = PySequence_Size(groups);
8163     if (len < 0) {
8164         return NULL;
8165     }
8166     if (len > MAX_GROUPS) {
8167         PyErr_SetString(PyExc_ValueError, "too many groups");
8168         return NULL;
8169     }
8170     for(i = 0; i < len; i++) {
8171         PyObject *elem;
8172         elem = PySequence_GetItem(groups, i);
8173         if (!elem)
8174             return NULL;
8175         if (!PyLong_Check(elem)) {
8176             PyErr_SetString(PyExc_TypeError,
8177                             "groups must be integers");
8178             Py_DECREF(elem);
8179             return NULL;
8180         } else {
8181             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8182                 Py_DECREF(elem);
8183                 return NULL;
8184             }
8185         }
8186         Py_DECREF(elem);
8187     }
8188 
8189     if (setgroups(len, grouplist) < 0)
8190         return posix_error();
8191     Py_RETURN_NONE;
8192 }
8193 #endif /* HAVE_SETGROUPS */
8194 
8195 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8196 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8197 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8198 {
8199     PyObject *result;
8200     PyObject *struct_rusage;
8201 
8202     if (pid == -1)
8203         return posix_error();
8204 
8205     // If wait succeeded but no child was ready to report status, ru will not
8206     // have been populated.
8207     if (pid == 0) {
8208         memset(ru, 0, sizeof(*ru));
8209     }
8210 
8211     PyObject *m = PyImport_ImportModuleNoBlock("resource");
8212     if (m == NULL)
8213         return NULL;
8214     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8215     Py_DECREF(m);
8216     if (struct_rusage == NULL)
8217         return NULL;
8218 
8219     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8220     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8221     Py_DECREF(struct_rusage);
8222     if (!result)
8223         return NULL;
8224 
8225 #ifndef doubletime
8226 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8227 #endif
8228 
8229     PyStructSequence_SET_ITEM(result, 0,
8230                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8231     PyStructSequence_SET_ITEM(result, 1,
8232                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8233 #define SET_INT(result, index, value)\
8234         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8235     SET_INT(result, 2, ru->ru_maxrss);
8236     SET_INT(result, 3, ru->ru_ixrss);
8237     SET_INT(result, 4, ru->ru_idrss);
8238     SET_INT(result, 5, ru->ru_isrss);
8239     SET_INT(result, 6, ru->ru_minflt);
8240     SET_INT(result, 7, ru->ru_majflt);
8241     SET_INT(result, 8, ru->ru_nswap);
8242     SET_INT(result, 9, ru->ru_inblock);
8243     SET_INT(result, 10, ru->ru_oublock);
8244     SET_INT(result, 11, ru->ru_msgsnd);
8245     SET_INT(result, 12, ru->ru_msgrcv);
8246     SET_INT(result, 13, ru->ru_nsignals);
8247     SET_INT(result, 14, ru->ru_nvcsw);
8248     SET_INT(result, 15, ru->ru_nivcsw);
8249 #undef SET_INT
8250 
8251     if (PyErr_Occurred()) {
8252         Py_DECREF(result);
8253         return NULL;
8254     }
8255 
8256     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8257 }
8258 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8259 
8260 
8261 #ifdef HAVE_WAIT3
8262 /*[clinic input]
8263 os.wait3
8264 
8265     options: int
8266 Wait for completion of a child process.
8267 
8268 Returns a tuple of information about the child process:
8269   (pid, status, rusage)
8270 [clinic start generated code]*/
8271 
8272 static PyObject *
os_wait3_impl(PyObject * module,int options)8273 os_wait3_impl(PyObject *module, int options)
8274 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8275 {
8276     pid_t pid;
8277     struct rusage ru;
8278     int async_err = 0;
8279     WAIT_TYPE status;
8280     WAIT_STATUS_INT(status) = 0;
8281 
8282     do {
8283         Py_BEGIN_ALLOW_THREADS
8284         pid = wait3(&status, options, &ru);
8285         Py_END_ALLOW_THREADS
8286     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8287     if (pid < 0)
8288         return (!async_err) ? posix_error() : NULL;
8289 
8290     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8291 }
8292 #endif /* HAVE_WAIT3 */
8293 
8294 
8295 #ifdef HAVE_WAIT4
8296 /*[clinic input]
8297 
8298 os.wait4
8299 
8300     pid: pid_t
8301     options: int
8302 
8303 Wait for completion of a specific child process.
8304 
8305 Returns a tuple of information about the child process:
8306   (pid, status, rusage)
8307 [clinic start generated code]*/
8308 
8309 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8310 os_wait4_impl(PyObject *module, pid_t pid, int options)
8311 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8312 {
8313     pid_t res;
8314     struct rusage ru;
8315     int async_err = 0;
8316     WAIT_TYPE status;
8317     WAIT_STATUS_INT(status) = 0;
8318 
8319     do {
8320         Py_BEGIN_ALLOW_THREADS
8321         res = wait4(pid, &status, options, &ru);
8322         Py_END_ALLOW_THREADS
8323     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8324     if (res < 0)
8325         return (!async_err) ? posix_error() : NULL;
8326 
8327     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8328 }
8329 #endif /* HAVE_WAIT4 */
8330 
8331 
8332 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8333 /*[clinic input]
8334 os.waitid
8335 
8336     idtype: idtype_t
8337         Must be one of be P_PID, P_PGID or P_ALL.
8338     id: id_t
8339         The id to wait on.
8340     options: int
8341         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8342         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8343     /
8344 
8345 Returns the result of waiting for a process or processes.
8346 
8347 Returns either waitid_result or None if WNOHANG is specified and there are
8348 no children in a waitable state.
8349 [clinic start generated code]*/
8350 
8351 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8352 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8353 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8354 {
8355     PyObject *result;
8356     int res;
8357     int async_err = 0;
8358     siginfo_t si;
8359     si.si_pid = 0;
8360 
8361     do {
8362         Py_BEGIN_ALLOW_THREADS
8363         res = waitid(idtype, id, &si, options);
8364         Py_END_ALLOW_THREADS
8365     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8366     if (res < 0)
8367         return (!async_err) ? posix_error() : NULL;
8368 
8369     if (si.si_pid == 0)
8370         Py_RETURN_NONE;
8371 
8372     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8373     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8374     if (!result)
8375         return NULL;
8376 
8377     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8378     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8379     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8380     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8381     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8382     if (PyErr_Occurred()) {
8383         Py_DECREF(result);
8384         return NULL;
8385     }
8386 
8387     return result;
8388 }
8389 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8390 
8391 
8392 #if defined(HAVE_WAITPID)
8393 /*[clinic input]
8394 os.waitpid
8395     pid: pid_t
8396     options: int
8397     /
8398 
8399 Wait for completion of a given child process.
8400 
8401 Returns a tuple of information regarding the child process:
8402     (pid, status)
8403 
8404 The options argument is ignored on Windows.
8405 [clinic start generated code]*/
8406 
8407 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8408 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8409 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8410 {
8411     pid_t res;
8412     int async_err = 0;
8413     WAIT_TYPE status;
8414     WAIT_STATUS_INT(status) = 0;
8415 
8416     do {
8417         Py_BEGIN_ALLOW_THREADS
8418         res = waitpid(pid, &status, options);
8419         Py_END_ALLOW_THREADS
8420     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8421     if (res < 0)
8422         return (!async_err) ? posix_error() : NULL;
8423 
8424     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8425 }
8426 #elif defined(HAVE_CWAIT)
8427 /* MS C has a variant of waitpid() that's usable for most purposes. */
8428 /*[clinic input]
8429 os.waitpid
8430     pid: intptr_t
8431     options: int
8432     /
8433 
8434 Wait for completion of a given process.
8435 
8436 Returns a tuple of information regarding the process:
8437     (pid, status << 8)
8438 
8439 The options argument is ignored on Windows.
8440 [clinic start generated code]*/
8441 
8442 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8443 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8444 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8445 {
8446     int status;
8447     intptr_t res;
8448     int async_err = 0;
8449 
8450     do {
8451         Py_BEGIN_ALLOW_THREADS
8452         _Py_BEGIN_SUPPRESS_IPH
8453         res = _cwait(&status, pid, options);
8454         _Py_END_SUPPRESS_IPH
8455         Py_END_ALLOW_THREADS
8456     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8457     if (res < 0)
8458         return (!async_err) ? posix_error() : NULL;
8459 
8460     unsigned long long ustatus = (unsigned int)status;
8461 
8462     /* shift the status left a byte so this is more like the POSIX waitpid */
8463     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8464 }
8465 #endif
8466 
8467 
8468 #ifdef HAVE_WAIT
8469 /*[clinic input]
8470 os.wait
8471 
8472 Wait for completion of a child process.
8473 
8474 Returns a tuple of information about the child process:
8475     (pid, status)
8476 [clinic start generated code]*/
8477 
8478 static PyObject *
os_wait_impl(PyObject * module)8479 os_wait_impl(PyObject *module)
8480 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8481 {
8482     pid_t pid;
8483     int async_err = 0;
8484     WAIT_TYPE status;
8485     WAIT_STATUS_INT(status) = 0;
8486 
8487     do {
8488         Py_BEGIN_ALLOW_THREADS
8489         pid = wait(&status);
8490         Py_END_ALLOW_THREADS
8491     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8492     if (pid < 0)
8493         return (!async_err) ? posix_error() : NULL;
8494 
8495     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8496 }
8497 #endif /* HAVE_WAIT */
8498 
8499 #if defined(__linux__) && defined(__NR_pidfd_open)
8500 /*[clinic input]
8501 os.pidfd_open
8502   pid: pid_t
8503   flags: unsigned_int = 0
8504 
8505 Return a file descriptor referring to the process *pid*.
8506 
8507 The descriptor can be used to perform process management without races and
8508 signals.
8509 [clinic start generated code]*/
8510 
8511 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8512 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8513 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8514 {
8515     int fd = syscall(__NR_pidfd_open, pid, flags);
8516     if (fd < 0) {
8517         return posix_error();
8518     }
8519     return PyLong_FromLong(fd);
8520 }
8521 #endif
8522 
8523 
8524 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8525 /*[clinic input]
8526 os.readlink
8527 
8528     path: path_t
8529     *
8530     dir_fd: dir_fd(requires='readlinkat') = None
8531 
8532 Return a string representing the path to which the symbolic link points.
8533 
8534 If dir_fd is not None, it should be a file descriptor open to a directory,
8535 and path should be relative; path will then be relative to that directory.
8536 
8537 dir_fd may not be implemented on your platform.  If it is unavailable,
8538 using it will raise a NotImplementedError.
8539 [clinic start generated code]*/
8540 
8541 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8542 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8543 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8544 {
8545 #if defined(HAVE_READLINK)
8546     char buffer[MAXPATHLEN+1];
8547     ssize_t length;
8548 #ifdef HAVE_READLINKAT
8549     int readlinkat_unavailable = 0;
8550 #endif
8551 
8552     Py_BEGIN_ALLOW_THREADS
8553 #ifdef HAVE_READLINKAT
8554     if (dir_fd != DEFAULT_DIR_FD) {
8555         if (HAVE_READLINKAT_RUNTIME) {
8556             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8557         } else {
8558             readlinkat_unavailable = 1;
8559         }
8560     } else
8561 #endif
8562         length = readlink(path->narrow, buffer, MAXPATHLEN);
8563     Py_END_ALLOW_THREADS
8564 
8565 #ifdef HAVE_READLINKAT
8566     if (readlinkat_unavailable) {
8567         argument_unavailable_error(NULL, "dir_fd");
8568         return NULL;
8569     }
8570 #endif
8571 
8572     if (length < 0) {
8573         return path_error(path);
8574     }
8575     buffer[length] = '\0';
8576 
8577     if (PyUnicode_Check(path->object))
8578         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8579     else
8580         return PyBytes_FromStringAndSize(buffer, length);
8581 #elif defined(MS_WINDOWS)
8582     DWORD n_bytes_returned;
8583     DWORD io_result = 0;
8584     HANDLE reparse_point_handle;
8585     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8586     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8587     PyObject *result = NULL;
8588 
8589     /* First get a handle to the reparse point */
8590     Py_BEGIN_ALLOW_THREADS
8591     reparse_point_handle = CreateFileW(
8592         path->wide,
8593         0,
8594         0,
8595         0,
8596         OPEN_EXISTING,
8597         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8598         0);
8599     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8600         /* New call DeviceIoControl to read the reparse point */
8601         io_result = DeviceIoControl(
8602             reparse_point_handle,
8603             FSCTL_GET_REPARSE_POINT,
8604             0, 0, /* in buffer */
8605             target_buffer, sizeof(target_buffer),
8606             &n_bytes_returned,
8607             0 /* we're not using OVERLAPPED_IO */
8608             );
8609         CloseHandle(reparse_point_handle);
8610     }
8611     Py_END_ALLOW_THREADS
8612 
8613     if (io_result == 0) {
8614         return path_error(path);
8615     }
8616 
8617     wchar_t *name = NULL;
8618     Py_ssize_t nameLen = 0;
8619     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8620     {
8621         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8622                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8623         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8624     }
8625     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8626     {
8627         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8628                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8629         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8630     }
8631     else
8632     {
8633         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8634     }
8635     if (name) {
8636         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8637             /* Our buffer is mutable, so this is okay */
8638             name[1] = L'\\';
8639         }
8640         result = PyUnicode_FromWideChar(name, nameLen);
8641         if (result && path->narrow) {
8642             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8643         }
8644     }
8645     return result;
8646 #endif
8647 }
8648 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8649 
8650 #if defined(MS_WINDOWS)
8651 
8652 /* Remove the last portion of the path - return 0 on success */
8653 static int
_dirnameW(WCHAR * path)8654 _dirnameW(WCHAR *path)
8655 {
8656     WCHAR *ptr;
8657     size_t length = wcsnlen_s(path, MAX_PATH);
8658     if (length == MAX_PATH) {
8659         return -1;
8660     }
8661 
8662     /* walk the path from the end until a backslash is encountered */
8663     for(ptr = path + length; ptr != path; ptr--) {
8664         if (*ptr == L'\\' || *ptr == L'/') {
8665             break;
8666         }
8667     }
8668     *ptr = 0;
8669     return 0;
8670 }
8671 
8672 #endif
8673 
8674 #ifdef HAVE_SYMLINK
8675 
8676 #if defined(MS_WINDOWS)
8677 
8678 /* Is this path absolute? */
8679 static int
_is_absW(const WCHAR * path)8680 _is_absW(const WCHAR *path)
8681 {
8682     return path[0] == L'\\' || path[0] == L'/' ||
8683         (path[0] && path[1] == L':');
8684 }
8685 
8686 /* join root and rest with a backslash - return 0 on success */
8687 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8688 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8689 {
8690     if (_is_absW(rest)) {
8691         return wcscpy_s(dest_path, MAX_PATH, rest);
8692     }
8693 
8694     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8695         return -1;
8696     }
8697 
8698     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8699         return -1;
8700     }
8701 
8702     return wcscat_s(dest_path, MAX_PATH, rest);
8703 }
8704 
8705 /* Return True if the path at src relative to dest is a directory */
8706 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8707 _check_dirW(LPCWSTR src, LPCWSTR dest)
8708 {
8709     WIN32_FILE_ATTRIBUTE_DATA src_info;
8710     WCHAR dest_parent[MAX_PATH];
8711     WCHAR src_resolved[MAX_PATH] = L"";
8712 
8713     /* dest_parent = os.path.dirname(dest) */
8714     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8715         _dirnameW(dest_parent)) {
8716         return 0;
8717     }
8718     /* src_resolved = os.path.join(dest_parent, src) */
8719     if (_joinW(src_resolved, dest_parent, src)) {
8720         return 0;
8721     }
8722     return (
8723         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8724         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8725     );
8726 }
8727 #endif
8728 
8729 
8730 /*[clinic input]
8731 os.symlink
8732     src: path_t
8733     dst: path_t
8734     target_is_directory: bool = False
8735     *
8736     dir_fd: dir_fd(requires='symlinkat')=None
8737 
8738 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8739 
8740 Create a symbolic link pointing to src named dst.
8741 
8742 target_is_directory is required on Windows if the target is to be
8743   interpreted as a directory.  (On Windows, symlink requires
8744   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8745   target_is_directory is ignored on non-Windows platforms.
8746 
8747 If dir_fd is not None, it should be a file descriptor open to a directory,
8748   and path should be relative; path will then be relative to that directory.
8749 dir_fd may not be implemented on your platform.
8750   If it is unavailable, using it will raise a NotImplementedError.
8751 
8752 [clinic start generated code]*/
8753 
8754 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8755 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8756                 int target_is_directory, int dir_fd)
8757 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8758 {
8759 #ifdef MS_WINDOWS
8760     DWORD result;
8761     DWORD flags = 0;
8762 
8763     /* Assumed true, set to false if detected to not be available. */
8764     static int windows_has_symlink_unprivileged_flag = TRUE;
8765 #else
8766     int result;
8767 #ifdef HAVE_SYMLINKAT
8768     int symlinkat_unavailable = 0;
8769 #endif
8770 #endif
8771 
8772     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8773                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8774         return NULL;
8775     }
8776 
8777 #ifdef MS_WINDOWS
8778 
8779     if (windows_has_symlink_unprivileged_flag) {
8780         /* Allow non-admin symlinks if system allows it. */
8781         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8782     }
8783 
8784     Py_BEGIN_ALLOW_THREADS
8785     _Py_BEGIN_SUPPRESS_IPH
8786     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8787     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8788         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8789     }
8790 
8791     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8792     _Py_END_SUPPRESS_IPH
8793     Py_END_ALLOW_THREADS
8794 
8795     if (windows_has_symlink_unprivileged_flag && !result &&
8796         ERROR_INVALID_PARAMETER == GetLastError()) {
8797 
8798         Py_BEGIN_ALLOW_THREADS
8799         _Py_BEGIN_SUPPRESS_IPH
8800         /* This error might be caused by
8801         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8802         Try again, and update windows_has_symlink_unprivileged_flag if we
8803         are successful this time.
8804 
8805         NOTE: There is a risk of a race condition here if there are other
8806         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8807         another process (or thread) changes that condition in between our
8808         calls to CreateSymbolicLink.
8809         */
8810         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8811         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8812         _Py_END_SUPPRESS_IPH
8813         Py_END_ALLOW_THREADS
8814 
8815         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8816             windows_has_symlink_unprivileged_flag = FALSE;
8817         }
8818     }
8819 
8820     if (!result)
8821         return path_error2(src, dst);
8822 
8823 #else
8824 
8825     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8826         PyErr_SetString(PyExc_ValueError,
8827             "symlink: src and dst must be the same type");
8828         return NULL;
8829     }
8830 
8831     Py_BEGIN_ALLOW_THREADS
8832 #ifdef HAVE_SYMLINKAT
8833     if (dir_fd != DEFAULT_DIR_FD) {
8834         if (HAVE_SYMLINKAT_RUNTIME) {
8835             result = symlinkat(src->narrow, dir_fd, dst->narrow);
8836         } else {
8837             symlinkat_unavailable = 1;
8838         }
8839     } else
8840 #endif
8841         result = symlink(src->narrow, dst->narrow);
8842     Py_END_ALLOW_THREADS
8843 
8844 #ifdef HAVE_SYMLINKAT
8845     if (symlinkat_unavailable) {
8846           argument_unavailable_error(NULL, "dir_fd");
8847           return NULL;
8848     }
8849 #endif
8850 
8851     if (result)
8852         return path_error2(src, dst);
8853 #endif
8854 
8855     Py_RETURN_NONE;
8856 }
8857 #endif /* HAVE_SYMLINK */
8858 
8859 
8860 
8861 
8862 static PyStructSequence_Field times_result_fields[] = {
8863     {"user",    "user time"},
8864     {"system",   "system time"},
8865     {"children_user",    "user time of children"},
8866     {"children_system",    "system time of children"},
8867     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8868     {NULL}
8869 };
8870 
8871 PyDoc_STRVAR(times_result__doc__,
8872 "times_result: Result from os.times().\n\n\
8873 This object may be accessed either as a tuple of\n\
8874   (user, system, children_user, children_system, elapsed),\n\
8875 or via the attributes user, system, children_user, children_system,\n\
8876 and elapsed.\n\
8877 \n\
8878 See os.times for more information.");
8879 
8880 static PyStructSequence_Desc times_result_desc = {
8881     "times_result", /* name */
8882     times_result__doc__, /* doc */
8883     times_result_fields,
8884     5
8885 };
8886 
8887 #ifdef MS_WINDOWS
8888 #define HAVE_TIMES  /* mandatory, for the method table */
8889 #endif
8890 
8891 #ifdef HAVE_TIMES
8892 
8893 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)8894 build_times_result(PyObject *module, double user, double system,
8895     double children_user, double children_system,
8896     double elapsed)
8897 {
8898     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
8899     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
8900     if (value == NULL)
8901         return NULL;
8902 
8903 #define SET(i, field) \
8904     { \
8905     PyObject *o = PyFloat_FromDouble(field); \
8906     if (!o) { \
8907         Py_DECREF(value); \
8908         return NULL; \
8909     } \
8910     PyStructSequence_SET_ITEM(value, i, o); \
8911     } \
8912 
8913     SET(0, user);
8914     SET(1, system);
8915     SET(2, children_user);
8916     SET(3, children_system);
8917     SET(4, elapsed);
8918 
8919 #undef SET
8920 
8921     return value;
8922 }
8923 
8924 
8925 #ifndef MS_WINDOWS
8926 #define NEED_TICKS_PER_SECOND
8927 static long ticks_per_second = -1;
8928 #endif /* MS_WINDOWS */
8929 
8930 /*[clinic input]
8931 os.times
8932 
8933 Return a collection containing process timing information.
8934 
8935 The object returned behaves like a named tuple with these fields:
8936   (utime, stime, cutime, cstime, elapsed_time)
8937 All fields are floating point numbers.
8938 [clinic start generated code]*/
8939 
8940 static PyObject *
os_times_impl(PyObject * module)8941 os_times_impl(PyObject *module)
8942 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
8943 #ifdef MS_WINDOWS
8944 {
8945     FILETIME create, exit, kernel, user;
8946     HANDLE hProc;
8947     hProc = GetCurrentProcess();
8948     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
8949     /* The fields of a FILETIME structure are the hi and lo part
8950        of a 64-bit value expressed in 100 nanosecond units.
8951        1e7 is one second in such units; 1e-7 the inverse.
8952        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
8953     */
8954     return build_times_result(module,
8955         (double)(user.dwHighDateTime*429.4967296 +
8956                  user.dwLowDateTime*1e-7),
8957         (double)(kernel.dwHighDateTime*429.4967296 +
8958                  kernel.dwLowDateTime*1e-7),
8959         (double)0,
8960         (double)0,
8961         (double)0);
8962 }
8963 #else /* MS_WINDOWS */
8964 {
8965 
8966 
8967     struct tms t;
8968     clock_t c;
8969     errno = 0;
8970     c = times(&t);
8971     if (c == (clock_t) -1)
8972         return posix_error();
8973     return build_times_result(module,
8974                          (double)t.tms_utime / ticks_per_second,
8975                          (double)t.tms_stime / ticks_per_second,
8976                          (double)t.tms_cutime / ticks_per_second,
8977                          (double)t.tms_cstime / ticks_per_second,
8978                          (double)c / ticks_per_second);
8979 }
8980 #endif /* MS_WINDOWS */
8981 #endif /* HAVE_TIMES */
8982 
8983 
8984 #ifdef HAVE_GETSID
8985 /*[clinic input]
8986 os.getsid
8987 
8988     pid: pid_t
8989     /
8990 
8991 Call the system call getsid(pid) and return the result.
8992 [clinic start generated code]*/
8993 
8994 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)8995 os_getsid_impl(PyObject *module, pid_t pid)
8996 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
8997 {
8998     int sid;
8999     sid = getsid(pid);
9000     if (sid < 0)
9001         return posix_error();
9002     return PyLong_FromLong((long)sid);
9003 }
9004 #endif /* HAVE_GETSID */
9005 
9006 
9007 #ifdef HAVE_SETSID
9008 /*[clinic input]
9009 os.setsid
9010 
9011 Call the system call setsid().
9012 [clinic start generated code]*/
9013 
9014 static PyObject *
os_setsid_impl(PyObject * module)9015 os_setsid_impl(PyObject *module)
9016 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9017 {
9018     if (setsid() < 0)
9019         return posix_error();
9020     Py_RETURN_NONE;
9021 }
9022 #endif /* HAVE_SETSID */
9023 
9024 
9025 #ifdef HAVE_SETPGID
9026 /*[clinic input]
9027 os.setpgid
9028 
9029     pid: pid_t
9030     pgrp: pid_t
9031     /
9032 
9033 Call the system call setpgid(pid, pgrp).
9034 [clinic start generated code]*/
9035 
9036 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9037 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9038 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9039 {
9040     if (setpgid(pid, pgrp) < 0)
9041         return posix_error();
9042     Py_RETURN_NONE;
9043 }
9044 #endif /* HAVE_SETPGID */
9045 
9046 
9047 #ifdef HAVE_TCGETPGRP
9048 /*[clinic input]
9049 os.tcgetpgrp
9050 
9051     fd: int
9052     /
9053 
9054 Return the process group associated with the terminal specified by fd.
9055 [clinic start generated code]*/
9056 
9057 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9058 os_tcgetpgrp_impl(PyObject *module, int fd)
9059 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9060 {
9061     pid_t pgid = tcgetpgrp(fd);
9062     if (pgid < 0)
9063         return posix_error();
9064     return PyLong_FromPid(pgid);
9065 }
9066 #endif /* HAVE_TCGETPGRP */
9067 
9068 
9069 #ifdef HAVE_TCSETPGRP
9070 /*[clinic input]
9071 os.tcsetpgrp
9072 
9073     fd: int
9074     pgid: pid_t
9075     /
9076 
9077 Set the process group associated with the terminal specified by fd.
9078 [clinic start generated code]*/
9079 
9080 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9081 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9082 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9083 {
9084     if (tcsetpgrp(fd, pgid) < 0)
9085         return posix_error();
9086     Py_RETURN_NONE;
9087 }
9088 #endif /* HAVE_TCSETPGRP */
9089 
9090 /* Functions acting on file descriptors */
9091 
9092 #ifdef O_CLOEXEC
9093 extern int _Py_open_cloexec_works;
9094 #endif
9095 
9096 
9097 /*[clinic input]
9098 os.open -> int
9099     path: path_t
9100     flags: int
9101     mode: int = 0o777
9102     *
9103     dir_fd: dir_fd(requires='openat') = None
9104 
9105 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9106 
9107 Open a file for low level IO.  Returns a file descriptor (integer).
9108 
9109 If dir_fd is not None, it should be a file descriptor open to a directory,
9110   and path should be relative; path will then be relative to that directory.
9111 dir_fd may not be implemented on your platform.
9112   If it is unavailable, using it will raise a NotImplementedError.
9113 [clinic start generated code]*/
9114 
9115 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9116 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9117 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9118 {
9119     int fd;
9120     int async_err = 0;
9121 #ifdef HAVE_OPENAT
9122     int openat_unavailable = 0;
9123 #endif
9124 
9125 #ifdef O_CLOEXEC
9126     int *atomic_flag_works = &_Py_open_cloexec_works;
9127 #elif !defined(MS_WINDOWS)
9128     int *atomic_flag_works = NULL;
9129 #endif
9130 
9131 #ifdef MS_WINDOWS
9132     flags |= O_NOINHERIT;
9133 #elif defined(O_CLOEXEC)
9134     flags |= O_CLOEXEC;
9135 #endif
9136 
9137     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9138         return -1;
9139     }
9140 
9141     _Py_BEGIN_SUPPRESS_IPH
9142     do {
9143         Py_BEGIN_ALLOW_THREADS
9144 #ifdef MS_WINDOWS
9145         fd = _wopen(path->wide, flags, mode);
9146 #else
9147 #ifdef HAVE_OPENAT
9148         if (dir_fd != DEFAULT_DIR_FD) {
9149             if (HAVE_OPENAT_RUNTIME) {
9150                 fd = openat(dir_fd, path->narrow, flags, mode);
9151 
9152             } else {
9153                 openat_unavailable = 1;
9154                 fd = -1;
9155             }
9156         } else
9157 #endif /* HAVE_OPENAT */
9158             fd = open(path->narrow, flags, mode);
9159 #endif /* !MS_WINDOWS */
9160         Py_END_ALLOW_THREADS
9161     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9162     _Py_END_SUPPRESS_IPH
9163 
9164 #ifdef HAVE_OPENAT
9165     if (openat_unavailable) {
9166         argument_unavailable_error(NULL, "dir_fd");
9167         return -1;
9168     }
9169 #endif
9170 
9171     if (fd < 0) {
9172         if (!async_err)
9173             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9174         return -1;
9175     }
9176 
9177 #ifndef MS_WINDOWS
9178     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9179         close(fd);
9180         return -1;
9181     }
9182 #endif
9183 
9184     return fd;
9185 }
9186 
9187 
9188 /*[clinic input]
9189 os.close
9190 
9191     fd: int
9192 
9193 Close a file descriptor.
9194 [clinic start generated code]*/
9195 
9196 static PyObject *
os_close_impl(PyObject * module,int fd)9197 os_close_impl(PyObject *module, int fd)
9198 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9199 {
9200     int res;
9201     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9202      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9203      * for more details.
9204      */
9205     Py_BEGIN_ALLOW_THREADS
9206     _Py_BEGIN_SUPPRESS_IPH
9207     res = close(fd);
9208     _Py_END_SUPPRESS_IPH
9209     Py_END_ALLOW_THREADS
9210     if (res < 0)
9211         return posix_error();
9212     Py_RETURN_NONE;
9213 }
9214 
9215 /*[clinic input]
9216 os.closerange
9217 
9218     fd_low: int
9219     fd_high: int
9220     /
9221 
9222 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9223 [clinic start generated code]*/
9224 
9225 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9226 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9227 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9228 {
9229     Py_BEGIN_ALLOW_THREADS
9230     _Py_closerange(fd_low, fd_high - 1);
9231     Py_END_ALLOW_THREADS
9232     Py_RETURN_NONE;
9233 }
9234 
9235 
9236 /*[clinic input]
9237 os.dup -> int
9238 
9239     fd: int
9240     /
9241 
9242 Return a duplicate of a file descriptor.
9243 [clinic start generated code]*/
9244 
9245 static int
os_dup_impl(PyObject * module,int fd)9246 os_dup_impl(PyObject *module, int fd)
9247 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9248 {
9249     return _Py_dup(fd);
9250 }
9251 
9252 
9253 /*[clinic input]
9254 os.dup2 -> int
9255     fd: int
9256     fd2: int
9257     inheritable: bool=True
9258 
9259 Duplicate file descriptor.
9260 [clinic start generated code]*/
9261 
9262 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9263 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9264 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9265 {
9266     int res = 0;
9267 #if defined(HAVE_DUP3) && \
9268     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9269     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9270     static int dup3_works = -1;
9271 #endif
9272 
9273     if (fd < 0 || fd2 < 0) {
9274         posix_error();
9275         return -1;
9276     }
9277 
9278     /* dup2() can fail with EINTR if the target FD is already open, because it
9279      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9280      * upon close(), and therefore below.
9281      */
9282 #ifdef MS_WINDOWS
9283     Py_BEGIN_ALLOW_THREADS
9284     _Py_BEGIN_SUPPRESS_IPH
9285     res = dup2(fd, fd2);
9286     _Py_END_SUPPRESS_IPH
9287     Py_END_ALLOW_THREADS
9288     if (res < 0) {
9289         posix_error();
9290         return -1;
9291     }
9292     res = fd2; // msvcrt dup2 returns 0 on success.
9293 
9294     /* Character files like console cannot be make non-inheritable */
9295     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9296         close(fd2);
9297         return -1;
9298     }
9299 
9300 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9301     Py_BEGIN_ALLOW_THREADS
9302     if (!inheritable)
9303         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9304     else
9305         res = dup2(fd, fd2);
9306     Py_END_ALLOW_THREADS
9307     if (res < 0) {
9308         posix_error();
9309         return -1;
9310     }
9311 
9312 #else
9313 
9314 #ifdef HAVE_DUP3
9315     if (!inheritable && dup3_works != 0) {
9316         Py_BEGIN_ALLOW_THREADS
9317         res = dup3(fd, fd2, O_CLOEXEC);
9318         Py_END_ALLOW_THREADS
9319         if (res < 0) {
9320             if (dup3_works == -1)
9321                 dup3_works = (errno != ENOSYS);
9322             if (dup3_works) {
9323                 posix_error();
9324                 return -1;
9325             }
9326         }
9327     }
9328 
9329     if (inheritable || dup3_works == 0)
9330     {
9331 #endif
9332         Py_BEGIN_ALLOW_THREADS
9333         res = dup2(fd, fd2);
9334         Py_END_ALLOW_THREADS
9335         if (res < 0) {
9336             posix_error();
9337             return -1;
9338         }
9339 
9340         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9341             close(fd2);
9342             return -1;
9343         }
9344 #ifdef HAVE_DUP3
9345     }
9346 #endif
9347 
9348 #endif
9349 
9350     return res;
9351 }
9352 
9353 
9354 #ifdef HAVE_LOCKF
9355 /*[clinic input]
9356 os.lockf
9357 
9358     fd: int
9359         An open file descriptor.
9360     command: int
9361         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9362     length: Py_off_t
9363         The number of bytes to lock, starting at the current position.
9364     /
9365 
9366 Apply, test or remove a POSIX lock on an open file descriptor.
9367 
9368 [clinic start generated code]*/
9369 
9370 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9371 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9372 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9373 {
9374     int res;
9375 
9376     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9377         return NULL;
9378     }
9379 
9380     Py_BEGIN_ALLOW_THREADS
9381     res = lockf(fd, command, length);
9382     Py_END_ALLOW_THREADS
9383 
9384     if (res < 0)
9385         return posix_error();
9386 
9387     Py_RETURN_NONE;
9388 }
9389 #endif /* HAVE_LOCKF */
9390 
9391 
9392 /*[clinic input]
9393 os.lseek -> Py_off_t
9394 
9395     fd: int
9396     position: Py_off_t
9397     how: int
9398     /
9399 
9400 Set the position of a file descriptor.  Return the new position.
9401 
9402 Return the new cursor position in number of bytes
9403 relative to the beginning of the file.
9404 [clinic start generated code]*/
9405 
9406 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9407 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9408 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9409 {
9410     Py_off_t result;
9411 
9412 #ifdef SEEK_SET
9413     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9414     switch (how) {
9415         case 0: how = SEEK_SET; break;
9416         case 1: how = SEEK_CUR; break;
9417         case 2: how = SEEK_END; break;
9418     }
9419 #endif /* SEEK_END */
9420 
9421     Py_BEGIN_ALLOW_THREADS
9422     _Py_BEGIN_SUPPRESS_IPH
9423 #ifdef MS_WINDOWS
9424     result = _lseeki64(fd, position, how);
9425 #else
9426     result = lseek(fd, position, how);
9427 #endif
9428     _Py_END_SUPPRESS_IPH
9429     Py_END_ALLOW_THREADS
9430     if (result < 0)
9431         posix_error();
9432 
9433     return result;
9434 }
9435 
9436 
9437 /*[clinic input]
9438 os.read
9439     fd: int
9440     length: Py_ssize_t
9441     /
9442 
9443 Read from a file descriptor.  Returns a bytes object.
9444 [clinic start generated code]*/
9445 
9446 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9447 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9448 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9449 {
9450     Py_ssize_t n;
9451     PyObject *buffer;
9452 
9453     if (length < 0) {
9454         errno = EINVAL;
9455         return posix_error();
9456     }
9457 
9458     length = Py_MIN(length, _PY_READ_MAX);
9459 
9460     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9461     if (buffer == NULL)
9462         return NULL;
9463 
9464     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9465     if (n == -1) {
9466         Py_DECREF(buffer);
9467         return NULL;
9468     }
9469 
9470     if (n != length)
9471         _PyBytes_Resize(&buffer, n);
9472 
9473     return buffer;
9474 }
9475 
9476 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9477                                 || defined(__APPLE__))) \
9478     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9479     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9480 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9481 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9482 {
9483     Py_ssize_t i, j;
9484 
9485     *iov = PyMem_New(struct iovec, cnt);
9486     if (*iov == NULL) {
9487         PyErr_NoMemory();
9488         return -1;
9489     }
9490 
9491     *buf = PyMem_New(Py_buffer, cnt);
9492     if (*buf == NULL) {
9493         PyMem_Free(*iov);
9494         PyErr_NoMemory();
9495         return -1;
9496     }
9497 
9498     for (i = 0; i < cnt; i++) {
9499         PyObject *item = PySequence_GetItem(seq, i);
9500         if (item == NULL)
9501             goto fail;
9502         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9503             Py_DECREF(item);
9504             goto fail;
9505         }
9506         Py_DECREF(item);
9507         (*iov)[i].iov_base = (*buf)[i].buf;
9508         (*iov)[i].iov_len = (*buf)[i].len;
9509     }
9510     return 0;
9511 
9512 fail:
9513     PyMem_Free(*iov);
9514     for (j = 0; j < i; j++) {
9515         PyBuffer_Release(&(*buf)[j]);
9516     }
9517     PyMem_Free(*buf);
9518     return -1;
9519 }
9520 
9521 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9522 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9523 {
9524     int i;
9525     PyMem_Free(iov);
9526     for (i = 0; i < cnt; i++) {
9527         PyBuffer_Release(&buf[i]);
9528     }
9529     PyMem_Free(buf);
9530 }
9531 #endif
9532 
9533 
9534 #ifdef HAVE_READV
9535 /*[clinic input]
9536 os.readv -> Py_ssize_t
9537 
9538     fd: int
9539     buffers: object
9540     /
9541 
9542 Read from a file descriptor fd into an iterable of buffers.
9543 
9544 The buffers should be mutable buffers accepting bytes.
9545 readv will transfer data into each buffer until it is full
9546 and then move on to the next buffer in the sequence to hold
9547 the rest of the data.
9548 
9549 readv returns the total number of bytes read,
9550 which may be less than the total capacity of all the buffers.
9551 [clinic start generated code]*/
9552 
9553 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9554 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9555 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9556 {
9557     Py_ssize_t cnt, n;
9558     int async_err = 0;
9559     struct iovec *iov;
9560     Py_buffer *buf;
9561 
9562     if (!PySequence_Check(buffers)) {
9563         PyErr_SetString(PyExc_TypeError,
9564             "readv() arg 2 must be a sequence");
9565         return -1;
9566     }
9567 
9568     cnt = PySequence_Size(buffers);
9569     if (cnt < 0)
9570         return -1;
9571 
9572     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9573         return -1;
9574 
9575     do {
9576         Py_BEGIN_ALLOW_THREADS
9577         n = readv(fd, iov, cnt);
9578         Py_END_ALLOW_THREADS
9579     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9580 
9581     iov_cleanup(iov, buf, cnt);
9582     if (n < 0) {
9583         if (!async_err)
9584             posix_error();
9585         return -1;
9586     }
9587 
9588     return n;
9589 }
9590 #endif /* HAVE_READV */
9591 
9592 
9593 #ifdef HAVE_PREAD
9594 /*[clinic input]
9595 os.pread
9596 
9597     fd: int
9598     length: Py_ssize_t
9599     offset: Py_off_t
9600     /
9601 
9602 Read a number of bytes from a file descriptor starting at a particular offset.
9603 
9604 Read length bytes from file descriptor fd, starting at offset bytes from
9605 the beginning of the file.  The file offset remains unchanged.
9606 [clinic start generated code]*/
9607 
9608 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9609 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9610 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9611 {
9612     Py_ssize_t n;
9613     int async_err = 0;
9614     PyObject *buffer;
9615 
9616     if (length < 0) {
9617         errno = EINVAL;
9618         return posix_error();
9619     }
9620     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9621     if (buffer == NULL)
9622         return NULL;
9623 
9624     do {
9625         Py_BEGIN_ALLOW_THREADS
9626         _Py_BEGIN_SUPPRESS_IPH
9627         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9628         _Py_END_SUPPRESS_IPH
9629         Py_END_ALLOW_THREADS
9630     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9631 
9632     if (n < 0) {
9633         Py_DECREF(buffer);
9634         return (!async_err) ? posix_error() : NULL;
9635     }
9636     if (n != length)
9637         _PyBytes_Resize(&buffer, n);
9638     return buffer;
9639 }
9640 #endif /* HAVE_PREAD */
9641 
9642 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9643 /*[clinic input]
9644 os.preadv -> Py_ssize_t
9645 
9646     fd: int
9647     buffers: object
9648     offset: Py_off_t
9649     flags: int = 0
9650     /
9651 
9652 Reads from a file descriptor into a number of mutable bytes-like objects.
9653 
9654 Combines the functionality of readv() and pread(). As readv(), it will
9655 transfer data into each buffer until it is full and then move on to the next
9656 buffer in the sequence to hold the rest of the data. Its fourth argument,
9657 specifies the file offset at which the input operation is to be performed. It
9658 will return the total number of bytes read (which can be less than the total
9659 capacity of all the objects).
9660 
9661 The flags argument contains a bitwise OR of zero or more of the following flags:
9662 
9663 - RWF_HIPRI
9664 - RWF_NOWAIT
9665 
9666 Using non-zero flags requires Linux 4.6 or newer.
9667 [clinic start generated code]*/
9668 
9669 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9670 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9671                int flags)
9672 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9673 {
9674     Py_ssize_t cnt, n;
9675     int async_err = 0;
9676     struct iovec *iov;
9677     Py_buffer *buf;
9678 
9679     if (!PySequence_Check(buffers)) {
9680         PyErr_SetString(PyExc_TypeError,
9681             "preadv2() arg 2 must be a sequence");
9682         return -1;
9683     }
9684 
9685     cnt = PySequence_Size(buffers);
9686     if (cnt < 0) {
9687         return -1;
9688     }
9689 
9690 #ifndef HAVE_PREADV2
9691     if(flags != 0) {
9692         argument_unavailable_error("preadv2", "flags");
9693         return -1;
9694     }
9695 #endif
9696 
9697     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9698         return -1;
9699     }
9700 #ifdef HAVE_PREADV2
9701     do {
9702         Py_BEGIN_ALLOW_THREADS
9703         _Py_BEGIN_SUPPRESS_IPH
9704         n = preadv2(fd, iov, cnt, offset, flags);
9705         _Py_END_SUPPRESS_IPH
9706         Py_END_ALLOW_THREADS
9707     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9708 #else
9709     do {
9710 #ifdef __APPLE__
9711 /* This entire function will be removed from the module dict when the API
9712  * is not available.
9713  */
9714 #pragma clang diagnostic push
9715 #pragma clang diagnostic ignored "-Wunguarded-availability"
9716 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9717 #endif
9718         Py_BEGIN_ALLOW_THREADS
9719         _Py_BEGIN_SUPPRESS_IPH
9720         n = preadv(fd, iov, cnt, offset);
9721         _Py_END_SUPPRESS_IPH
9722         Py_END_ALLOW_THREADS
9723     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9724 
9725 #ifdef __APPLE__
9726 #pragma clang diagnostic pop
9727 #endif
9728 
9729 #endif
9730 
9731     iov_cleanup(iov, buf, cnt);
9732     if (n < 0) {
9733         if (!async_err) {
9734             posix_error();
9735         }
9736         return -1;
9737     }
9738 
9739     return n;
9740 }
9741 #endif /* HAVE_PREADV */
9742 
9743 
9744 /*[clinic input]
9745 os.write -> Py_ssize_t
9746 
9747     fd: int
9748     data: Py_buffer
9749     /
9750 
9751 Write a bytes object to a file descriptor.
9752 [clinic start generated code]*/
9753 
9754 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9755 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9756 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9757 {
9758     return _Py_write(fd, data->buf, data->len);
9759 }
9760 
9761 #ifdef HAVE_SENDFILE
9762 #ifdef __APPLE__
9763 /*[clinic input]
9764 os.sendfile
9765 
9766     out_fd: int
9767     in_fd: int
9768     offset: Py_off_t
9769     count as sbytes: Py_off_t
9770     headers: object(c_default="NULL") = ()
9771     trailers: object(c_default="NULL") = ()
9772     flags: int = 0
9773 
9774 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9775 [clinic start generated code]*/
9776 
9777 static PyObject *
os_sendfile_impl(PyObject * module,int out_fd,int in_fd,Py_off_t offset,Py_off_t sbytes,PyObject * headers,PyObject * trailers,int flags)9778 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9779                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9780                  int flags)
9781 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9782 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9783 /*[clinic input]
9784 os.sendfile
9785 
9786     out_fd: int
9787     in_fd: int
9788     offset: Py_off_t
9789     count: Py_ssize_t
9790     headers: object(c_default="NULL") = ()
9791     trailers: object(c_default="NULL") = ()
9792     flags: int = 0
9793 
9794 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9795 [clinic start generated code]*/
9796 
9797 static PyObject *
9798 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9799                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9800                  int flags)
9801 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9802 #else
9803 /*[clinic input]
9804 os.sendfile
9805 
9806     out_fd: int
9807     in_fd: int
9808     offset as offobj: object
9809     count: Py_ssize_t
9810 
9811 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9812 [clinic start generated code]*/
9813 
9814 static PyObject *
9815 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9816                  Py_ssize_t count)
9817 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9818 #endif
9819 {
9820     Py_ssize_t ret;
9821     int async_err = 0;
9822 
9823 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9824 #ifndef __APPLE__
9825     off_t sbytes;
9826 #endif
9827     Py_buffer *hbuf, *tbuf;
9828     struct sf_hdtr sf;
9829 
9830     sf.headers = NULL;
9831     sf.trailers = NULL;
9832 
9833     if (headers != NULL) {
9834         if (!PySequence_Check(headers)) {
9835             PyErr_SetString(PyExc_TypeError,
9836                 "sendfile() headers must be a sequence");
9837             return NULL;
9838         } else {
9839             Py_ssize_t i = PySequence_Size(headers);
9840             if (i < 0)
9841                 return NULL;
9842             if (i > INT_MAX) {
9843                 PyErr_SetString(PyExc_OverflowError,
9844                     "sendfile() header is too large");
9845                 return NULL;
9846             }
9847             if (i > 0) {
9848                 sf.hdr_cnt = (int)i;
9849                 if (iov_setup(&(sf.headers), &hbuf,
9850                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9851                     return NULL;
9852 #ifdef __APPLE__
9853                 for (i = 0; i < sf.hdr_cnt; i++) {
9854                     Py_ssize_t blen = sf.headers[i].iov_len;
9855 # define OFF_T_MAX 0x7fffffffffffffff
9856                     if (sbytes >= OFF_T_MAX - blen) {
9857                         PyErr_SetString(PyExc_OverflowError,
9858                             "sendfile() header is too large");
9859                         return NULL;
9860                     }
9861                     sbytes += blen;
9862                 }
9863 #endif
9864             }
9865         }
9866     }
9867     if (trailers != NULL) {
9868         if (!PySequence_Check(trailers)) {
9869             PyErr_SetString(PyExc_TypeError,
9870                 "sendfile() trailers must be a sequence");
9871             return NULL;
9872         } else {
9873             Py_ssize_t i = PySequence_Size(trailers);
9874             if (i < 0)
9875                 return NULL;
9876             if (i > INT_MAX) {
9877                 PyErr_SetString(PyExc_OverflowError,
9878                     "sendfile() trailer is too large");
9879                 return NULL;
9880             }
9881             if (i > 0) {
9882                 sf.trl_cnt = (int)i;
9883                 if (iov_setup(&(sf.trailers), &tbuf,
9884                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
9885                     return NULL;
9886             }
9887         }
9888     }
9889 
9890     _Py_BEGIN_SUPPRESS_IPH
9891     do {
9892         Py_BEGIN_ALLOW_THREADS
9893 #ifdef __APPLE__
9894         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
9895 #else
9896         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
9897 #endif
9898         Py_END_ALLOW_THREADS
9899     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9900     _Py_END_SUPPRESS_IPH
9901 
9902     if (sf.headers != NULL)
9903         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
9904     if (sf.trailers != NULL)
9905         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
9906 
9907     if (ret < 0) {
9908         if ((errno == EAGAIN) || (errno == EBUSY)) {
9909             if (sbytes != 0) {
9910                 // some data has been sent
9911                 goto done;
9912             }
9913             else {
9914                 // no data has been sent; upper application is supposed
9915                 // to retry on EAGAIN or EBUSY
9916                 return posix_error();
9917             }
9918         }
9919         return (!async_err) ? posix_error() : NULL;
9920     }
9921     goto done;
9922 
9923 done:
9924     #if !defined(HAVE_LARGEFILE_SUPPORT)
9925         return Py_BuildValue("l", sbytes);
9926     #else
9927         return Py_BuildValue("L", sbytes);
9928     #endif
9929 
9930 #else
9931 #ifdef __linux__
9932     if (offobj == Py_None) {
9933         do {
9934             Py_BEGIN_ALLOW_THREADS
9935             ret = sendfile(out_fd, in_fd, NULL, count);
9936             Py_END_ALLOW_THREADS
9937         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9938         if (ret < 0)
9939             return (!async_err) ? posix_error() : NULL;
9940         return Py_BuildValue("n", ret);
9941     }
9942 #endif
9943     off_t offset;
9944     if (!Py_off_t_converter(offobj, &offset))
9945         return NULL;
9946 
9947 #if defined(__sun) && defined(__SVR4)
9948     // On Solaris, sendfile raises EINVAL rather than returning 0
9949     // when the offset is equal or bigger than the in_fd size.
9950     struct stat st;
9951 
9952     do {
9953         Py_BEGIN_ALLOW_THREADS
9954         ret = fstat(in_fd, &st);
9955         Py_END_ALLOW_THREADS
9956     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9957     if (ret < 0)
9958         return (!async_err) ? posix_error() : NULL;
9959 
9960     if (offset >= st.st_size) {
9961         return Py_BuildValue("i", 0);
9962     }
9963 
9964     // On illumos specifically sendfile() may perform a partial write but
9965     // return -1/an error (in one confirmed case the destination socket
9966     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
9967     // code to check if the offset parameter was modified by sendfile().
9968     //
9969     // We need this variable to track said change.
9970     off_t original_offset = offset;
9971 #endif
9972 
9973     do {
9974         Py_BEGIN_ALLOW_THREADS
9975         ret = sendfile(out_fd, in_fd, &offset, count);
9976 #if defined(__sun) && defined(__SVR4)
9977         // This handles illumos-specific sendfile() partial write behavior,
9978         // see a comment above for more details.
9979         if (ret < 0 && offset != original_offset) {
9980             ret = offset - original_offset;
9981         }
9982 #endif
9983         Py_END_ALLOW_THREADS
9984     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9985     if (ret < 0)
9986         return (!async_err) ? posix_error() : NULL;
9987     return Py_BuildValue("n", ret);
9988 #endif
9989 }
9990 #endif /* HAVE_SENDFILE */
9991 
9992 
9993 #if defined(__APPLE__)
9994 /*[clinic input]
9995 os._fcopyfile
9996 
9997     in_fd: int
9998     out_fd: int
9999     flags: int
10000     /
10001 
10002 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10003 [clinic start generated code]*/
10004 
10005 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10006 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10007 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10008 {
10009     int ret;
10010 
10011     Py_BEGIN_ALLOW_THREADS
10012     ret = fcopyfile(in_fd, out_fd, NULL, flags);
10013     Py_END_ALLOW_THREADS
10014     if (ret < 0)
10015         return posix_error();
10016     Py_RETURN_NONE;
10017 }
10018 #endif
10019 
10020 
10021 /*[clinic input]
10022 os.fstat
10023 
10024     fd : int
10025 
10026 Perform a stat system call on the given file descriptor.
10027 
10028 Like stat(), but for an open file descriptor.
10029 Equivalent to os.stat(fd).
10030 [clinic start generated code]*/
10031 
10032 static PyObject *
os_fstat_impl(PyObject * module,int fd)10033 os_fstat_impl(PyObject *module, int fd)
10034 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10035 {
10036     STRUCT_STAT st;
10037     int res;
10038     int async_err = 0;
10039 
10040     do {
10041         Py_BEGIN_ALLOW_THREADS
10042         res = FSTAT(fd, &st);
10043         Py_END_ALLOW_THREADS
10044     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10045     if (res != 0) {
10046 #ifdef MS_WINDOWS
10047         return PyErr_SetFromWindowsErr(0);
10048 #else
10049         return (!async_err) ? posix_error() : NULL;
10050 #endif
10051     }
10052 
10053     return _pystat_fromstructstat(module, &st);
10054 }
10055 
10056 
10057 /*[clinic input]
10058 os.isatty -> bool
10059     fd: int
10060     /
10061 
10062 Return True if the fd is connected to a terminal.
10063 
10064 Return True if the file descriptor is an open file descriptor
10065 connected to the slave end of a terminal.
10066 [clinic start generated code]*/
10067 
10068 static int
os_isatty_impl(PyObject * module,int fd)10069 os_isatty_impl(PyObject *module, int fd)
10070 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10071 {
10072     int return_value;
10073     Py_BEGIN_ALLOW_THREADS
10074     _Py_BEGIN_SUPPRESS_IPH
10075     return_value = isatty(fd);
10076     _Py_END_SUPPRESS_IPH
10077     Py_END_ALLOW_THREADS
10078     return return_value;
10079 }
10080 
10081 
10082 #ifdef HAVE_PIPE
10083 /*[clinic input]
10084 os.pipe
10085 
10086 Create a pipe.
10087 
10088 Returns a tuple of two file descriptors:
10089   (read_fd, write_fd)
10090 [clinic start generated code]*/
10091 
10092 static PyObject *
os_pipe_impl(PyObject * module)10093 os_pipe_impl(PyObject *module)
10094 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10095 {
10096     int fds[2];
10097 #ifdef MS_WINDOWS
10098     HANDLE read, write;
10099     SECURITY_ATTRIBUTES attr;
10100     BOOL ok;
10101 #else
10102     int res;
10103 #endif
10104 
10105 #ifdef MS_WINDOWS
10106     attr.nLength = sizeof(attr);
10107     attr.lpSecurityDescriptor = NULL;
10108     attr.bInheritHandle = FALSE;
10109 
10110     Py_BEGIN_ALLOW_THREADS
10111     ok = CreatePipe(&read, &write, &attr, 0);
10112     if (ok) {
10113         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10114         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10115         if (fds[0] == -1 || fds[1] == -1) {
10116             CloseHandle(read);
10117             CloseHandle(write);
10118             ok = 0;
10119         }
10120     }
10121     Py_END_ALLOW_THREADS
10122 
10123     if (!ok)
10124         return PyErr_SetFromWindowsErr(0);
10125 #else
10126 
10127 #ifdef HAVE_PIPE2
10128     Py_BEGIN_ALLOW_THREADS
10129     res = pipe2(fds, O_CLOEXEC);
10130     Py_END_ALLOW_THREADS
10131 
10132     if (res != 0 && errno == ENOSYS)
10133     {
10134 #endif
10135         Py_BEGIN_ALLOW_THREADS
10136         res = pipe(fds);
10137         Py_END_ALLOW_THREADS
10138 
10139         if (res == 0) {
10140             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10141                 close(fds[0]);
10142                 close(fds[1]);
10143                 return NULL;
10144             }
10145             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10146                 close(fds[0]);
10147                 close(fds[1]);
10148                 return NULL;
10149             }
10150         }
10151 #ifdef HAVE_PIPE2
10152     }
10153 #endif
10154 
10155     if (res != 0)
10156         return PyErr_SetFromErrno(PyExc_OSError);
10157 #endif /* !MS_WINDOWS */
10158     return Py_BuildValue("(ii)", fds[0], fds[1]);
10159 }
10160 #endif  /* HAVE_PIPE */
10161 
10162 
10163 #ifdef HAVE_PIPE2
10164 /*[clinic input]
10165 os.pipe2
10166 
10167     flags: int
10168     /
10169 
10170 Create a pipe with flags set atomically.
10171 
10172 Returns a tuple of two file descriptors:
10173   (read_fd, write_fd)
10174 
10175 flags can be constructed by ORing together one or more of these values:
10176 O_NONBLOCK, O_CLOEXEC.
10177 [clinic start generated code]*/
10178 
10179 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10180 os_pipe2_impl(PyObject *module, int flags)
10181 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10182 {
10183     int fds[2];
10184     int res;
10185 
10186     res = pipe2(fds, flags);
10187     if (res != 0)
10188         return posix_error();
10189     return Py_BuildValue("(ii)", fds[0], fds[1]);
10190 }
10191 #endif /* HAVE_PIPE2 */
10192 
10193 
10194 #ifdef HAVE_WRITEV
10195 /*[clinic input]
10196 os.writev -> Py_ssize_t
10197     fd: int
10198     buffers: object
10199     /
10200 
10201 Iterate over buffers, and write the contents of each to a file descriptor.
10202 
10203 Returns the total number of bytes written.
10204 buffers must be a sequence of bytes-like objects.
10205 [clinic start generated code]*/
10206 
10207 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10208 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10209 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10210 {
10211     Py_ssize_t cnt;
10212     Py_ssize_t result;
10213     int async_err = 0;
10214     struct iovec *iov;
10215     Py_buffer *buf;
10216 
10217     if (!PySequence_Check(buffers)) {
10218         PyErr_SetString(PyExc_TypeError,
10219             "writev() arg 2 must be a sequence");
10220         return -1;
10221     }
10222     cnt = PySequence_Size(buffers);
10223     if (cnt < 0)
10224         return -1;
10225 
10226     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10227         return -1;
10228     }
10229 
10230     do {
10231         Py_BEGIN_ALLOW_THREADS
10232         result = writev(fd, iov, cnt);
10233         Py_END_ALLOW_THREADS
10234     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10235 
10236     iov_cleanup(iov, buf, cnt);
10237     if (result < 0 && !async_err)
10238         posix_error();
10239 
10240     return result;
10241 }
10242 #endif /* HAVE_WRITEV */
10243 
10244 
10245 #ifdef HAVE_PWRITE
10246 /*[clinic input]
10247 os.pwrite -> Py_ssize_t
10248 
10249     fd: int
10250     buffer: Py_buffer
10251     offset: Py_off_t
10252     /
10253 
10254 Write bytes to a file descriptor starting at a particular offset.
10255 
10256 Write buffer to fd, starting at offset bytes from the beginning of
10257 the file.  Returns the number of bytes writte.  Does not change the
10258 current file offset.
10259 [clinic start generated code]*/
10260 
10261 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10262 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10263 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10264 {
10265     Py_ssize_t size;
10266     int async_err = 0;
10267 
10268     do {
10269         Py_BEGIN_ALLOW_THREADS
10270         _Py_BEGIN_SUPPRESS_IPH
10271         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10272         _Py_END_SUPPRESS_IPH
10273         Py_END_ALLOW_THREADS
10274     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10275 
10276     if (size < 0 && !async_err)
10277         posix_error();
10278     return size;
10279 }
10280 #endif /* HAVE_PWRITE */
10281 
10282 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10283 /*[clinic input]
10284 os.pwritev -> Py_ssize_t
10285 
10286     fd: int
10287     buffers: object
10288     offset: Py_off_t
10289     flags: int = 0
10290     /
10291 
10292 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10293 
10294 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10295 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10296 buffer is written before proceeding to second, and so on. The operating system may
10297 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10298 This function writes the contents of each object to the file descriptor and returns
10299 the total number of bytes written.
10300 
10301 The flags argument contains a bitwise OR of zero or more of the following flags:
10302 
10303 - RWF_DSYNC
10304 - RWF_SYNC
10305 - RWF_APPEND
10306 
10307 Using non-zero flags requires Linux 4.7 or newer.
10308 [clinic start generated code]*/
10309 
10310 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10311 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10312                 int flags)
10313 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10314 {
10315     Py_ssize_t cnt;
10316     Py_ssize_t result;
10317     int async_err = 0;
10318     struct iovec *iov;
10319     Py_buffer *buf;
10320 
10321     if (!PySequence_Check(buffers)) {
10322         PyErr_SetString(PyExc_TypeError,
10323             "pwritev() arg 2 must be a sequence");
10324         return -1;
10325     }
10326 
10327     cnt = PySequence_Size(buffers);
10328     if (cnt < 0) {
10329         return -1;
10330     }
10331 
10332 #ifndef HAVE_PWRITEV2
10333     if(flags != 0) {
10334         argument_unavailable_error("pwritev2", "flags");
10335         return -1;
10336     }
10337 #endif
10338 
10339     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10340         return -1;
10341     }
10342 #ifdef HAVE_PWRITEV2
10343     do {
10344         Py_BEGIN_ALLOW_THREADS
10345         _Py_BEGIN_SUPPRESS_IPH
10346         result = pwritev2(fd, iov, cnt, offset, flags);
10347         _Py_END_SUPPRESS_IPH
10348         Py_END_ALLOW_THREADS
10349     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10350 #else
10351 
10352 #ifdef __APPLE__
10353 /* This entire function will be removed from the module dict when the API
10354  * is not available.
10355  */
10356 #pragma clang diagnostic push
10357 #pragma clang diagnostic ignored "-Wunguarded-availability"
10358 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10359 #endif
10360     do {
10361         Py_BEGIN_ALLOW_THREADS
10362         _Py_BEGIN_SUPPRESS_IPH
10363         result = pwritev(fd, iov, cnt, offset);
10364         _Py_END_SUPPRESS_IPH
10365         Py_END_ALLOW_THREADS
10366     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10367 
10368 #ifdef __APPLE__
10369 #pragma clang diagnostic pop
10370 #endif
10371 
10372 #endif
10373 
10374     iov_cleanup(iov, buf, cnt);
10375     if (result < 0) {
10376         if (!async_err) {
10377             posix_error();
10378         }
10379         return -1;
10380     }
10381 
10382     return result;
10383 }
10384 #endif /* HAVE_PWRITEV */
10385 
10386 #ifdef HAVE_COPY_FILE_RANGE
10387 /*[clinic input]
10388 
10389 os.copy_file_range
10390     src: int
10391         Source file descriptor.
10392     dst: int
10393         Destination file descriptor.
10394     count: Py_ssize_t
10395         Number of bytes to copy.
10396     offset_src: object = None
10397         Starting offset in src.
10398     offset_dst: object = None
10399         Starting offset in dst.
10400 
10401 Copy count bytes from one file descriptor to another.
10402 
10403 If offset_src is None, then src is read from the current position;
10404 respectively for offset_dst.
10405 [clinic start generated code]*/
10406 
10407 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10408 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10409                         PyObject *offset_src, PyObject *offset_dst)
10410 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10411 {
10412     off_t offset_src_val, offset_dst_val;
10413     off_t *p_offset_src = NULL;
10414     off_t *p_offset_dst = NULL;
10415     Py_ssize_t ret;
10416     int async_err = 0;
10417     /* The flags argument is provided to allow
10418      * for future extensions and currently must be to 0. */
10419     int flags = 0;
10420 
10421 
10422     if (count < 0) {
10423         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10424         return NULL;
10425     }
10426 
10427     if (offset_src != Py_None) {
10428         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10429             return NULL;
10430         }
10431         p_offset_src = &offset_src_val;
10432     }
10433 
10434     if (offset_dst != Py_None) {
10435         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10436             return NULL;
10437         }
10438         p_offset_dst = &offset_dst_val;
10439     }
10440 
10441     do {
10442         Py_BEGIN_ALLOW_THREADS
10443         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10444         Py_END_ALLOW_THREADS
10445     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10446 
10447     if (ret < 0) {
10448         return (!async_err) ? posix_error() : NULL;
10449     }
10450 
10451     return PyLong_FromSsize_t(ret);
10452 }
10453 #endif /* HAVE_COPY_FILE_RANGE*/
10454 
10455 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10456 /*[clinic input]
10457 
10458 os.splice
10459     src: int
10460         Source file descriptor.
10461     dst: int
10462         Destination file descriptor.
10463     count: Py_ssize_t
10464         Number of bytes to copy.
10465     offset_src: object = None
10466         Starting offset in src.
10467     offset_dst: object = None
10468         Starting offset in dst.
10469     flags: unsigned_int = 0
10470         Flags to modify the semantics of the call.
10471 
10472 Transfer count bytes from one pipe to a descriptor or vice versa.
10473 
10474 If offset_src is None, then src is read from the current position;
10475 respectively for offset_dst. The offset associated to the file
10476 descriptor that refers to a pipe must be None.
10477 [clinic start generated code]*/
10478 
10479 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10480 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10481                PyObject *offset_src, PyObject *offset_dst,
10482                unsigned int flags)
10483 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10484 {
10485     off_t offset_src_val, offset_dst_val;
10486     off_t *p_offset_src = NULL;
10487     off_t *p_offset_dst = NULL;
10488     Py_ssize_t ret;
10489     int async_err = 0;
10490 
10491     if (count < 0) {
10492         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10493         return NULL;
10494     }
10495 
10496     if (offset_src != Py_None) {
10497         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10498             return NULL;
10499         }
10500         p_offset_src = &offset_src_val;
10501     }
10502 
10503     if (offset_dst != Py_None) {
10504         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10505             return NULL;
10506         }
10507         p_offset_dst = &offset_dst_val;
10508     }
10509 
10510     do {
10511         Py_BEGIN_ALLOW_THREADS
10512         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10513         Py_END_ALLOW_THREADS
10514     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10515 
10516     if (ret < 0) {
10517         return (!async_err) ? posix_error() : NULL;
10518     }
10519 
10520     return PyLong_FromSsize_t(ret);
10521 }
10522 #endif /* HAVE_SPLICE*/
10523 
10524 #ifdef HAVE_MKFIFO
10525 /*[clinic input]
10526 os.mkfifo
10527 
10528     path: path_t
10529     mode: int=0o666
10530     *
10531     dir_fd: dir_fd(requires='mkfifoat')=None
10532 
10533 Create a "fifo" (a POSIX named pipe).
10534 
10535 If dir_fd is not None, it should be a file descriptor open to a directory,
10536   and path should be relative; path will then be relative to that directory.
10537 dir_fd may not be implemented on your platform.
10538   If it is unavailable, using it will raise a NotImplementedError.
10539 [clinic start generated code]*/
10540 
10541 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10542 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10543 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10544 {
10545     int result;
10546     int async_err = 0;
10547 
10548     do {
10549         Py_BEGIN_ALLOW_THREADS
10550 #ifdef HAVE_MKFIFOAT
10551         if (dir_fd != DEFAULT_DIR_FD)
10552             result = mkfifoat(dir_fd, path->narrow, mode);
10553         else
10554 #endif
10555             result = mkfifo(path->narrow, mode);
10556         Py_END_ALLOW_THREADS
10557     } while (result != 0 && errno == EINTR &&
10558              !(async_err = PyErr_CheckSignals()));
10559     if (result != 0)
10560         return (!async_err) ? posix_error() : NULL;
10561 
10562     Py_RETURN_NONE;
10563 }
10564 #endif /* HAVE_MKFIFO */
10565 
10566 
10567 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10568 /*[clinic input]
10569 os.mknod
10570 
10571     path: path_t
10572     mode: int=0o600
10573     device: dev_t=0
10574     *
10575     dir_fd: dir_fd(requires='mknodat')=None
10576 
10577 Create a node in the file system.
10578 
10579 Create a node in the file system (file, device special file or named pipe)
10580 at path.  mode specifies both the permissions to use and the
10581 type of node to be created, being combined (bitwise OR) with one of
10582 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10583 device defines the newly created device special file (probably using
10584 os.makedev()).  Otherwise device is ignored.
10585 
10586 If dir_fd is not None, it should be a file descriptor open to a directory,
10587   and path should be relative; path will then be relative to that directory.
10588 dir_fd may not be implemented on your platform.
10589   If it is unavailable, using it will raise a NotImplementedError.
10590 [clinic start generated code]*/
10591 
10592 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10593 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10594               int dir_fd)
10595 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10596 {
10597     int result;
10598     int async_err = 0;
10599 
10600     do {
10601         Py_BEGIN_ALLOW_THREADS
10602 #ifdef HAVE_MKNODAT
10603         if (dir_fd != DEFAULT_DIR_FD)
10604             result = mknodat(dir_fd, path->narrow, mode, device);
10605         else
10606 #endif
10607             result = mknod(path->narrow, mode, device);
10608         Py_END_ALLOW_THREADS
10609     } while (result != 0 && errno == EINTR &&
10610              !(async_err = PyErr_CheckSignals()));
10611     if (result != 0)
10612         return (!async_err) ? posix_error() : NULL;
10613 
10614     Py_RETURN_NONE;
10615 }
10616 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10617 
10618 
10619 #ifdef HAVE_DEVICE_MACROS
10620 /*[clinic input]
10621 os.major -> unsigned_int
10622 
10623     device: dev_t
10624     /
10625 
10626 Extracts a device major number from a raw device number.
10627 [clinic start generated code]*/
10628 
10629 static unsigned int
os_major_impl(PyObject * module,dev_t device)10630 os_major_impl(PyObject *module, dev_t device)
10631 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10632 {
10633     return major(device);
10634 }
10635 
10636 
10637 /*[clinic input]
10638 os.minor -> unsigned_int
10639 
10640     device: dev_t
10641     /
10642 
10643 Extracts a device minor number from a raw device number.
10644 [clinic start generated code]*/
10645 
10646 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10647 os_minor_impl(PyObject *module, dev_t device)
10648 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10649 {
10650     return minor(device);
10651 }
10652 
10653 
10654 /*[clinic input]
10655 os.makedev -> dev_t
10656 
10657     major: int
10658     minor: int
10659     /
10660 
10661 Composes a raw device number from the major and minor device numbers.
10662 [clinic start generated code]*/
10663 
10664 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10665 os_makedev_impl(PyObject *module, int major, int minor)
10666 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10667 {
10668     return makedev(major, minor);
10669 }
10670 #endif /* HAVE_DEVICE_MACROS */
10671 
10672 
10673 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10674 /*[clinic input]
10675 os.ftruncate
10676 
10677     fd: int
10678     length: Py_off_t
10679     /
10680 
10681 Truncate a file, specified by file descriptor, to a specific length.
10682 [clinic start generated code]*/
10683 
10684 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10685 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10686 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10687 {
10688     int result;
10689     int async_err = 0;
10690 
10691     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10692         return NULL;
10693     }
10694 
10695     do {
10696         Py_BEGIN_ALLOW_THREADS
10697         _Py_BEGIN_SUPPRESS_IPH
10698 #ifdef MS_WINDOWS
10699         result = _chsize_s(fd, length);
10700 #else
10701         result = ftruncate(fd, length);
10702 #endif
10703         _Py_END_SUPPRESS_IPH
10704         Py_END_ALLOW_THREADS
10705     } while (result != 0 && errno == EINTR &&
10706              !(async_err = PyErr_CheckSignals()));
10707     if (result != 0)
10708         return (!async_err) ? posix_error() : NULL;
10709     Py_RETURN_NONE;
10710 }
10711 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10712 
10713 
10714 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10715 /*[clinic input]
10716 os.truncate
10717     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10718     length: Py_off_t
10719 
10720 Truncate a file, specified by path, to a specific length.
10721 
10722 On some platforms, path may also be specified as an open file descriptor.
10723   If this functionality is unavailable, using it raises an exception.
10724 [clinic start generated code]*/
10725 
10726 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10727 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10728 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10729 {
10730     int result;
10731 #ifdef MS_WINDOWS
10732     int fd;
10733 #endif
10734 
10735     if (path->fd != -1)
10736         return os_ftruncate_impl(module, path->fd, length);
10737 
10738     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10739         return NULL;
10740     }
10741 
10742     Py_BEGIN_ALLOW_THREADS
10743     _Py_BEGIN_SUPPRESS_IPH
10744 #ifdef MS_WINDOWS
10745     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10746     if (fd < 0)
10747         result = -1;
10748     else {
10749         result = _chsize_s(fd, length);
10750         close(fd);
10751         if (result < 0)
10752             errno = result;
10753     }
10754 #else
10755     result = truncate(path->narrow, length);
10756 #endif
10757     _Py_END_SUPPRESS_IPH
10758     Py_END_ALLOW_THREADS
10759     if (result < 0)
10760         return posix_path_error(path);
10761 
10762     Py_RETURN_NONE;
10763 }
10764 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10765 
10766 
10767 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10768    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10769    defined, which is the case in Python on AIX. AIX bug report:
10770    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10771 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10772 #  define POSIX_FADVISE_AIX_BUG
10773 #endif
10774 
10775 
10776 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10777 /*[clinic input]
10778 os.posix_fallocate
10779 
10780     fd: int
10781     offset: Py_off_t
10782     length: Py_off_t
10783     /
10784 
10785 Ensure a file has allocated at least a particular number of bytes on disk.
10786 
10787 Ensure that the file specified by fd encompasses a range of bytes
10788 starting at offset bytes from the beginning and continuing for length bytes.
10789 [clinic start generated code]*/
10790 
10791 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10792 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10793                         Py_off_t length)
10794 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10795 {
10796     int result;
10797     int async_err = 0;
10798 
10799     do {
10800         Py_BEGIN_ALLOW_THREADS
10801         result = posix_fallocate(fd, offset, length);
10802         Py_END_ALLOW_THREADS
10803     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10804 
10805     if (result == 0)
10806         Py_RETURN_NONE;
10807 
10808     if (async_err)
10809         return NULL;
10810 
10811     errno = result;
10812     return posix_error();
10813 }
10814 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10815 
10816 
10817 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10818 /*[clinic input]
10819 os.posix_fadvise
10820 
10821     fd: int
10822     offset: Py_off_t
10823     length: Py_off_t
10824     advice: int
10825     /
10826 
10827 Announce an intention to access data in a specific pattern.
10828 
10829 Announce an intention to access data in a specific pattern, thus allowing
10830 the kernel to make optimizations.
10831 The advice applies to the region of the file specified by fd starting at
10832 offset and continuing for length bytes.
10833 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10834 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10835 POSIX_FADV_DONTNEED.
10836 [clinic start generated code]*/
10837 
10838 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10839 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10840                       Py_off_t length, int advice)
10841 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10842 {
10843     int result;
10844     int async_err = 0;
10845 
10846     do {
10847         Py_BEGIN_ALLOW_THREADS
10848         result = posix_fadvise(fd, offset, length, advice);
10849         Py_END_ALLOW_THREADS
10850     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10851 
10852     if (result == 0)
10853         Py_RETURN_NONE;
10854 
10855     if (async_err)
10856         return NULL;
10857 
10858     errno = result;
10859     return posix_error();
10860 }
10861 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
10862 
10863 
10864 #ifdef MS_WINDOWS
10865 static PyObject*
win32_putenv(PyObject * name,PyObject * value)10866 win32_putenv(PyObject *name, PyObject *value)
10867 {
10868     /* Search from index 1 because on Windows starting '=' is allowed for
10869        defining hidden environment variables. */
10870     if (PyUnicode_GET_LENGTH(name) == 0 ||
10871         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
10872     {
10873         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10874         return NULL;
10875     }
10876     PyObject *unicode;
10877     if (value != NULL) {
10878         unicode = PyUnicode_FromFormat("%U=%U", name, value);
10879     }
10880     else {
10881         unicode = PyUnicode_FromFormat("%U=", name);
10882     }
10883     if (unicode == NULL) {
10884         return NULL;
10885     }
10886 
10887     Py_ssize_t size;
10888     /* PyUnicode_AsWideCharString() rejects embedded null characters */
10889     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
10890     Py_DECREF(unicode);
10891 
10892     if (env == NULL) {
10893         return NULL;
10894     }
10895     if (size > _MAX_ENV) {
10896         PyErr_Format(PyExc_ValueError,
10897                      "the environment variable is longer than %u characters",
10898                      _MAX_ENV);
10899         PyMem_Free(env);
10900         return NULL;
10901     }
10902 
10903     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
10904        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
10905        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
10906 
10907        Prefer _wputenv() to be compatible with C libraries using CRT
10908        variables and CRT functions using these variables (ex: getenv()). */
10909     int err = _wputenv(env);
10910     PyMem_Free(env);
10911 
10912     if (err) {
10913         posix_error();
10914         return NULL;
10915     }
10916 
10917     Py_RETURN_NONE;
10918 }
10919 #endif
10920 
10921 
10922 #ifdef MS_WINDOWS
10923 /*[clinic input]
10924 os.putenv
10925 
10926     name: unicode
10927     value: unicode
10928     /
10929 
10930 Change or add an environment variable.
10931 [clinic start generated code]*/
10932 
10933 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10934 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10935 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
10936 {
10937     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10938         return NULL;
10939     }
10940     return win32_putenv(name, value);
10941 }
10942 #else
10943 /*[clinic input]
10944 os.putenv
10945 
10946     name: FSConverter
10947     value: FSConverter
10948     /
10949 
10950 Change or add an environment variable.
10951 [clinic start generated code]*/
10952 
10953 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)10954 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
10955 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
10956 {
10957     const char *name_string = PyBytes_AS_STRING(name);
10958     const char *value_string = PyBytes_AS_STRING(value);
10959 
10960     if (strchr(name_string, '=') != NULL) {
10961         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
10962         return NULL;
10963     }
10964 
10965     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
10966         return NULL;
10967     }
10968 
10969     if (setenv(name_string, value_string, 1)) {
10970         return posix_error();
10971     }
10972     Py_RETURN_NONE;
10973 }
10974 #endif  /* !defined(MS_WINDOWS) */
10975 
10976 
10977 #ifdef MS_WINDOWS
10978 /*[clinic input]
10979 os.unsetenv
10980     name: unicode
10981     /
10982 
10983 Delete an environment variable.
10984 [clinic start generated code]*/
10985 
10986 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)10987 os_unsetenv_impl(PyObject *module, PyObject *name)
10988 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
10989 {
10990     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
10991         return NULL;
10992     }
10993     return win32_putenv(name, NULL);
10994 }
10995 #else
10996 /*[clinic input]
10997 os.unsetenv
10998     name: FSConverter
10999     /
11000 
11001 Delete an environment variable.
11002 [clinic start generated code]*/
11003 
11004 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11005 os_unsetenv_impl(PyObject *module, PyObject *name)
11006 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11007 {
11008     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11009         return NULL;
11010     }
11011 #ifdef HAVE_BROKEN_UNSETENV
11012     unsetenv(PyBytes_AS_STRING(name));
11013 #else
11014     int err = unsetenv(PyBytes_AS_STRING(name));
11015     if (err) {
11016         return posix_error();
11017     }
11018 #endif
11019 
11020     Py_RETURN_NONE;
11021 }
11022 #endif /* !MS_WINDOWS */
11023 
11024 
11025 /*[clinic input]
11026 os.strerror
11027 
11028     code: int
11029     /
11030 
11031 Translate an error code to a message string.
11032 [clinic start generated code]*/
11033 
11034 static PyObject *
os_strerror_impl(PyObject * module,int code)11035 os_strerror_impl(PyObject *module, int code)
11036 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11037 {
11038     char *message = strerror(code);
11039     if (message == NULL) {
11040         PyErr_SetString(PyExc_ValueError,
11041                         "strerror() argument out of range");
11042         return NULL;
11043     }
11044     return PyUnicode_DecodeLocale(message, "surrogateescape");
11045 }
11046 
11047 
11048 #ifdef HAVE_SYS_WAIT_H
11049 #ifdef WCOREDUMP
11050 /*[clinic input]
11051 os.WCOREDUMP -> bool
11052 
11053     status: int
11054     /
11055 
11056 Return True if the process returning status was dumped to a core file.
11057 [clinic start generated code]*/
11058 
11059 static int
os_WCOREDUMP_impl(PyObject * module,int status)11060 os_WCOREDUMP_impl(PyObject *module, int status)
11061 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11062 {
11063     WAIT_TYPE wait_status;
11064     WAIT_STATUS_INT(wait_status) = status;
11065     return WCOREDUMP(wait_status);
11066 }
11067 #endif /* WCOREDUMP */
11068 
11069 
11070 #ifdef WIFCONTINUED
11071 /*[clinic input]
11072 os.WIFCONTINUED -> bool
11073 
11074     status: int
11075 
11076 Return True if a particular process was continued from a job control stop.
11077 
11078 Return True if the process returning status was continued from a
11079 job control stop.
11080 [clinic start generated code]*/
11081 
11082 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11083 os_WIFCONTINUED_impl(PyObject *module, int status)
11084 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11085 {
11086     WAIT_TYPE wait_status;
11087     WAIT_STATUS_INT(wait_status) = status;
11088     return WIFCONTINUED(wait_status);
11089 }
11090 #endif /* WIFCONTINUED */
11091 
11092 
11093 #ifdef WIFSTOPPED
11094 /*[clinic input]
11095 os.WIFSTOPPED -> bool
11096 
11097     status: int
11098 
11099 Return True if the process returning status was stopped.
11100 [clinic start generated code]*/
11101 
11102 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11103 os_WIFSTOPPED_impl(PyObject *module, int status)
11104 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11105 {
11106     WAIT_TYPE wait_status;
11107     WAIT_STATUS_INT(wait_status) = status;
11108     return WIFSTOPPED(wait_status);
11109 }
11110 #endif /* WIFSTOPPED */
11111 
11112 
11113 #ifdef WIFSIGNALED
11114 /*[clinic input]
11115 os.WIFSIGNALED -> bool
11116 
11117     status: int
11118 
11119 Return True if the process returning status was terminated by a signal.
11120 [clinic start generated code]*/
11121 
11122 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11123 os_WIFSIGNALED_impl(PyObject *module, int status)
11124 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11125 {
11126     WAIT_TYPE wait_status;
11127     WAIT_STATUS_INT(wait_status) = status;
11128     return WIFSIGNALED(wait_status);
11129 }
11130 #endif /* WIFSIGNALED */
11131 
11132 
11133 #ifdef WIFEXITED
11134 /*[clinic input]
11135 os.WIFEXITED -> bool
11136 
11137     status: int
11138 
11139 Return True if the process returning status exited via the exit() system call.
11140 [clinic start generated code]*/
11141 
11142 static int
os_WIFEXITED_impl(PyObject * module,int status)11143 os_WIFEXITED_impl(PyObject *module, int status)
11144 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11145 {
11146     WAIT_TYPE wait_status;
11147     WAIT_STATUS_INT(wait_status) = status;
11148     return WIFEXITED(wait_status);
11149 }
11150 #endif /* WIFEXITED */
11151 
11152 
11153 #ifdef WEXITSTATUS
11154 /*[clinic input]
11155 os.WEXITSTATUS -> int
11156 
11157     status: int
11158 
11159 Return the process return code from status.
11160 [clinic start generated code]*/
11161 
11162 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11163 os_WEXITSTATUS_impl(PyObject *module, int status)
11164 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11165 {
11166     WAIT_TYPE wait_status;
11167     WAIT_STATUS_INT(wait_status) = status;
11168     return WEXITSTATUS(wait_status);
11169 }
11170 #endif /* WEXITSTATUS */
11171 
11172 
11173 #ifdef WTERMSIG
11174 /*[clinic input]
11175 os.WTERMSIG -> int
11176 
11177     status: int
11178 
11179 Return the signal that terminated the process that provided the status value.
11180 [clinic start generated code]*/
11181 
11182 static int
os_WTERMSIG_impl(PyObject * module,int status)11183 os_WTERMSIG_impl(PyObject *module, int status)
11184 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11185 {
11186     WAIT_TYPE wait_status;
11187     WAIT_STATUS_INT(wait_status) = status;
11188     return WTERMSIG(wait_status);
11189 }
11190 #endif /* WTERMSIG */
11191 
11192 
11193 #ifdef WSTOPSIG
11194 /*[clinic input]
11195 os.WSTOPSIG -> int
11196 
11197     status: int
11198 
11199 Return the signal that stopped the process that provided the status value.
11200 [clinic start generated code]*/
11201 
11202 static int
os_WSTOPSIG_impl(PyObject * module,int status)11203 os_WSTOPSIG_impl(PyObject *module, int status)
11204 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11205 {
11206     WAIT_TYPE wait_status;
11207     WAIT_STATUS_INT(wait_status) = status;
11208     return WSTOPSIG(wait_status);
11209 }
11210 #endif /* WSTOPSIG */
11211 #endif /* HAVE_SYS_WAIT_H */
11212 
11213 
11214 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11215 #ifdef _SCO_DS
11216 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11217    needed definitions in sys/statvfs.h */
11218 #define _SVID3
11219 #endif
11220 #include <sys/statvfs.h>
11221 
11222 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11223 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11224     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11225     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11226     if (v == NULL)
11227         return NULL;
11228 
11229 #if !defined(HAVE_LARGEFILE_SUPPORT)
11230     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11231     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11232     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11233     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11234     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11235     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11236     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11237     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11238     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11239     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11240 #else
11241     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11242     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11243     PyStructSequence_SET_ITEM(v, 2,
11244                               PyLong_FromLongLong((long long) st.f_blocks));
11245     PyStructSequence_SET_ITEM(v, 3,
11246                               PyLong_FromLongLong((long long) st.f_bfree));
11247     PyStructSequence_SET_ITEM(v, 4,
11248                               PyLong_FromLongLong((long long) st.f_bavail));
11249     PyStructSequence_SET_ITEM(v, 5,
11250                               PyLong_FromLongLong((long long) st.f_files));
11251     PyStructSequence_SET_ITEM(v, 6,
11252                               PyLong_FromLongLong((long long) st.f_ffree));
11253     PyStructSequence_SET_ITEM(v, 7,
11254                               PyLong_FromLongLong((long long) st.f_favail));
11255     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11256     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11257 #endif
11258 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11259  * (issue #32390). */
11260 #if defined(_AIX) && defined(_ALL_SOURCE)
11261     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11262 #else
11263     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11264 #endif
11265     if (PyErr_Occurred()) {
11266         Py_DECREF(v);
11267         return NULL;
11268     }
11269 
11270     return v;
11271 }
11272 
11273 
11274 /*[clinic input]
11275 os.fstatvfs
11276     fd: int
11277     /
11278 
11279 Perform an fstatvfs system call on the given fd.
11280 
11281 Equivalent to statvfs(fd).
11282 [clinic start generated code]*/
11283 
11284 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11285 os_fstatvfs_impl(PyObject *module, int fd)
11286 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11287 {
11288     int result;
11289     int async_err = 0;
11290     struct statvfs st;
11291 
11292     do {
11293         Py_BEGIN_ALLOW_THREADS
11294         result = fstatvfs(fd, &st);
11295         Py_END_ALLOW_THREADS
11296     } while (result != 0 && errno == EINTR &&
11297              !(async_err = PyErr_CheckSignals()));
11298     if (result != 0)
11299         return (!async_err) ? posix_error() : NULL;
11300 
11301     return _pystatvfs_fromstructstatvfs(module, st);
11302 }
11303 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11304 
11305 
11306 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11307 #include <sys/statvfs.h>
11308 /*[clinic input]
11309 os.statvfs
11310 
11311     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11312 
11313 Perform a statvfs system call on the given path.
11314 
11315 path may always be specified as a string.
11316 On some platforms, path may also be specified as an open file descriptor.
11317   If this functionality is unavailable, using it raises an exception.
11318 [clinic start generated code]*/
11319 
11320 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11321 os_statvfs_impl(PyObject *module, path_t *path)
11322 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11323 {
11324     int result;
11325     struct statvfs st;
11326 
11327     Py_BEGIN_ALLOW_THREADS
11328 #ifdef HAVE_FSTATVFS
11329     if (path->fd != -1) {
11330         result = fstatvfs(path->fd, &st);
11331     }
11332     else
11333 #endif
11334         result = statvfs(path->narrow, &st);
11335     Py_END_ALLOW_THREADS
11336 
11337     if (result) {
11338         return path_error(path);
11339     }
11340 
11341     return _pystatvfs_fromstructstatvfs(module, st);
11342 }
11343 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11344 
11345 
11346 #ifdef MS_WINDOWS
11347 /*[clinic input]
11348 os._getdiskusage
11349 
11350     path: path_t
11351 
11352 Return disk usage statistics about the given path as a (total, free) tuple.
11353 [clinic start generated code]*/
11354 
11355 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11356 os__getdiskusage_impl(PyObject *module, path_t *path)
11357 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11358 {
11359     BOOL retval;
11360     ULARGE_INTEGER _, total, free;
11361     DWORD err = 0;
11362 
11363     Py_BEGIN_ALLOW_THREADS
11364     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11365     Py_END_ALLOW_THREADS
11366     if (retval == 0) {
11367         if (GetLastError() == ERROR_DIRECTORY) {
11368             wchar_t *dir_path = NULL;
11369 
11370             dir_path = PyMem_New(wchar_t, path->length + 1);
11371             if (dir_path == NULL) {
11372                 return PyErr_NoMemory();
11373             }
11374 
11375             wcscpy_s(dir_path, path->length + 1, path->wide);
11376 
11377             if (_dirnameW(dir_path) != -1) {
11378                 Py_BEGIN_ALLOW_THREADS
11379                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11380                 Py_END_ALLOW_THREADS
11381             }
11382             /* Record the last error in case it's modified by PyMem_Free. */
11383             err = GetLastError();
11384             PyMem_Free(dir_path);
11385             if (retval) {
11386                 goto success;
11387             }
11388         }
11389         return PyErr_SetFromWindowsErr(err);
11390     }
11391 
11392 success:
11393     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11394 }
11395 #endif /* MS_WINDOWS */
11396 
11397 
11398 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11399  * It maps strings representing configuration variable names to
11400  * integer values, allowing those functions to be called with the
11401  * magic names instead of polluting the module's namespace with tons of
11402  * rarely-used constants.  There are three separate tables that use
11403  * these definitions.
11404  *
11405  * This code is always included, even if none of the interfaces that
11406  * need it are included.  The #if hackery needed to avoid it would be
11407  * sufficiently pervasive that it's not worth the loss of readability.
11408  */
11409 struct constdef {
11410     const char *name;
11411     int value;
11412 };
11413 
11414 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11415 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11416               size_t tablesize)
11417 {
11418     if (PyLong_Check(arg)) {
11419         int value = _PyLong_AsInt(arg);
11420         if (value == -1 && PyErr_Occurred())
11421             return 0;
11422         *valuep = value;
11423         return 1;
11424     }
11425     else {
11426         /* look up the value in the table using a binary search */
11427         size_t lo = 0;
11428         size_t mid;
11429         size_t hi = tablesize;
11430         int cmp;
11431         const char *confname;
11432         if (!PyUnicode_Check(arg)) {
11433             PyErr_SetString(PyExc_TypeError,
11434                 "configuration names must be strings or integers");
11435             return 0;
11436         }
11437         confname = PyUnicode_AsUTF8(arg);
11438         if (confname == NULL)
11439             return 0;
11440         while (lo < hi) {
11441             mid = (lo + hi) / 2;
11442             cmp = strcmp(confname, table[mid].name);
11443             if (cmp < 0)
11444                 hi = mid;
11445             else if (cmp > 0)
11446                 lo = mid + 1;
11447             else {
11448                 *valuep = table[mid].value;
11449                 return 1;
11450             }
11451         }
11452         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11453         return 0;
11454     }
11455 }
11456 
11457 
11458 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11459 static struct constdef  posix_constants_pathconf[] = {
11460 #ifdef _PC_ABI_AIO_XFER_MAX
11461     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11462 #endif
11463 #ifdef _PC_ABI_ASYNC_IO
11464     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11465 #endif
11466 #ifdef _PC_ASYNC_IO
11467     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11468 #endif
11469 #ifdef _PC_CHOWN_RESTRICTED
11470     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11471 #endif
11472 #ifdef _PC_FILESIZEBITS
11473     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11474 #endif
11475 #ifdef _PC_LAST
11476     {"PC_LAST", _PC_LAST},
11477 #endif
11478 #ifdef _PC_LINK_MAX
11479     {"PC_LINK_MAX",     _PC_LINK_MAX},
11480 #endif
11481 #ifdef _PC_MAX_CANON
11482     {"PC_MAX_CANON",    _PC_MAX_CANON},
11483 #endif
11484 #ifdef _PC_MAX_INPUT
11485     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11486 #endif
11487 #ifdef _PC_NAME_MAX
11488     {"PC_NAME_MAX",     _PC_NAME_MAX},
11489 #endif
11490 #ifdef _PC_NO_TRUNC
11491     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11492 #endif
11493 #ifdef _PC_PATH_MAX
11494     {"PC_PATH_MAX",     _PC_PATH_MAX},
11495 #endif
11496 #ifdef _PC_PIPE_BUF
11497     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11498 #endif
11499 #ifdef _PC_PRIO_IO
11500     {"PC_PRIO_IO",      _PC_PRIO_IO},
11501 #endif
11502 #ifdef _PC_SOCK_MAXBUF
11503     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11504 #endif
11505 #ifdef _PC_SYNC_IO
11506     {"PC_SYNC_IO",      _PC_SYNC_IO},
11507 #endif
11508 #ifdef _PC_VDISABLE
11509     {"PC_VDISABLE",     _PC_VDISABLE},
11510 #endif
11511 #ifdef _PC_ACL_ENABLED
11512     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11513 #endif
11514 #ifdef _PC_MIN_HOLE_SIZE
11515     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11516 #endif
11517 #ifdef _PC_ALLOC_SIZE_MIN
11518     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11519 #endif
11520 #ifdef _PC_REC_INCR_XFER_SIZE
11521     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11522 #endif
11523 #ifdef _PC_REC_MAX_XFER_SIZE
11524     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11525 #endif
11526 #ifdef _PC_REC_MIN_XFER_SIZE
11527     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11528 #endif
11529 #ifdef _PC_REC_XFER_ALIGN
11530     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11531 #endif
11532 #ifdef _PC_SYMLINK_MAX
11533     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11534 #endif
11535 #ifdef _PC_XATTR_ENABLED
11536     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11537 #endif
11538 #ifdef _PC_XATTR_EXISTS
11539     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11540 #endif
11541 #ifdef _PC_TIMESTAMP_RESOLUTION
11542     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11543 #endif
11544 };
11545 
11546 static int
conv_path_confname(PyObject * arg,int * valuep)11547 conv_path_confname(PyObject *arg, int *valuep)
11548 {
11549     return conv_confname(arg, valuep, posix_constants_pathconf,
11550                          sizeof(posix_constants_pathconf)
11551                            / sizeof(struct constdef));
11552 }
11553 #endif
11554 
11555 
11556 #ifdef HAVE_FPATHCONF
11557 /*[clinic input]
11558 os.fpathconf -> long
11559 
11560     fd: fildes
11561     name: path_confname
11562     /
11563 
11564 Return the configuration limit name for the file descriptor fd.
11565 
11566 If there is no limit, return -1.
11567 [clinic start generated code]*/
11568 
11569 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11570 os_fpathconf_impl(PyObject *module, int fd, int name)
11571 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11572 {
11573     long limit;
11574 
11575     errno = 0;
11576     limit = fpathconf(fd, name);
11577     if (limit == -1 && errno != 0)
11578         posix_error();
11579 
11580     return limit;
11581 }
11582 #endif /* HAVE_FPATHCONF */
11583 
11584 
11585 #ifdef HAVE_PATHCONF
11586 /*[clinic input]
11587 os.pathconf -> long
11588     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11589     name: path_confname
11590 
11591 Return the configuration limit name for the file or directory path.
11592 
11593 If there is no limit, return -1.
11594 On some platforms, path may also be specified as an open file descriptor.
11595   If this functionality is unavailable, using it raises an exception.
11596 [clinic start generated code]*/
11597 
11598 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11599 os_pathconf_impl(PyObject *module, path_t *path, int name)
11600 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11601 {
11602     long limit;
11603 
11604     errno = 0;
11605 #ifdef HAVE_FPATHCONF
11606     if (path->fd != -1)
11607         limit = fpathconf(path->fd, name);
11608     else
11609 #endif
11610         limit = pathconf(path->narrow, name);
11611     if (limit == -1 && errno != 0) {
11612         if (errno == EINVAL)
11613             /* could be a path or name problem */
11614             posix_error();
11615         else
11616             path_error(path);
11617     }
11618 
11619     return limit;
11620 }
11621 #endif /* HAVE_PATHCONF */
11622 
11623 #ifdef HAVE_CONFSTR
11624 static struct constdef posix_constants_confstr[] = {
11625 #ifdef _CS_ARCHITECTURE
11626     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11627 #endif
11628 #ifdef _CS_GNU_LIBC_VERSION
11629     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11630 #endif
11631 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11632     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11633 #endif
11634 #ifdef _CS_HOSTNAME
11635     {"CS_HOSTNAME",     _CS_HOSTNAME},
11636 #endif
11637 #ifdef _CS_HW_PROVIDER
11638     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11639 #endif
11640 #ifdef _CS_HW_SERIAL
11641     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11642 #endif
11643 #ifdef _CS_INITTAB_NAME
11644     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11645 #endif
11646 #ifdef _CS_LFS64_CFLAGS
11647     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11648 #endif
11649 #ifdef _CS_LFS64_LDFLAGS
11650     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11651 #endif
11652 #ifdef _CS_LFS64_LIBS
11653     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11654 #endif
11655 #ifdef _CS_LFS64_LINTFLAGS
11656     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11657 #endif
11658 #ifdef _CS_LFS_CFLAGS
11659     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11660 #endif
11661 #ifdef _CS_LFS_LDFLAGS
11662     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11663 #endif
11664 #ifdef _CS_LFS_LIBS
11665     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11666 #endif
11667 #ifdef _CS_LFS_LINTFLAGS
11668     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11669 #endif
11670 #ifdef _CS_MACHINE
11671     {"CS_MACHINE",      _CS_MACHINE},
11672 #endif
11673 #ifdef _CS_PATH
11674     {"CS_PATH", _CS_PATH},
11675 #endif
11676 #ifdef _CS_RELEASE
11677     {"CS_RELEASE",      _CS_RELEASE},
11678 #endif
11679 #ifdef _CS_SRPC_DOMAIN
11680     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11681 #endif
11682 #ifdef _CS_SYSNAME
11683     {"CS_SYSNAME",      _CS_SYSNAME},
11684 #endif
11685 #ifdef _CS_VERSION
11686     {"CS_VERSION",      _CS_VERSION},
11687 #endif
11688 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11689     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11690 #endif
11691 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11692     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11693 #endif
11694 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11695     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11696 #endif
11697 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11698     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11699 #endif
11700 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11701     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11702 #endif
11703 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11704     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11705 #endif
11706 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11707     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11708 #endif
11709 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11710     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11711 #endif
11712 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11713     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11714 #endif
11715 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11716     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11717 #endif
11718 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11719     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11720 #endif
11721 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11722     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11723 #endif
11724 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11725     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11726 #endif
11727 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11728     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11729 #endif
11730 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11731     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11732 #endif
11733 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11734     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11735 #endif
11736 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11737     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11738 #endif
11739 #ifdef _MIPS_CS_BASE
11740     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11741 #endif
11742 #ifdef _MIPS_CS_HOSTID
11743     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11744 #endif
11745 #ifdef _MIPS_CS_HW_NAME
11746     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11747 #endif
11748 #ifdef _MIPS_CS_NUM_PROCESSORS
11749     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11750 #endif
11751 #ifdef _MIPS_CS_OSREL_MAJ
11752     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11753 #endif
11754 #ifdef _MIPS_CS_OSREL_MIN
11755     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11756 #endif
11757 #ifdef _MIPS_CS_OSREL_PATCH
11758     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11759 #endif
11760 #ifdef _MIPS_CS_OS_NAME
11761     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11762 #endif
11763 #ifdef _MIPS_CS_OS_PROVIDER
11764     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11765 #endif
11766 #ifdef _MIPS_CS_PROCESSORS
11767     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11768 #endif
11769 #ifdef _MIPS_CS_SERIAL
11770     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11771 #endif
11772 #ifdef _MIPS_CS_VENDOR
11773     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11774 #endif
11775 };
11776 
11777 static int
conv_confstr_confname(PyObject * arg,int * valuep)11778 conv_confstr_confname(PyObject *arg, int *valuep)
11779 {
11780     return conv_confname(arg, valuep, posix_constants_confstr,
11781                          sizeof(posix_constants_confstr)
11782                            / sizeof(struct constdef));
11783 }
11784 
11785 
11786 /*[clinic input]
11787 os.confstr
11788 
11789     name: confstr_confname
11790     /
11791 
11792 Return a string-valued system configuration variable.
11793 [clinic start generated code]*/
11794 
11795 static PyObject *
os_confstr_impl(PyObject * module,int name)11796 os_confstr_impl(PyObject *module, int name)
11797 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11798 {
11799     PyObject *result = NULL;
11800     char buffer[255];
11801     size_t len;
11802 
11803     errno = 0;
11804     len = confstr(name, buffer, sizeof(buffer));
11805     if (len == 0) {
11806         if (errno) {
11807             posix_error();
11808             return NULL;
11809         }
11810         else {
11811             Py_RETURN_NONE;
11812         }
11813     }
11814 
11815     if (len >= sizeof(buffer)) {
11816         size_t len2;
11817         char *buf = PyMem_Malloc(len);
11818         if (buf == NULL)
11819             return PyErr_NoMemory();
11820         len2 = confstr(name, buf, len);
11821         assert(len == len2);
11822         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11823         PyMem_Free(buf);
11824     }
11825     else
11826         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11827     return result;
11828 }
11829 #endif /* HAVE_CONFSTR */
11830 
11831 
11832 #ifdef HAVE_SYSCONF
11833 static struct constdef posix_constants_sysconf[] = {
11834 #ifdef _SC_2_CHAR_TERM
11835     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11836 #endif
11837 #ifdef _SC_2_C_BIND
11838     {"SC_2_C_BIND",     _SC_2_C_BIND},
11839 #endif
11840 #ifdef _SC_2_C_DEV
11841     {"SC_2_C_DEV",      _SC_2_C_DEV},
11842 #endif
11843 #ifdef _SC_2_C_VERSION
11844     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11845 #endif
11846 #ifdef _SC_2_FORT_DEV
11847     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
11848 #endif
11849 #ifdef _SC_2_FORT_RUN
11850     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
11851 #endif
11852 #ifdef _SC_2_LOCALEDEF
11853     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
11854 #endif
11855 #ifdef _SC_2_SW_DEV
11856     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
11857 #endif
11858 #ifdef _SC_2_UPE
11859     {"SC_2_UPE",        _SC_2_UPE},
11860 #endif
11861 #ifdef _SC_2_VERSION
11862     {"SC_2_VERSION",    _SC_2_VERSION},
11863 #endif
11864 #ifdef _SC_ABI_ASYNCHRONOUS_IO
11865     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
11866 #endif
11867 #ifdef _SC_ACL
11868     {"SC_ACL",  _SC_ACL},
11869 #endif
11870 #ifdef _SC_AIO_LISTIO_MAX
11871     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
11872 #endif
11873 #ifdef _SC_AIO_MAX
11874     {"SC_AIO_MAX",      _SC_AIO_MAX},
11875 #endif
11876 #ifdef _SC_AIO_PRIO_DELTA_MAX
11877     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
11878 #endif
11879 #ifdef _SC_ARG_MAX
11880     {"SC_ARG_MAX",      _SC_ARG_MAX},
11881 #endif
11882 #ifdef _SC_ASYNCHRONOUS_IO
11883     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
11884 #endif
11885 #ifdef _SC_ATEXIT_MAX
11886     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
11887 #endif
11888 #ifdef _SC_AUDIT
11889     {"SC_AUDIT",        _SC_AUDIT},
11890 #endif
11891 #ifdef _SC_AVPHYS_PAGES
11892     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
11893 #endif
11894 #ifdef _SC_BC_BASE_MAX
11895     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
11896 #endif
11897 #ifdef _SC_BC_DIM_MAX
11898     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
11899 #endif
11900 #ifdef _SC_BC_SCALE_MAX
11901     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
11902 #endif
11903 #ifdef _SC_BC_STRING_MAX
11904     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
11905 #endif
11906 #ifdef _SC_CAP
11907     {"SC_CAP",  _SC_CAP},
11908 #endif
11909 #ifdef _SC_CHARCLASS_NAME_MAX
11910     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
11911 #endif
11912 #ifdef _SC_CHAR_BIT
11913     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
11914 #endif
11915 #ifdef _SC_CHAR_MAX
11916     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
11917 #endif
11918 #ifdef _SC_CHAR_MIN
11919     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
11920 #endif
11921 #ifdef _SC_CHILD_MAX
11922     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
11923 #endif
11924 #ifdef _SC_CLK_TCK
11925     {"SC_CLK_TCK",      _SC_CLK_TCK},
11926 #endif
11927 #ifdef _SC_COHER_BLKSZ
11928     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
11929 #endif
11930 #ifdef _SC_COLL_WEIGHTS_MAX
11931     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
11932 #endif
11933 #ifdef _SC_DCACHE_ASSOC
11934     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
11935 #endif
11936 #ifdef _SC_DCACHE_BLKSZ
11937     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
11938 #endif
11939 #ifdef _SC_DCACHE_LINESZ
11940     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
11941 #endif
11942 #ifdef _SC_DCACHE_SZ
11943     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
11944 #endif
11945 #ifdef _SC_DCACHE_TBLKSZ
11946     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
11947 #endif
11948 #ifdef _SC_DELAYTIMER_MAX
11949     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
11950 #endif
11951 #ifdef _SC_EQUIV_CLASS_MAX
11952     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
11953 #endif
11954 #ifdef _SC_EXPR_NEST_MAX
11955     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
11956 #endif
11957 #ifdef _SC_FSYNC
11958     {"SC_FSYNC",        _SC_FSYNC},
11959 #endif
11960 #ifdef _SC_GETGR_R_SIZE_MAX
11961     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
11962 #endif
11963 #ifdef _SC_GETPW_R_SIZE_MAX
11964     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
11965 #endif
11966 #ifdef _SC_ICACHE_ASSOC
11967     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
11968 #endif
11969 #ifdef _SC_ICACHE_BLKSZ
11970     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
11971 #endif
11972 #ifdef _SC_ICACHE_LINESZ
11973     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
11974 #endif
11975 #ifdef _SC_ICACHE_SZ
11976     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
11977 #endif
11978 #ifdef _SC_INF
11979     {"SC_INF",  _SC_INF},
11980 #endif
11981 #ifdef _SC_INT_MAX
11982     {"SC_INT_MAX",      _SC_INT_MAX},
11983 #endif
11984 #ifdef _SC_INT_MIN
11985     {"SC_INT_MIN",      _SC_INT_MIN},
11986 #endif
11987 #ifdef _SC_IOV_MAX
11988     {"SC_IOV_MAX",      _SC_IOV_MAX},
11989 #endif
11990 #ifdef _SC_IP_SECOPTS
11991     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
11992 #endif
11993 #ifdef _SC_JOB_CONTROL
11994     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
11995 #endif
11996 #ifdef _SC_KERN_POINTERS
11997     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
11998 #endif
11999 #ifdef _SC_KERN_SIM
12000     {"SC_KERN_SIM",     _SC_KERN_SIM},
12001 #endif
12002 #ifdef _SC_LINE_MAX
12003     {"SC_LINE_MAX",     _SC_LINE_MAX},
12004 #endif
12005 #ifdef _SC_LOGIN_NAME_MAX
12006     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
12007 #endif
12008 #ifdef _SC_LOGNAME_MAX
12009     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
12010 #endif
12011 #ifdef _SC_LONG_BIT
12012     {"SC_LONG_BIT",     _SC_LONG_BIT},
12013 #endif
12014 #ifdef _SC_MAC
12015     {"SC_MAC",  _SC_MAC},
12016 #endif
12017 #ifdef _SC_MAPPED_FILES
12018     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12019 #endif
12020 #ifdef _SC_MAXPID
12021     {"SC_MAXPID",       _SC_MAXPID},
12022 #endif
12023 #ifdef _SC_MB_LEN_MAX
12024     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
12025 #endif
12026 #ifdef _SC_MEMLOCK
12027     {"SC_MEMLOCK",      _SC_MEMLOCK},
12028 #endif
12029 #ifdef _SC_MEMLOCK_RANGE
12030     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
12031 #endif
12032 #ifdef _SC_MEMORY_PROTECTION
12033     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
12034 #endif
12035 #ifdef _SC_MESSAGE_PASSING
12036     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
12037 #endif
12038 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12039     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12040 #endif
12041 #ifdef _SC_MQ_OPEN_MAX
12042     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
12043 #endif
12044 #ifdef _SC_MQ_PRIO_MAX
12045     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
12046 #endif
12047 #ifdef _SC_NACLS_MAX
12048     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
12049 #endif
12050 #ifdef _SC_NGROUPS_MAX
12051     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
12052 #endif
12053 #ifdef _SC_NL_ARGMAX
12054     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
12055 #endif
12056 #ifdef _SC_NL_LANGMAX
12057     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
12058 #endif
12059 #ifdef _SC_NL_MSGMAX
12060     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
12061 #endif
12062 #ifdef _SC_NL_NMAX
12063     {"SC_NL_NMAX",      _SC_NL_NMAX},
12064 #endif
12065 #ifdef _SC_NL_SETMAX
12066     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
12067 #endif
12068 #ifdef _SC_NL_TEXTMAX
12069     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
12070 #endif
12071 #ifdef _SC_NPROCESSORS_CONF
12072     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
12073 #endif
12074 #ifdef _SC_NPROCESSORS_ONLN
12075     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
12076 #endif
12077 #ifdef _SC_NPROC_CONF
12078     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
12079 #endif
12080 #ifdef _SC_NPROC_ONLN
12081     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
12082 #endif
12083 #ifdef _SC_NZERO
12084     {"SC_NZERO",        _SC_NZERO},
12085 #endif
12086 #ifdef _SC_OPEN_MAX
12087     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
12088 #endif
12089 #ifdef _SC_PAGESIZE
12090     {"SC_PAGESIZE",     _SC_PAGESIZE},
12091 #endif
12092 #ifdef _SC_PAGE_SIZE
12093     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
12094 #endif
12095 #ifdef _SC_AIX_REALMEM
12096     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12097 #endif
12098 #ifdef _SC_PASS_MAX
12099     {"SC_PASS_MAX",     _SC_PASS_MAX},
12100 #endif
12101 #ifdef _SC_PHYS_PAGES
12102     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
12103 #endif
12104 #ifdef _SC_PII
12105     {"SC_PII",  _SC_PII},
12106 #endif
12107 #ifdef _SC_PII_INTERNET
12108     {"SC_PII_INTERNET", _SC_PII_INTERNET},
12109 #endif
12110 #ifdef _SC_PII_INTERNET_DGRAM
12111     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
12112 #endif
12113 #ifdef _SC_PII_INTERNET_STREAM
12114     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
12115 #endif
12116 #ifdef _SC_PII_OSI
12117     {"SC_PII_OSI",      _SC_PII_OSI},
12118 #endif
12119 #ifdef _SC_PII_OSI_CLTS
12120     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12121 #endif
12122 #ifdef _SC_PII_OSI_COTS
12123     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12124 #endif
12125 #ifdef _SC_PII_OSI_M
12126     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
12127 #endif
12128 #ifdef _SC_PII_SOCKET
12129     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
12130 #endif
12131 #ifdef _SC_PII_XTI
12132     {"SC_PII_XTI",      _SC_PII_XTI},
12133 #endif
12134 #ifdef _SC_POLL
12135     {"SC_POLL", _SC_POLL},
12136 #endif
12137 #ifdef _SC_PRIORITIZED_IO
12138     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
12139 #endif
12140 #ifdef _SC_PRIORITY_SCHEDULING
12141     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
12142 #endif
12143 #ifdef _SC_REALTIME_SIGNALS
12144     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
12145 #endif
12146 #ifdef _SC_RE_DUP_MAX
12147     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
12148 #endif
12149 #ifdef _SC_RTSIG_MAX
12150     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
12151 #endif
12152 #ifdef _SC_SAVED_IDS
12153     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
12154 #endif
12155 #ifdef _SC_SCHAR_MAX
12156     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
12157 #endif
12158 #ifdef _SC_SCHAR_MIN
12159     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
12160 #endif
12161 #ifdef _SC_SELECT
12162     {"SC_SELECT",       _SC_SELECT},
12163 #endif
12164 #ifdef _SC_SEMAPHORES
12165     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12166 #endif
12167 #ifdef _SC_SEM_NSEMS_MAX
12168     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12169 #endif
12170 #ifdef _SC_SEM_VALUE_MAX
12171     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12172 #endif
12173 #ifdef _SC_SHARED_MEMORY_OBJECTS
12174     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12175 #endif
12176 #ifdef _SC_SHRT_MAX
12177     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12178 #endif
12179 #ifdef _SC_SHRT_MIN
12180     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12181 #endif
12182 #ifdef _SC_SIGQUEUE_MAX
12183     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12184 #endif
12185 #ifdef _SC_SIGRT_MAX
12186     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12187 #endif
12188 #ifdef _SC_SIGRT_MIN
12189     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12190 #endif
12191 #ifdef _SC_SOFTPOWER
12192     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12193 #endif
12194 #ifdef _SC_SPLIT_CACHE
12195     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12196 #endif
12197 #ifdef _SC_SSIZE_MAX
12198     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12199 #endif
12200 #ifdef _SC_STACK_PROT
12201     {"SC_STACK_PROT",   _SC_STACK_PROT},
12202 #endif
12203 #ifdef _SC_STREAM_MAX
12204     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12205 #endif
12206 #ifdef _SC_SYNCHRONIZED_IO
12207     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12208 #endif
12209 #ifdef _SC_THREADS
12210     {"SC_THREADS",      _SC_THREADS},
12211 #endif
12212 #ifdef _SC_THREAD_ATTR_STACKADDR
12213     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12214 #endif
12215 #ifdef _SC_THREAD_ATTR_STACKSIZE
12216     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12217 #endif
12218 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12219     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12220 #endif
12221 #ifdef _SC_THREAD_KEYS_MAX
12222     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12223 #endif
12224 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12225     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12226 #endif
12227 #ifdef _SC_THREAD_PRIO_INHERIT
12228     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12229 #endif
12230 #ifdef _SC_THREAD_PRIO_PROTECT
12231     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12232 #endif
12233 #ifdef _SC_THREAD_PROCESS_SHARED
12234     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12235 #endif
12236 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12237     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12238 #endif
12239 #ifdef _SC_THREAD_STACK_MIN
12240     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12241 #endif
12242 #ifdef _SC_THREAD_THREADS_MAX
12243     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12244 #endif
12245 #ifdef _SC_TIMERS
12246     {"SC_TIMERS",       _SC_TIMERS},
12247 #endif
12248 #ifdef _SC_TIMER_MAX
12249     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12250 #endif
12251 #ifdef _SC_TTY_NAME_MAX
12252     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12253 #endif
12254 #ifdef _SC_TZNAME_MAX
12255     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12256 #endif
12257 #ifdef _SC_T_IOV_MAX
12258     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12259 #endif
12260 #ifdef _SC_UCHAR_MAX
12261     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12262 #endif
12263 #ifdef _SC_UINT_MAX
12264     {"SC_UINT_MAX",     _SC_UINT_MAX},
12265 #endif
12266 #ifdef _SC_UIO_MAXIOV
12267     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12268 #endif
12269 #ifdef _SC_ULONG_MAX
12270     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12271 #endif
12272 #ifdef _SC_USHRT_MAX
12273     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12274 #endif
12275 #ifdef _SC_VERSION
12276     {"SC_VERSION",      _SC_VERSION},
12277 #endif
12278 #ifdef _SC_WORD_BIT
12279     {"SC_WORD_BIT",     _SC_WORD_BIT},
12280 #endif
12281 #ifdef _SC_XBS5_ILP32_OFF32
12282     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12283 #endif
12284 #ifdef _SC_XBS5_ILP32_OFFBIG
12285     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12286 #endif
12287 #ifdef _SC_XBS5_LP64_OFF64
12288     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12289 #endif
12290 #ifdef _SC_XBS5_LPBIG_OFFBIG
12291     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12292 #endif
12293 #ifdef _SC_XOPEN_CRYPT
12294     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12295 #endif
12296 #ifdef _SC_XOPEN_ENH_I18N
12297     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12298 #endif
12299 #ifdef _SC_XOPEN_LEGACY
12300     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12301 #endif
12302 #ifdef _SC_XOPEN_REALTIME
12303     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12304 #endif
12305 #ifdef _SC_XOPEN_REALTIME_THREADS
12306     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12307 #endif
12308 #ifdef _SC_XOPEN_SHM
12309     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12310 #endif
12311 #ifdef _SC_XOPEN_UNIX
12312     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12313 #endif
12314 #ifdef _SC_XOPEN_VERSION
12315     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12316 #endif
12317 #ifdef _SC_XOPEN_XCU_VERSION
12318     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12319 #endif
12320 #ifdef _SC_XOPEN_XPG2
12321     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12322 #endif
12323 #ifdef _SC_XOPEN_XPG3
12324     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12325 #endif
12326 #ifdef _SC_XOPEN_XPG4
12327     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12328 #endif
12329 };
12330 
12331 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12332 conv_sysconf_confname(PyObject *arg, int *valuep)
12333 {
12334     return conv_confname(arg, valuep, posix_constants_sysconf,
12335                          sizeof(posix_constants_sysconf)
12336                            / sizeof(struct constdef));
12337 }
12338 
12339 
12340 /*[clinic input]
12341 os.sysconf -> long
12342     name: sysconf_confname
12343     /
12344 
12345 Return an integer-valued system configuration variable.
12346 [clinic start generated code]*/
12347 
12348 static long
os_sysconf_impl(PyObject * module,int name)12349 os_sysconf_impl(PyObject *module, int name)
12350 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12351 {
12352     long value;
12353 
12354     errno = 0;
12355     value = sysconf(name);
12356     if (value == -1 && errno != 0)
12357         posix_error();
12358     return value;
12359 }
12360 #endif /* HAVE_SYSCONF */
12361 
12362 
12363 /* This code is used to ensure that the tables of configuration value names
12364  * are in sorted order as required by conv_confname(), and also to build
12365  * the exported dictionaries that are used to publish information about the
12366  * names available on the host platform.
12367  *
12368  * Sorting the table at runtime ensures that the table is properly ordered
12369  * when used, even for platforms we're not able to test on.  It also makes
12370  * it easier to add additional entries to the tables.
12371  */
12372 
12373 static int
cmp_constdefs(const void * v1,const void * v2)12374 cmp_constdefs(const void *v1,  const void *v2)
12375 {
12376     const struct constdef *c1 =
12377     (const struct constdef *) v1;
12378     const struct constdef *c2 =
12379     (const struct constdef *) v2;
12380 
12381     return strcmp(c1->name, c2->name);
12382 }
12383 
12384 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12385 setup_confname_table(struct constdef *table, size_t tablesize,
12386                      const char *tablename, PyObject *module)
12387 {
12388     PyObject *d = NULL;
12389     size_t i;
12390 
12391     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12392     d = PyDict_New();
12393     if (d == NULL)
12394         return -1;
12395 
12396     for (i=0; i < tablesize; ++i) {
12397         PyObject *o = PyLong_FromLong(table[i].value);
12398         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12399             Py_XDECREF(o);
12400             Py_DECREF(d);
12401             return -1;
12402         }
12403         Py_DECREF(o);
12404     }
12405     return PyModule_AddObject(module, tablename, d);
12406 }
12407 
12408 /* Return -1 on failure, 0 on success. */
12409 static int
setup_confname_tables(PyObject * module)12410 setup_confname_tables(PyObject *module)
12411 {
12412 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12413     if (setup_confname_table(posix_constants_pathconf,
12414                              sizeof(posix_constants_pathconf)
12415                                / sizeof(struct constdef),
12416                              "pathconf_names", module))
12417         return -1;
12418 #endif
12419 #ifdef HAVE_CONFSTR
12420     if (setup_confname_table(posix_constants_confstr,
12421                              sizeof(posix_constants_confstr)
12422                                / sizeof(struct constdef),
12423                              "confstr_names", module))
12424         return -1;
12425 #endif
12426 #ifdef HAVE_SYSCONF
12427     if (setup_confname_table(posix_constants_sysconf,
12428                              sizeof(posix_constants_sysconf)
12429                                / sizeof(struct constdef),
12430                              "sysconf_names", module))
12431         return -1;
12432 #endif
12433     return 0;
12434 }
12435 
12436 
12437 /*[clinic input]
12438 os.abort
12439 
12440 Abort the interpreter immediately.
12441 
12442 This function 'dumps core' or otherwise fails in the hardest way possible
12443 on the hosting operating system.  This function never returns.
12444 [clinic start generated code]*/
12445 
12446 static PyObject *
os_abort_impl(PyObject * module)12447 os_abort_impl(PyObject *module)
12448 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12449 {
12450     abort();
12451     /*NOTREACHED*/
12452 #ifndef __clang__
12453     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12454        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12455        is smarter and emits a warning on the return. */
12456     Py_FatalError("abort() called from Python code didn't abort!");
12457     return NULL;
12458 #endif
12459 }
12460 
12461 #ifdef MS_WINDOWS
12462 /* Grab ShellExecute dynamically from shell32 */
12463 static int has_ShellExecute = -1;
12464 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12465                                               LPCWSTR, INT);
12466 static int
check_ShellExecute()12467 check_ShellExecute()
12468 {
12469     HINSTANCE hShell32;
12470 
12471     /* only recheck */
12472     if (-1 == has_ShellExecute) {
12473         Py_BEGIN_ALLOW_THREADS
12474         /* Security note: this call is not vulnerable to "DLL hijacking".
12475            SHELL32 is part of "KnownDLLs" and so Windows always load
12476            the system SHELL32.DLL, even if there is another SHELL32.DLL
12477            in the DLL search path. */
12478         hShell32 = LoadLibraryW(L"SHELL32");
12479         if (hShell32) {
12480             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12481                                             "ShellExecuteW");
12482             has_ShellExecute = Py_ShellExecuteW != NULL;
12483         } else {
12484             has_ShellExecute = 0;
12485         }
12486         Py_END_ALLOW_THREADS
12487     }
12488     return has_ShellExecute;
12489 }
12490 
12491 
12492 /*[clinic input]
12493 os.startfile
12494     filepath: path_t
12495     operation: Py_UNICODE = NULL
12496     arguments: Py_UNICODE = NULL
12497     cwd: path_t(nullable=True) = None
12498     show_cmd: int = 1
12499 
12500 Start a file with its associated application.
12501 
12502 When "operation" is not specified or "open", this acts like
12503 double-clicking the file in Explorer, or giving the file name as an
12504 argument to the DOS "start" command: the file is opened with whatever
12505 application (if any) its extension is associated.
12506 When another "operation" is given, it specifies what should be done with
12507 the file.  A typical operation is "print".
12508 
12509 "arguments" is passed to the application, but should be omitted if the
12510 file is a document.
12511 
12512 "cwd" is the working directory for the operation. If "filepath" is
12513 relative, it will be resolved against this directory. This argument
12514 should usually be an absolute path.
12515 
12516 "show_cmd" can be used to override the recommended visibility option.
12517 See the Windows ShellExecute documentation for values.
12518 
12519 startfile returns as soon as the associated application is launched.
12520 There is no option to wait for the application to close, and no way
12521 to retrieve the application's exit status.
12522 
12523 The filepath is relative to the current directory.  If you want to use
12524 an absolute path, make sure the first character is not a slash ("/");
12525 the underlying Win32 ShellExecute function doesn't work if it is.
12526 [clinic start generated code]*/
12527 
12528 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12529 os_startfile_impl(PyObject *module, path_t *filepath,
12530                   const Py_UNICODE *operation, const Py_UNICODE *arguments,
12531                   path_t *cwd, int show_cmd)
12532 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12533 {
12534     HINSTANCE rc;
12535 
12536     if(!check_ShellExecute()) {
12537         /* If the OS doesn't have ShellExecute, return a
12538            NotImplementedError. */
12539         return PyErr_Format(PyExc_NotImplementedError,
12540             "startfile not available on this platform");
12541     }
12542 
12543     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12544         return NULL;
12545     }
12546     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12547                     arguments, cwd->object ? cwd->object : Py_None,
12548                     show_cmd) < 0) {
12549         return NULL;
12550     }
12551 
12552     Py_BEGIN_ALLOW_THREADS
12553     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12554                           arguments, cwd->wide, show_cmd);
12555     Py_END_ALLOW_THREADS
12556 
12557     if (rc <= (HINSTANCE)32) {
12558         win32_error_object("startfile", filepath->object);
12559         return NULL;
12560     }
12561     Py_RETURN_NONE;
12562 }
12563 #endif /* MS_WINDOWS */
12564 
12565 
12566 #ifdef HAVE_GETLOADAVG
12567 /*[clinic input]
12568 os.getloadavg
12569 
12570 Return average recent system load information.
12571 
12572 Return the number of processes in the system run queue averaged over
12573 the last 1, 5, and 15 minutes as a tuple of three floats.
12574 Raises OSError if the load average was unobtainable.
12575 [clinic start generated code]*/
12576 
12577 static PyObject *
os_getloadavg_impl(PyObject * module)12578 os_getloadavg_impl(PyObject *module)
12579 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12580 {
12581     double loadavg[3];
12582     if (getloadavg(loadavg, 3)!=3) {
12583         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12584         return NULL;
12585     } else
12586         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12587 }
12588 #endif /* HAVE_GETLOADAVG */
12589 
12590 
12591 /*[clinic input]
12592 os.device_encoding
12593     fd: int
12594 
12595 Return a string describing the encoding of a terminal's file descriptor.
12596 
12597 The file descriptor must be attached to a terminal.
12598 If the device is not a terminal, return None.
12599 [clinic start generated code]*/
12600 
12601 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12602 os_device_encoding_impl(PyObject *module, int fd)
12603 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12604 {
12605     return _Py_device_encoding(fd);
12606 }
12607 
12608 
12609 #ifdef HAVE_SETRESUID
12610 /*[clinic input]
12611 os.setresuid
12612 
12613     ruid: uid_t
12614     euid: uid_t
12615     suid: uid_t
12616     /
12617 
12618 Set the current process's real, effective, and saved user ids.
12619 [clinic start generated code]*/
12620 
12621 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12622 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12623 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12624 {
12625     if (setresuid(ruid, euid, suid) < 0)
12626         return posix_error();
12627     Py_RETURN_NONE;
12628 }
12629 #endif /* HAVE_SETRESUID */
12630 
12631 
12632 #ifdef HAVE_SETRESGID
12633 /*[clinic input]
12634 os.setresgid
12635 
12636     rgid: gid_t
12637     egid: gid_t
12638     sgid: gid_t
12639     /
12640 
12641 Set the current process's real, effective, and saved group ids.
12642 [clinic start generated code]*/
12643 
12644 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12645 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12646 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12647 {
12648     if (setresgid(rgid, egid, sgid) < 0)
12649         return posix_error();
12650     Py_RETURN_NONE;
12651 }
12652 #endif /* HAVE_SETRESGID */
12653 
12654 
12655 #ifdef HAVE_GETRESUID
12656 /*[clinic input]
12657 os.getresuid
12658 
12659 Return a tuple of the current process's real, effective, and saved user ids.
12660 [clinic start generated code]*/
12661 
12662 static PyObject *
os_getresuid_impl(PyObject * module)12663 os_getresuid_impl(PyObject *module)
12664 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12665 {
12666     uid_t ruid, euid, suid;
12667     if (getresuid(&ruid, &euid, &suid) < 0)
12668         return posix_error();
12669     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12670                                   _PyLong_FromUid(euid),
12671                                   _PyLong_FromUid(suid));
12672 }
12673 #endif /* HAVE_GETRESUID */
12674 
12675 
12676 #ifdef HAVE_GETRESGID
12677 /*[clinic input]
12678 os.getresgid
12679 
12680 Return a tuple of the current process's real, effective, and saved group ids.
12681 [clinic start generated code]*/
12682 
12683 static PyObject *
os_getresgid_impl(PyObject * module)12684 os_getresgid_impl(PyObject *module)
12685 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12686 {
12687     gid_t rgid, egid, sgid;
12688     if (getresgid(&rgid, &egid, &sgid) < 0)
12689         return posix_error();
12690     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12691                                   _PyLong_FromGid(egid),
12692                                   _PyLong_FromGid(sgid));
12693 }
12694 #endif /* HAVE_GETRESGID */
12695 
12696 
12697 #ifdef USE_XATTRS
12698 /*[clinic input]
12699 os.getxattr
12700 
12701     path: path_t(allow_fd=True)
12702     attribute: path_t
12703     *
12704     follow_symlinks: bool = True
12705 
12706 Return the value of extended attribute attribute on path.
12707 
12708 path may be either a string, a path-like object, or an open file descriptor.
12709 If follow_symlinks is False, and the last element of the path is a symbolic
12710   link, getxattr will examine the symbolic link itself instead of the file
12711   the link points to.
12712 
12713 [clinic start generated code]*/
12714 
12715 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12716 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12717                  int follow_symlinks)
12718 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12719 {
12720     Py_ssize_t i;
12721     PyObject *buffer = NULL;
12722 
12723     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12724         return NULL;
12725 
12726     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12727         return NULL;
12728     }
12729 
12730     for (i = 0; ; i++) {
12731         void *ptr;
12732         ssize_t result;
12733         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12734         Py_ssize_t buffer_size = buffer_sizes[i];
12735         if (!buffer_size) {
12736             path_error(path);
12737             return NULL;
12738         }
12739         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12740         if (!buffer)
12741             return NULL;
12742         ptr = PyBytes_AS_STRING(buffer);
12743 
12744         Py_BEGIN_ALLOW_THREADS;
12745         if (path->fd >= 0)
12746             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12747         else if (follow_symlinks)
12748             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12749         else
12750             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12751         Py_END_ALLOW_THREADS;
12752 
12753         if (result < 0) {
12754             Py_DECREF(buffer);
12755             if (errno == ERANGE)
12756                 continue;
12757             path_error(path);
12758             return NULL;
12759         }
12760 
12761         if (result != buffer_size) {
12762             /* Can only shrink. */
12763             _PyBytes_Resize(&buffer, result);
12764         }
12765         break;
12766     }
12767 
12768     return buffer;
12769 }
12770 
12771 
12772 /*[clinic input]
12773 os.setxattr
12774 
12775     path: path_t(allow_fd=True)
12776     attribute: path_t
12777     value: Py_buffer
12778     flags: int = 0
12779     *
12780     follow_symlinks: bool = True
12781 
12782 Set extended attribute attribute on path to value.
12783 
12784 path may be either a string, a path-like object,  or an open file descriptor.
12785 If follow_symlinks is False, and the last element of the path is a symbolic
12786   link, setxattr will modify the symbolic link itself instead of the file
12787   the link points to.
12788 
12789 [clinic start generated code]*/
12790 
12791 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12792 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12793                  Py_buffer *value, int flags, int follow_symlinks)
12794 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12795 {
12796     ssize_t result;
12797 
12798     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12799         return NULL;
12800 
12801     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12802                     value->buf, value->len, flags) < 0) {
12803         return NULL;
12804     }
12805 
12806     Py_BEGIN_ALLOW_THREADS;
12807     if (path->fd > -1)
12808         result = fsetxattr(path->fd, attribute->narrow,
12809                            value->buf, value->len, flags);
12810     else if (follow_symlinks)
12811         result = setxattr(path->narrow, attribute->narrow,
12812                            value->buf, value->len, flags);
12813     else
12814         result = lsetxattr(path->narrow, attribute->narrow,
12815                            value->buf, value->len, flags);
12816     Py_END_ALLOW_THREADS;
12817 
12818     if (result) {
12819         path_error(path);
12820         return NULL;
12821     }
12822 
12823     Py_RETURN_NONE;
12824 }
12825 
12826 
12827 /*[clinic input]
12828 os.removexattr
12829 
12830     path: path_t(allow_fd=True)
12831     attribute: path_t
12832     *
12833     follow_symlinks: bool = True
12834 
12835 Remove extended attribute attribute on path.
12836 
12837 path may be either a string, a path-like object, or an open file descriptor.
12838 If follow_symlinks is False, and the last element of the path is a symbolic
12839   link, removexattr will modify the symbolic link itself instead of the file
12840   the link points to.
12841 
12842 [clinic start generated code]*/
12843 
12844 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12845 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
12846                     int follow_symlinks)
12847 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
12848 {
12849     ssize_t result;
12850 
12851     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
12852         return NULL;
12853 
12854     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
12855         return NULL;
12856     }
12857 
12858     Py_BEGIN_ALLOW_THREADS;
12859     if (path->fd > -1)
12860         result = fremovexattr(path->fd, attribute->narrow);
12861     else if (follow_symlinks)
12862         result = removexattr(path->narrow, attribute->narrow);
12863     else
12864         result = lremovexattr(path->narrow, attribute->narrow);
12865     Py_END_ALLOW_THREADS;
12866 
12867     if (result) {
12868         return path_error(path);
12869     }
12870 
12871     Py_RETURN_NONE;
12872 }
12873 
12874 
12875 /*[clinic input]
12876 os.listxattr
12877 
12878     path: path_t(allow_fd=True, nullable=True) = None
12879     *
12880     follow_symlinks: bool = True
12881 
12882 Return a list of extended attributes on path.
12883 
12884 path may be either None, a string, a path-like object, or an open file descriptor.
12885 if path is None, listxattr will examine the current directory.
12886 If follow_symlinks is False, and the last element of the path is a symbolic
12887   link, listxattr will examine the symbolic link itself instead of the file
12888   the link points to.
12889 [clinic start generated code]*/
12890 
12891 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)12892 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
12893 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
12894 {
12895     Py_ssize_t i;
12896     PyObject *result = NULL;
12897     const char *name;
12898     char *buffer = NULL;
12899 
12900     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
12901         goto exit;
12902 
12903     if (PySys_Audit("os.listxattr", "(O)",
12904                     path->object ? path->object : Py_None) < 0) {
12905         return NULL;
12906     }
12907 
12908     name = path->narrow ? path->narrow : ".";
12909 
12910     for (i = 0; ; i++) {
12911         const char *start, *trace, *end;
12912         ssize_t length;
12913         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
12914         Py_ssize_t buffer_size = buffer_sizes[i];
12915         if (!buffer_size) {
12916             /* ERANGE */
12917             path_error(path);
12918             break;
12919         }
12920         buffer = PyMem_Malloc(buffer_size);
12921         if (!buffer) {
12922             PyErr_NoMemory();
12923             break;
12924         }
12925 
12926         Py_BEGIN_ALLOW_THREADS;
12927         if (path->fd > -1)
12928             length = flistxattr(path->fd, buffer, buffer_size);
12929         else if (follow_symlinks)
12930             length = listxattr(name, buffer, buffer_size);
12931         else
12932             length = llistxattr(name, buffer, buffer_size);
12933         Py_END_ALLOW_THREADS;
12934 
12935         if (length < 0) {
12936             if (errno == ERANGE) {
12937                 PyMem_Free(buffer);
12938                 buffer = NULL;
12939                 continue;
12940             }
12941             path_error(path);
12942             break;
12943         }
12944 
12945         result = PyList_New(0);
12946         if (!result) {
12947             goto exit;
12948         }
12949 
12950         end = buffer + length;
12951         for (trace = start = buffer; trace != end; trace++) {
12952             if (!*trace) {
12953                 int error;
12954                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
12955                                                                  trace - start);
12956                 if (!attribute) {
12957                     Py_DECREF(result);
12958                     result = NULL;
12959                     goto exit;
12960                 }
12961                 error = PyList_Append(result, attribute);
12962                 Py_DECREF(attribute);
12963                 if (error) {
12964                     Py_DECREF(result);
12965                     result = NULL;
12966                     goto exit;
12967                 }
12968                 start = trace + 1;
12969             }
12970         }
12971     break;
12972     }
12973 exit:
12974     if (buffer)
12975         PyMem_Free(buffer);
12976     return result;
12977 }
12978 #endif /* USE_XATTRS */
12979 
12980 
12981 /*[clinic input]
12982 os.urandom
12983 
12984     size: Py_ssize_t
12985     /
12986 
12987 Return a bytes object containing random bytes suitable for cryptographic use.
12988 [clinic start generated code]*/
12989 
12990 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)12991 os_urandom_impl(PyObject *module, Py_ssize_t size)
12992 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
12993 {
12994     PyObject *bytes;
12995     int result;
12996 
12997     if (size < 0)
12998         return PyErr_Format(PyExc_ValueError,
12999                             "negative argument not allowed");
13000     bytes = PyBytes_FromStringAndSize(NULL, size);
13001     if (bytes == NULL)
13002         return NULL;
13003 
13004     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13005     if (result == -1) {
13006         Py_DECREF(bytes);
13007         return NULL;
13008     }
13009     return bytes;
13010 }
13011 
13012 #ifdef HAVE_MEMFD_CREATE
13013 /*[clinic input]
13014 os.memfd_create
13015 
13016     name: FSConverter
13017     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13018 
13019 [clinic start generated code]*/
13020 
13021 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13022 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13023 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13024 {
13025     int fd;
13026     const char *bytes = PyBytes_AS_STRING(name);
13027     Py_BEGIN_ALLOW_THREADS
13028     fd = memfd_create(bytes, flags);
13029     Py_END_ALLOW_THREADS
13030     if (fd == -1) {
13031         return PyErr_SetFromErrno(PyExc_OSError);
13032     }
13033     return PyLong_FromLong(fd);
13034 }
13035 #endif
13036 
13037 #ifdef HAVE_EVENTFD
13038 /*[clinic input]
13039 os.eventfd
13040 
13041     initval: unsigned_int
13042     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13043 
13044 Creates and returns an event notification file descriptor.
13045 [clinic start generated code]*/
13046 
13047 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13048 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13049 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13050 
13051 {
13052     /* initval is limited to uint32_t, internal counter is uint64_t */
13053     int fd;
13054     Py_BEGIN_ALLOW_THREADS
13055     fd = eventfd(initval, flags);
13056     Py_END_ALLOW_THREADS
13057     if (fd == -1) {
13058         return PyErr_SetFromErrno(PyExc_OSError);
13059     }
13060     return PyLong_FromLong(fd);
13061 }
13062 
13063 /*[clinic input]
13064 os.eventfd_read
13065 
13066     fd: fildes
13067 
13068 Read eventfd value
13069 [clinic start generated code]*/
13070 
13071 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13072 os_eventfd_read_impl(PyObject *module, int fd)
13073 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13074 {
13075     eventfd_t value;
13076     int result;
13077     Py_BEGIN_ALLOW_THREADS
13078     result = eventfd_read(fd, &value);
13079     Py_END_ALLOW_THREADS
13080     if (result == -1) {
13081         return PyErr_SetFromErrno(PyExc_OSError);
13082     }
13083     return PyLong_FromUnsignedLongLong(value);
13084 }
13085 
13086 /*[clinic input]
13087 os.eventfd_write
13088 
13089     fd: fildes
13090     value: unsigned_long_long
13091 
13092 Write eventfd value.
13093 [clinic start generated code]*/
13094 
13095 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13096 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13097 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13098 {
13099     int result;
13100     Py_BEGIN_ALLOW_THREADS
13101     result = eventfd_write(fd, value);
13102     Py_END_ALLOW_THREADS
13103     if (result == -1) {
13104         return PyErr_SetFromErrno(PyExc_OSError);
13105     }
13106     Py_RETURN_NONE;
13107 }
13108 #endif  /* HAVE_EVENTFD */
13109 
13110 /* Terminal size querying */
13111 
13112 PyDoc_STRVAR(TerminalSize_docstring,
13113     "A tuple of (columns, lines) for holding terminal window size");
13114 
13115 static PyStructSequence_Field TerminalSize_fields[] = {
13116     {"columns", "width of the terminal window in characters"},
13117     {"lines", "height of the terminal window in characters"},
13118     {NULL, NULL}
13119 };
13120 
13121 static PyStructSequence_Desc TerminalSize_desc = {
13122     "os.terminal_size",
13123     TerminalSize_docstring,
13124     TerminalSize_fields,
13125     2,
13126 };
13127 
13128 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13129 /*[clinic input]
13130 os.get_terminal_size
13131 
13132     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13133     /
13134 
13135 Return the size of the terminal window as (columns, lines).
13136 
13137 The optional argument fd (default standard output) specifies
13138 which file descriptor should be queried.
13139 
13140 If the file descriptor is not connected to a terminal, an OSError
13141 is thrown.
13142 
13143 This function will only be defined if an implementation is
13144 available for this system.
13145 
13146 shutil.get_terminal_size is the high-level function which should
13147 normally be used, os.get_terminal_size is the low-level implementation.
13148 [clinic start generated code]*/
13149 
13150 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13151 os_get_terminal_size_impl(PyObject *module, int fd)
13152 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13153 {
13154     int columns, lines;
13155     PyObject *termsize;
13156 
13157     /* Under some conditions stdout may not be connected and
13158      * fileno(stdout) may point to an invalid file descriptor. For example
13159      * GUI apps don't have valid standard streams by default.
13160      *
13161      * If this happens, and the optional fd argument is not present,
13162      * the ioctl below will fail returning EBADF. This is what we want.
13163      */
13164 
13165 #ifdef TERMSIZE_USE_IOCTL
13166     {
13167         struct winsize w;
13168         if (ioctl(fd, TIOCGWINSZ, &w))
13169             return PyErr_SetFromErrno(PyExc_OSError);
13170         columns = w.ws_col;
13171         lines = w.ws_row;
13172     }
13173 #endif /* TERMSIZE_USE_IOCTL */
13174 
13175 #ifdef TERMSIZE_USE_CONIO
13176     {
13177         DWORD nhandle;
13178         HANDLE handle;
13179         CONSOLE_SCREEN_BUFFER_INFO csbi;
13180         switch (fd) {
13181         case 0: nhandle = STD_INPUT_HANDLE;
13182             break;
13183         case 1: nhandle = STD_OUTPUT_HANDLE;
13184             break;
13185         case 2: nhandle = STD_ERROR_HANDLE;
13186             break;
13187         default:
13188             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13189         }
13190         handle = GetStdHandle(nhandle);
13191         if (handle == NULL)
13192             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13193         if (handle == INVALID_HANDLE_VALUE)
13194             return PyErr_SetFromWindowsErr(0);
13195 
13196         if (!GetConsoleScreenBufferInfo(handle, &csbi))
13197             return PyErr_SetFromWindowsErr(0);
13198 
13199         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13200         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13201     }
13202 #endif /* TERMSIZE_USE_CONIO */
13203 
13204     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13205     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13206     if (termsize == NULL)
13207         return NULL;
13208     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13209     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13210     if (PyErr_Occurred()) {
13211         Py_DECREF(termsize);
13212         return NULL;
13213     }
13214     return termsize;
13215 }
13216 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13217 
13218 
13219 /*[clinic input]
13220 os.cpu_count
13221 
13222 Return the number of CPUs in the system; return None if indeterminable.
13223 
13224 This number is not equivalent to the number of CPUs the current process can
13225 use.  The number of usable CPUs can be obtained with
13226 ``len(os.sched_getaffinity(0))``
13227 [clinic start generated code]*/
13228 
13229 static PyObject *
os_cpu_count_impl(PyObject * module)13230 os_cpu_count_impl(PyObject *module)
13231 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13232 {
13233     int ncpu = 0;
13234 #ifdef MS_WINDOWS
13235     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13236 #elif defined(__hpux)
13237     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13238 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13239     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13240 #elif defined(__VXWORKS__)
13241     ncpu = _Py_popcount32(vxCpuEnabledGet());
13242 #elif defined(__DragonFly__) || \
13243       defined(__OpenBSD__)   || \
13244       defined(__FreeBSD__)   || \
13245       defined(__NetBSD__)    || \
13246       defined(__APPLE__)
13247     int mib[2];
13248     size_t len = sizeof(ncpu);
13249     mib[0] = CTL_HW;
13250     mib[1] = HW_NCPU;
13251     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13252         ncpu = 0;
13253 #endif
13254     if (ncpu >= 1)
13255         return PyLong_FromLong(ncpu);
13256     else
13257         Py_RETURN_NONE;
13258 }
13259 
13260 
13261 /*[clinic input]
13262 os.get_inheritable -> bool
13263 
13264     fd: int
13265     /
13266 
13267 Get the close-on-exe flag of the specified file descriptor.
13268 [clinic start generated code]*/
13269 
13270 static int
os_get_inheritable_impl(PyObject * module,int fd)13271 os_get_inheritable_impl(PyObject *module, int fd)
13272 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13273 {
13274     int return_value;
13275     _Py_BEGIN_SUPPRESS_IPH
13276     return_value = _Py_get_inheritable(fd);
13277     _Py_END_SUPPRESS_IPH
13278     return return_value;
13279 }
13280 
13281 
13282 /*[clinic input]
13283 os.set_inheritable
13284     fd: int
13285     inheritable: int
13286     /
13287 
13288 Set the inheritable flag of the specified file descriptor.
13289 [clinic start generated code]*/
13290 
13291 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13292 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13293 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13294 {
13295     int result;
13296 
13297     _Py_BEGIN_SUPPRESS_IPH
13298     result = _Py_set_inheritable(fd, inheritable, NULL);
13299     _Py_END_SUPPRESS_IPH
13300     if (result < 0)
13301         return NULL;
13302     Py_RETURN_NONE;
13303 }
13304 
13305 
13306 #ifdef MS_WINDOWS
13307 /*[clinic input]
13308 os.get_handle_inheritable -> bool
13309     handle: intptr_t
13310     /
13311 
13312 Get the close-on-exe flag of the specified file descriptor.
13313 [clinic start generated code]*/
13314 
13315 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13316 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13317 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13318 {
13319     DWORD flags;
13320 
13321     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13322         PyErr_SetFromWindowsErr(0);
13323         return -1;
13324     }
13325 
13326     return flags & HANDLE_FLAG_INHERIT;
13327 }
13328 
13329 
13330 /*[clinic input]
13331 os.set_handle_inheritable
13332     handle: intptr_t
13333     inheritable: bool
13334     /
13335 
13336 Set the inheritable flag of the specified handle.
13337 [clinic start generated code]*/
13338 
13339 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13340 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13341                                int inheritable)
13342 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13343 {
13344     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13345     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13346         PyErr_SetFromWindowsErr(0);
13347         return NULL;
13348     }
13349     Py_RETURN_NONE;
13350 }
13351 #endif /* MS_WINDOWS */
13352 
13353 #ifndef MS_WINDOWS
13354 /*[clinic input]
13355 os.get_blocking -> bool
13356     fd: int
13357     /
13358 
13359 Get the blocking mode of the file descriptor.
13360 
13361 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13362 [clinic start generated code]*/
13363 
13364 static int
os_get_blocking_impl(PyObject * module,int fd)13365 os_get_blocking_impl(PyObject *module, int fd)
13366 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13367 {
13368     int blocking;
13369 
13370     _Py_BEGIN_SUPPRESS_IPH
13371     blocking = _Py_get_blocking(fd);
13372     _Py_END_SUPPRESS_IPH
13373     return blocking;
13374 }
13375 
13376 /*[clinic input]
13377 os.set_blocking
13378     fd: int
13379     blocking: bool(accept={int})
13380     /
13381 
13382 Set the blocking mode of the specified file descriptor.
13383 
13384 Set the O_NONBLOCK flag if blocking is False,
13385 clear the O_NONBLOCK flag otherwise.
13386 [clinic start generated code]*/
13387 
13388 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13389 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13390 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13391 {
13392     int result;
13393 
13394     _Py_BEGIN_SUPPRESS_IPH
13395     result = _Py_set_blocking(fd, blocking);
13396     _Py_END_SUPPRESS_IPH
13397     if (result < 0)
13398         return NULL;
13399     Py_RETURN_NONE;
13400 }
13401 #endif   /* !MS_WINDOWS */
13402 
13403 
13404 /*[clinic input]
13405 class os.DirEntry "DirEntry *" "DirEntryType"
13406 [clinic start generated code]*/
13407 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13408 
13409 typedef struct {
13410     PyObject_HEAD
13411     PyObject *name;
13412     PyObject *path;
13413     PyObject *stat;
13414     PyObject *lstat;
13415 #ifdef MS_WINDOWS
13416     struct _Py_stat_struct win32_lstat;
13417     uint64_t win32_file_index;
13418     int got_file_index;
13419 #else /* POSIX */
13420 #ifdef HAVE_DIRENT_D_TYPE
13421     unsigned char d_type;
13422 #endif
13423     ino_t d_ino;
13424     int dir_fd;
13425 #endif
13426 } DirEntry;
13427 
13428 static void
DirEntry_dealloc(DirEntry * entry)13429 DirEntry_dealloc(DirEntry *entry)
13430 {
13431     PyTypeObject *tp = Py_TYPE(entry);
13432     Py_XDECREF(entry->name);
13433     Py_XDECREF(entry->path);
13434     Py_XDECREF(entry->stat);
13435     Py_XDECREF(entry->lstat);
13436     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13437     free_func(entry);
13438     Py_DECREF(tp);
13439 }
13440 
13441 /* Forward reference */
13442 static int
13443 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13444                    int follow_symlinks, unsigned short mode_bits);
13445 
13446 /*[clinic input]
13447 os.DirEntry.is_symlink -> bool
13448     defining_class: defining_class
13449     /
13450 
13451 Return True if the entry is a symbolic link; cached per entry.
13452 [clinic start generated code]*/
13453 
13454 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13455 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13456 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13457 {
13458 #ifdef MS_WINDOWS
13459     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13460 #elif defined(HAVE_DIRENT_D_TYPE)
13461     /* POSIX */
13462     if (self->d_type != DT_UNKNOWN)
13463         return self->d_type == DT_LNK;
13464     else
13465         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13466 #else
13467     /* POSIX without d_type */
13468     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13469 #endif
13470 }
13471 
13472 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13473 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13474 {
13475     int result;
13476     STRUCT_STAT st;
13477     PyObject *ub;
13478 
13479 #ifdef MS_WINDOWS
13480     if (!PyUnicode_FSDecoder(self->path, &ub))
13481         return NULL;
13482 #if USE_UNICODE_WCHAR_CACHE
13483 _Py_COMP_DIAG_PUSH
13484 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13485     const wchar_t *path = PyUnicode_AsUnicode(ub);
13486 _Py_COMP_DIAG_POP
13487 #else /* USE_UNICODE_WCHAR_CACHE */
13488     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13489     Py_DECREF(ub);
13490 #endif /* USE_UNICODE_WCHAR_CACHE */
13491 #else /* POSIX */
13492     if (!PyUnicode_FSConverter(self->path, &ub))
13493         return NULL;
13494     const char *path = PyBytes_AS_STRING(ub);
13495     if (self->dir_fd != DEFAULT_DIR_FD) {
13496 #ifdef HAVE_FSTATAT
13497       if (HAVE_FSTATAT_RUNTIME) {
13498         result = fstatat(self->dir_fd, path, &st,
13499                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13500       } else
13501 
13502 #endif /* HAVE_FSTATAT */
13503       {
13504         Py_DECREF(ub);
13505         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13506         return NULL;
13507       }
13508     }
13509     else
13510 #endif
13511     {
13512         if (follow_symlinks)
13513             result = STAT(path, &st);
13514         else
13515             result = LSTAT(path, &st);
13516     }
13517 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13518     PyMem_Free(path);
13519 #else /* USE_UNICODE_WCHAR_CACHE */
13520     Py_DECREF(ub);
13521 #endif /* USE_UNICODE_WCHAR_CACHE */
13522 
13523     if (result != 0)
13524         return path_object_error(self->path);
13525 
13526     return _pystat_fromstructstat(module, &st);
13527 }
13528 
13529 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13530 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13531 {
13532     if (!self->lstat) {
13533         PyObject *module = PyType_GetModule(defining_class);
13534 #ifdef MS_WINDOWS
13535         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13536 #else /* POSIX */
13537         self->lstat = DirEntry_fetch_stat(module, self, 0);
13538 #endif
13539     }
13540     Py_XINCREF(self->lstat);
13541     return self->lstat;
13542 }
13543 
13544 /*[clinic input]
13545 os.DirEntry.stat
13546     defining_class: defining_class
13547     /
13548     *
13549     follow_symlinks: bool = True
13550 
13551 Return stat_result object for the entry; cached per entry.
13552 [clinic start generated code]*/
13553 
13554 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13555 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13556                       int follow_symlinks)
13557 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13558 {
13559     if (!follow_symlinks) {
13560         return DirEntry_get_lstat(defining_class, self);
13561     }
13562 
13563     if (!self->stat) {
13564         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13565         if (result == -1) {
13566             return NULL;
13567         }
13568         if (result) {
13569             PyObject *module = PyType_GetModule(defining_class);
13570             self->stat = DirEntry_fetch_stat(module, self, 1);
13571         }
13572         else {
13573             self->stat = DirEntry_get_lstat(defining_class, self);
13574         }
13575     }
13576 
13577     Py_XINCREF(self->stat);
13578     return self->stat;
13579 }
13580 
13581 /* Set exception and return -1 on error, 0 for False, 1 for True */
13582 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13583 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13584                    int follow_symlinks, unsigned short mode_bits)
13585 {
13586     PyObject *stat = NULL;
13587     PyObject *st_mode = NULL;
13588     long mode;
13589     int result;
13590 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13591     int is_symlink;
13592     int need_stat;
13593 #endif
13594 #ifdef MS_WINDOWS
13595     unsigned long dir_bits;
13596 #endif
13597 
13598 #ifdef MS_WINDOWS
13599     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13600     need_stat = follow_symlinks && is_symlink;
13601 #elif defined(HAVE_DIRENT_D_TYPE)
13602     is_symlink = self->d_type == DT_LNK;
13603     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13604 #endif
13605 
13606 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13607     if (need_stat) {
13608 #endif
13609         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13610         if (!stat) {
13611             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13612                 /* If file doesn't exist (anymore), then return False
13613                    (i.e., say it's not a file/directory) */
13614                 PyErr_Clear();
13615                 return 0;
13616             }
13617             goto error;
13618         }
13619         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13620         st_mode = PyObject_GetAttr(stat, state->st_mode);
13621         if (!st_mode)
13622             goto error;
13623 
13624         mode = PyLong_AsLong(st_mode);
13625         if (mode == -1 && PyErr_Occurred())
13626             goto error;
13627         Py_CLEAR(st_mode);
13628         Py_CLEAR(stat);
13629         result = (mode & S_IFMT) == mode_bits;
13630 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13631     }
13632     else if (is_symlink) {
13633         assert(mode_bits != S_IFLNK);
13634         result = 0;
13635     }
13636     else {
13637         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13638 #ifdef MS_WINDOWS
13639         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13640         if (mode_bits == S_IFDIR)
13641             result = dir_bits != 0;
13642         else
13643             result = dir_bits == 0;
13644 #else /* POSIX */
13645         if (mode_bits == S_IFDIR)
13646             result = self->d_type == DT_DIR;
13647         else
13648             result = self->d_type == DT_REG;
13649 #endif
13650     }
13651 #endif
13652 
13653     return result;
13654 
13655 error:
13656     Py_XDECREF(st_mode);
13657     Py_XDECREF(stat);
13658     return -1;
13659 }
13660 
13661 /*[clinic input]
13662 os.DirEntry.is_dir -> bool
13663     defining_class: defining_class
13664     /
13665     *
13666     follow_symlinks: bool = True
13667 
13668 Return True if the entry is a directory; cached per entry.
13669 [clinic start generated code]*/
13670 
13671 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13672 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13673                         int follow_symlinks)
13674 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13675 {
13676     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13677 }
13678 
13679 /*[clinic input]
13680 os.DirEntry.is_file -> bool
13681     defining_class: defining_class
13682     /
13683     *
13684     follow_symlinks: bool = True
13685 
13686 Return True if the entry is a file; cached per entry.
13687 [clinic start generated code]*/
13688 
13689 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13690 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13691                          int follow_symlinks)
13692 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13693 {
13694     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13695 }
13696 
13697 /*[clinic input]
13698 os.DirEntry.inode
13699 
13700 Return inode of the entry; cached per entry.
13701 [clinic start generated code]*/
13702 
13703 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13704 os_DirEntry_inode_impl(DirEntry *self)
13705 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13706 {
13707 #ifdef MS_WINDOWS
13708     if (!self->got_file_index) {
13709         PyObject *unicode;
13710         STRUCT_STAT stat;
13711         int result;
13712 
13713         if (!PyUnicode_FSDecoder(self->path, &unicode))
13714             return NULL;
13715 #if USE_UNICODE_WCHAR_CACHE
13716 _Py_COMP_DIAG_PUSH
13717 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13718         const wchar_t *path = PyUnicode_AsUnicode(unicode);
13719         result = LSTAT(path, &stat);
13720         Py_DECREF(unicode);
13721 _Py_COMP_DIAG_POP
13722 #else /* USE_UNICODE_WCHAR_CACHE */
13723         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13724         Py_DECREF(unicode);
13725         result = LSTAT(path, &stat);
13726         PyMem_Free(path);
13727 #endif /* USE_UNICODE_WCHAR_CACHE */
13728 
13729         if (result != 0)
13730             return path_object_error(self->path);
13731 
13732         self->win32_file_index = stat.st_ino;
13733         self->got_file_index = 1;
13734     }
13735     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->win32_file_index));
13736     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13737 #else /* POSIX */
13738     Py_BUILD_ASSERT(sizeof(unsigned long long) >= sizeof(self->d_ino));
13739     return PyLong_FromUnsignedLongLong(self->d_ino);
13740 #endif
13741 }
13742 
13743 static PyObject *
DirEntry_repr(DirEntry * self)13744 DirEntry_repr(DirEntry *self)
13745 {
13746     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13747 }
13748 
13749 /*[clinic input]
13750 os.DirEntry.__fspath__
13751 
13752 Returns the path for the entry.
13753 [clinic start generated code]*/
13754 
13755 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13756 os_DirEntry___fspath___impl(DirEntry *self)
13757 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13758 {
13759     Py_INCREF(self->path);
13760     return self->path;
13761 }
13762 
13763 static PyMemberDef DirEntry_members[] = {
13764     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13765      "the entry's base filename, relative to scandir() \"path\" argument"},
13766     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13767      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13768     {NULL}
13769 };
13770 
13771 #include "clinic/posixmodule.c.h"
13772 
13773 static PyMethodDef DirEntry_methods[] = {
13774     OS_DIRENTRY_IS_DIR_METHODDEF
13775     OS_DIRENTRY_IS_FILE_METHODDEF
13776     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13777     OS_DIRENTRY_STAT_METHODDEF
13778     OS_DIRENTRY_INODE_METHODDEF
13779     OS_DIRENTRY___FSPATH___METHODDEF
13780     {"__class_getitem__",       (PyCFunction)Py_GenericAlias,
13781     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13782     {NULL}
13783 };
13784 
13785 static PyType_Slot DirEntryType_slots[] = {
13786     {Py_tp_dealloc, DirEntry_dealloc},
13787     {Py_tp_repr, DirEntry_repr},
13788     {Py_tp_methods, DirEntry_methods},
13789     {Py_tp_members, DirEntry_members},
13790     {0, 0},
13791 };
13792 
13793 static PyType_Spec DirEntryType_spec = {
13794     MODNAME ".DirEntry",
13795     sizeof(DirEntry),
13796     0,
13797     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13798     DirEntryType_slots
13799 };
13800 
13801 
13802 #ifdef MS_WINDOWS
13803 
13804 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13805 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13806 {
13807     Py_ssize_t path_len;
13808     Py_ssize_t size;
13809     wchar_t *result;
13810     wchar_t ch;
13811 
13812     if (!path_wide) { /* Default arg: "." */
13813         path_wide = L".";
13814         path_len = 1;
13815     }
13816     else {
13817         path_len = wcslen(path_wide);
13818     }
13819 
13820     /* The +1's are for the path separator and the NUL */
13821     size = path_len + 1 + wcslen(filename) + 1;
13822     result = PyMem_New(wchar_t, size);
13823     if (!result) {
13824         PyErr_NoMemory();
13825         return NULL;
13826     }
13827     wcscpy(result, path_wide);
13828     if (path_len > 0) {
13829         ch = result[path_len - 1];
13830         if (ch != SEP && ch != ALTSEP && ch != L':')
13831             result[path_len++] = SEP;
13832         wcscpy(result + path_len, filename);
13833     }
13834     return result;
13835 }
13836 
13837 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)13838 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
13839 {
13840     DirEntry *entry;
13841     BY_HANDLE_FILE_INFORMATION file_info;
13842     ULONG reparse_tag;
13843     wchar_t *joined_path;
13844 
13845     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13846     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13847     if (!entry)
13848         return NULL;
13849     entry->name = NULL;
13850     entry->path = NULL;
13851     entry->stat = NULL;
13852     entry->lstat = NULL;
13853     entry->got_file_index = 0;
13854 
13855     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
13856     if (!entry->name)
13857         goto error;
13858     if (path->narrow) {
13859         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
13860         if (!entry->name)
13861             goto error;
13862     }
13863 
13864     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
13865     if (!joined_path)
13866         goto error;
13867 
13868     entry->path = PyUnicode_FromWideChar(joined_path, -1);
13869     PyMem_Free(joined_path);
13870     if (!entry->path)
13871         goto error;
13872     if (path->narrow) {
13873         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
13874         if (!entry->path)
13875             goto error;
13876     }
13877 
13878     find_data_to_file_info(dataW, &file_info, &reparse_tag);
13879     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
13880 
13881     return (PyObject *)entry;
13882 
13883 error:
13884     Py_DECREF(entry);
13885     return NULL;
13886 }
13887 
13888 #else /* POSIX */
13889 
13890 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)13891 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
13892 {
13893     Py_ssize_t path_len;
13894     Py_ssize_t size;
13895     char *result;
13896 
13897     if (!path_narrow) { /* Default arg: "." */
13898         path_narrow = ".";
13899         path_len = 1;
13900     }
13901     else {
13902         path_len = strlen(path_narrow);
13903     }
13904 
13905     if (filename_len == -1)
13906         filename_len = strlen(filename);
13907 
13908     /* The +1's are for the path separator and the NUL */
13909     size = path_len + 1 + filename_len + 1;
13910     result = PyMem_New(char, size);
13911     if (!result) {
13912         PyErr_NoMemory();
13913         return NULL;
13914     }
13915     strcpy(result, path_narrow);
13916     if (path_len > 0 && result[path_len - 1] != '/')
13917         result[path_len++] = '/';
13918     strcpy(result + path_len, filename);
13919     return result;
13920 }
13921 
13922 static PyObject *
DirEntry_from_posix_info(PyObject * module,path_t * path,const char * name,Py_ssize_t name_len,ino_t d_ino,unsigned char d_type)13923 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
13924                          Py_ssize_t name_len, ino_t d_ino
13925 #ifdef HAVE_DIRENT_D_TYPE
13926                          , unsigned char d_type
13927 #endif
13928                          )
13929 {
13930     DirEntry *entry;
13931     char *joined_path;
13932 
13933     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
13934     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
13935     if (!entry)
13936         return NULL;
13937     entry->name = NULL;
13938     entry->path = NULL;
13939     entry->stat = NULL;
13940     entry->lstat = NULL;
13941 
13942     if (path->fd != -1) {
13943         entry->dir_fd = path->fd;
13944         joined_path = NULL;
13945     }
13946     else {
13947         entry->dir_fd = DEFAULT_DIR_FD;
13948         joined_path = join_path_filename(path->narrow, name, name_len);
13949         if (!joined_path)
13950             goto error;
13951     }
13952 
13953     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
13954         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
13955         if (joined_path)
13956             entry->path = PyUnicode_DecodeFSDefault(joined_path);
13957     }
13958     else {
13959         entry->name = PyBytes_FromStringAndSize(name, name_len);
13960         if (joined_path)
13961             entry->path = PyBytes_FromString(joined_path);
13962     }
13963     PyMem_Free(joined_path);
13964     if (!entry->name)
13965         goto error;
13966 
13967     if (path->fd != -1) {
13968         entry->path = entry->name;
13969         Py_INCREF(entry->path);
13970     }
13971     else if (!entry->path)
13972         goto error;
13973 
13974 #ifdef HAVE_DIRENT_D_TYPE
13975     entry->d_type = d_type;
13976 #endif
13977     entry->d_ino = d_ino;
13978 
13979     return (PyObject *)entry;
13980 
13981 error:
13982     Py_XDECREF(entry);
13983     return NULL;
13984 }
13985 
13986 #endif
13987 
13988 
13989 typedef struct {
13990     PyObject_HEAD
13991     path_t path;
13992 #ifdef MS_WINDOWS
13993     HANDLE handle;
13994     WIN32_FIND_DATAW file_data;
13995     int first_time;
13996 #else /* POSIX */
13997     DIR *dirp;
13998 #endif
13999 #ifdef HAVE_FDOPENDIR
14000     int fd;
14001 #endif
14002 } ScandirIterator;
14003 
14004 #ifdef MS_WINDOWS
14005 
14006 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14007 ScandirIterator_is_closed(ScandirIterator *iterator)
14008 {
14009     return iterator->handle == INVALID_HANDLE_VALUE;
14010 }
14011 
14012 static void
ScandirIterator_closedir(ScandirIterator * iterator)14013 ScandirIterator_closedir(ScandirIterator *iterator)
14014 {
14015     HANDLE handle = iterator->handle;
14016 
14017     if (handle == INVALID_HANDLE_VALUE)
14018         return;
14019 
14020     iterator->handle = INVALID_HANDLE_VALUE;
14021     Py_BEGIN_ALLOW_THREADS
14022     FindClose(handle);
14023     Py_END_ALLOW_THREADS
14024 }
14025 
14026 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14027 ScandirIterator_iternext(ScandirIterator *iterator)
14028 {
14029     WIN32_FIND_DATAW *file_data = &iterator->file_data;
14030     BOOL success;
14031     PyObject *entry;
14032 
14033     /* Happens if the iterator is iterated twice, or closed explicitly */
14034     if (iterator->handle == INVALID_HANDLE_VALUE)
14035         return NULL;
14036 
14037     while (1) {
14038         if (!iterator->first_time) {
14039             Py_BEGIN_ALLOW_THREADS
14040             success = FindNextFileW(iterator->handle, file_data);
14041             Py_END_ALLOW_THREADS
14042             if (!success) {
14043                 /* Error or no more files */
14044                 if (GetLastError() != ERROR_NO_MORE_FILES)
14045                     path_error(&iterator->path);
14046                 break;
14047             }
14048         }
14049         iterator->first_time = 0;
14050 
14051         /* Skip over . and .. */
14052         if (wcscmp(file_data->cFileName, L".") != 0 &&
14053             wcscmp(file_data->cFileName, L"..") != 0)
14054         {
14055             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14056             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14057             if (!entry)
14058                 break;
14059             return entry;
14060         }
14061 
14062         /* Loop till we get a non-dot directory or finish iterating */
14063     }
14064 
14065     /* Error or no more files */
14066     ScandirIterator_closedir(iterator);
14067     return NULL;
14068 }
14069 
14070 #else /* POSIX */
14071 
14072 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14073 ScandirIterator_is_closed(ScandirIterator *iterator)
14074 {
14075     return !iterator->dirp;
14076 }
14077 
14078 static void
ScandirIterator_closedir(ScandirIterator * iterator)14079 ScandirIterator_closedir(ScandirIterator *iterator)
14080 {
14081     DIR *dirp = iterator->dirp;
14082 
14083     if (!dirp)
14084         return;
14085 
14086     iterator->dirp = NULL;
14087     Py_BEGIN_ALLOW_THREADS
14088 #ifdef HAVE_FDOPENDIR
14089     if (iterator->path.fd != -1)
14090         rewinddir(dirp);
14091 #endif
14092     closedir(dirp);
14093     Py_END_ALLOW_THREADS
14094     return;
14095 }
14096 
14097 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14098 ScandirIterator_iternext(ScandirIterator *iterator)
14099 {
14100     struct dirent *direntp;
14101     Py_ssize_t name_len;
14102     int is_dot;
14103     PyObject *entry;
14104 
14105     /* Happens if the iterator is iterated twice, or closed explicitly */
14106     if (!iterator->dirp)
14107         return NULL;
14108 
14109     while (1) {
14110         errno = 0;
14111         Py_BEGIN_ALLOW_THREADS
14112         direntp = readdir(iterator->dirp);
14113         Py_END_ALLOW_THREADS
14114 
14115         if (!direntp) {
14116             /* Error or no more files */
14117             if (errno != 0)
14118                 path_error(&iterator->path);
14119             break;
14120         }
14121 
14122         /* Skip over . and .. */
14123         name_len = NAMLEN(direntp);
14124         is_dot = direntp->d_name[0] == '.' &&
14125                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14126         if (!is_dot) {
14127             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14128             entry = DirEntry_from_posix_info(module,
14129                                              &iterator->path, direntp->d_name,
14130                                              name_len, direntp->d_ino
14131 #ifdef HAVE_DIRENT_D_TYPE
14132                                              , direntp->d_type
14133 #endif
14134                                             );
14135             if (!entry)
14136                 break;
14137             return entry;
14138         }
14139 
14140         /* Loop till we get a non-dot directory or finish iterating */
14141     }
14142 
14143     /* Error or no more files */
14144     ScandirIterator_closedir(iterator);
14145     return NULL;
14146 }
14147 
14148 #endif
14149 
14150 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14151 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14152 {
14153     ScandirIterator_closedir(self);
14154     Py_RETURN_NONE;
14155 }
14156 
14157 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14158 ScandirIterator_enter(PyObject *self, PyObject *args)
14159 {
14160     Py_INCREF(self);
14161     return self;
14162 }
14163 
14164 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14165 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14166 {
14167     ScandirIterator_closedir(self);
14168     Py_RETURN_NONE;
14169 }
14170 
14171 static void
ScandirIterator_finalize(ScandirIterator * iterator)14172 ScandirIterator_finalize(ScandirIterator *iterator)
14173 {
14174     PyObject *error_type, *error_value, *error_traceback;
14175 
14176     /* Save the current exception, if any. */
14177     PyErr_Fetch(&error_type, &error_value, &error_traceback);
14178 
14179     if (!ScandirIterator_is_closed(iterator)) {
14180         ScandirIterator_closedir(iterator);
14181 
14182         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14183                                   "unclosed scandir iterator %R", iterator)) {
14184             /* Spurious errors can appear at shutdown */
14185             if (PyErr_ExceptionMatches(PyExc_Warning)) {
14186                 PyErr_WriteUnraisable((PyObject *) iterator);
14187             }
14188         }
14189     }
14190 
14191     path_cleanup(&iterator->path);
14192 
14193     /* Restore the saved exception. */
14194     PyErr_Restore(error_type, error_value, error_traceback);
14195 }
14196 
14197 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14198 ScandirIterator_dealloc(ScandirIterator *iterator)
14199 {
14200     PyTypeObject *tp = Py_TYPE(iterator);
14201     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14202         return;
14203 
14204     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14205     free_func(iterator);
14206     Py_DECREF(tp);
14207 }
14208 
14209 static PyMethodDef ScandirIterator_methods[] = {
14210     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14211     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14212     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14213     {NULL}
14214 };
14215 
14216 static PyType_Slot ScandirIteratorType_slots[] = {
14217     {Py_tp_dealloc, ScandirIterator_dealloc},
14218     {Py_tp_finalize, ScandirIterator_finalize},
14219     {Py_tp_iter, PyObject_SelfIter},
14220     {Py_tp_iternext, ScandirIterator_iternext},
14221     {Py_tp_methods, ScandirIterator_methods},
14222     {0, 0},
14223 };
14224 
14225 static PyType_Spec ScandirIteratorType_spec = {
14226     MODNAME ".ScandirIterator",
14227     sizeof(ScandirIterator),
14228     0,
14229     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14230     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14231     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14232         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14233     ScandirIteratorType_slots
14234 };
14235 
14236 /*[clinic input]
14237 os.scandir
14238 
14239     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14240 
14241 Return an iterator of DirEntry objects for given path.
14242 
14243 path can be specified as either str, bytes, or a path-like object.  If path
14244 is bytes, the names of yielded DirEntry objects will also be bytes; in
14245 all other circumstances they will be str.
14246 
14247 If path is None, uses the path='.'.
14248 [clinic start generated code]*/
14249 
14250 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14251 os_scandir_impl(PyObject *module, path_t *path)
14252 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14253 {
14254     ScandirIterator *iterator;
14255 #ifdef MS_WINDOWS
14256     wchar_t *path_strW;
14257 #else
14258     const char *path_str;
14259 #ifdef HAVE_FDOPENDIR
14260     int fd = -1;
14261 #endif
14262 #endif
14263 
14264     if (PySys_Audit("os.scandir", "O",
14265                     path->object ? path->object : Py_None) < 0) {
14266         return NULL;
14267     }
14268 
14269     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14270     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14271     if (!iterator)
14272         return NULL;
14273 
14274 #ifdef MS_WINDOWS
14275     iterator->handle = INVALID_HANDLE_VALUE;
14276 #else
14277     iterator->dirp = NULL;
14278 #endif
14279 
14280     /* Move the ownership to iterator->path */
14281     memcpy(&iterator->path, path, sizeof(path_t));
14282     memset(path, 0, sizeof(path_t));
14283 
14284 #ifdef MS_WINDOWS
14285     iterator->first_time = 1;
14286 
14287     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14288     if (!path_strW)
14289         goto error;
14290 
14291     Py_BEGIN_ALLOW_THREADS
14292     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14293     Py_END_ALLOW_THREADS
14294 
14295     PyMem_Free(path_strW);
14296 
14297     if (iterator->handle == INVALID_HANDLE_VALUE) {
14298         path_error(&iterator->path);
14299         goto error;
14300     }
14301 #else /* POSIX */
14302     errno = 0;
14303 #ifdef HAVE_FDOPENDIR
14304     if (iterator->path.fd != -1) {
14305       if (HAVE_FDOPENDIR_RUNTIME) {
14306         /* closedir() closes the FD, so we duplicate it */
14307         fd = _Py_dup(iterator->path.fd);
14308         if (fd == -1)
14309             goto error;
14310 
14311         Py_BEGIN_ALLOW_THREADS
14312         iterator->dirp = fdopendir(fd);
14313         Py_END_ALLOW_THREADS
14314       } else {
14315         PyErr_SetString(PyExc_TypeError,
14316             "scandir: path should be string, bytes, os.PathLike or None, not int");
14317         return NULL;
14318       }
14319     }
14320     else
14321 #endif
14322     {
14323         if (iterator->path.narrow)
14324             path_str = iterator->path.narrow;
14325         else
14326             path_str = ".";
14327 
14328         Py_BEGIN_ALLOW_THREADS
14329         iterator->dirp = opendir(path_str);
14330         Py_END_ALLOW_THREADS
14331     }
14332 
14333     if (!iterator->dirp) {
14334         path_error(&iterator->path);
14335 #ifdef HAVE_FDOPENDIR
14336         if (fd != -1) {
14337             Py_BEGIN_ALLOW_THREADS
14338             close(fd);
14339             Py_END_ALLOW_THREADS
14340         }
14341 #endif
14342         goto error;
14343     }
14344 #endif
14345 
14346     return (PyObject *)iterator;
14347 
14348 error:
14349     Py_DECREF(iterator);
14350     return NULL;
14351 }
14352 
14353 /*
14354     Return the file system path representation of the object.
14355 
14356     If the object is str or bytes, then allow it to pass through with
14357     an incremented refcount. If the object defines __fspath__(), then
14358     return the result of that method. All other types raise a TypeError.
14359 */
14360 PyObject *
PyOS_FSPath(PyObject * path)14361 PyOS_FSPath(PyObject *path)
14362 {
14363     /* For error message reasons, this function is manually inlined in
14364        path_converter(). */
14365     PyObject *func = NULL;
14366     PyObject *path_repr = NULL;
14367 
14368     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14369         Py_INCREF(path);
14370         return path;
14371     }
14372 
14373     func = _PyObject_LookupSpecial(path, &PyId___fspath__);
14374     if (NULL == func) {
14375         return PyErr_Format(PyExc_TypeError,
14376                             "expected str, bytes or os.PathLike object, "
14377                             "not %.200s",
14378                             _PyType_Name(Py_TYPE(path)));
14379     }
14380 
14381     path_repr = _PyObject_CallNoArg(func);
14382     Py_DECREF(func);
14383     if (NULL == path_repr) {
14384         return NULL;
14385     }
14386 
14387     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14388         PyErr_Format(PyExc_TypeError,
14389                      "expected %.200s.__fspath__() to return str or bytes, "
14390                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14391                      _PyType_Name(Py_TYPE(path_repr)));
14392         Py_DECREF(path_repr);
14393         return NULL;
14394     }
14395 
14396     return path_repr;
14397 }
14398 
14399 /*[clinic input]
14400 os.fspath
14401 
14402     path: object
14403 
14404 Return the file system path representation of the object.
14405 
14406 If the object is str or bytes, then allow it to pass through as-is. If the
14407 object defines __fspath__(), then return the result of that method. All other
14408 types raise a TypeError.
14409 [clinic start generated code]*/
14410 
14411 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14412 os_fspath_impl(PyObject *module, PyObject *path)
14413 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14414 {
14415     return PyOS_FSPath(path);
14416 }
14417 
14418 #ifdef HAVE_GETRANDOM_SYSCALL
14419 /*[clinic input]
14420 os.getrandom
14421 
14422     size: Py_ssize_t
14423     flags: int=0
14424 
14425 Obtain a series of random bytes.
14426 [clinic start generated code]*/
14427 
14428 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14429 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14430 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14431 {
14432     PyObject *bytes;
14433     Py_ssize_t n;
14434 
14435     if (size < 0) {
14436         errno = EINVAL;
14437         return posix_error();
14438     }
14439 
14440     bytes = PyBytes_FromStringAndSize(NULL, size);
14441     if (bytes == NULL) {
14442         PyErr_NoMemory();
14443         return NULL;
14444     }
14445 
14446     while (1) {
14447         n = syscall(SYS_getrandom,
14448                     PyBytes_AS_STRING(bytes),
14449                     PyBytes_GET_SIZE(bytes),
14450                     flags);
14451         if (n < 0 && errno == EINTR) {
14452             if (PyErr_CheckSignals() < 0) {
14453                 goto error;
14454             }
14455 
14456             /* getrandom() was interrupted by a signal: retry */
14457             continue;
14458         }
14459         break;
14460     }
14461 
14462     if (n < 0) {
14463         PyErr_SetFromErrno(PyExc_OSError);
14464         goto error;
14465     }
14466 
14467     if (n != size) {
14468         _PyBytes_Resize(&bytes, n);
14469     }
14470 
14471     return bytes;
14472 
14473 error:
14474     Py_DECREF(bytes);
14475     return NULL;
14476 }
14477 #endif   /* HAVE_GETRANDOM_SYSCALL */
14478 
14479 #ifdef MS_WINDOWS
14480 /* bpo-36085: Helper functions for managing DLL search directories
14481  * on win32
14482  */
14483 
14484 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14485 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14486 
14487 /*[clinic input]
14488 os._add_dll_directory
14489 
14490     path: path_t
14491 
14492 Add a path to the DLL search path.
14493 
14494 This search path is used when resolving dependencies for imported
14495 extension modules (the module itself is resolved through sys.path),
14496 and also by ctypes.
14497 
14498 Returns an opaque value that may be passed to os.remove_dll_directory
14499 to remove this directory from the search path.
14500 [clinic start generated code]*/
14501 
14502 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14503 os__add_dll_directory_impl(PyObject *module, path_t *path)
14504 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14505 {
14506     HMODULE hKernel32;
14507     PAddDllDirectory AddDllDirectory;
14508     DLL_DIRECTORY_COOKIE cookie = 0;
14509     DWORD err = 0;
14510 
14511     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14512         return NULL;
14513     }
14514 
14515     /* For Windows 7, we have to load this. As this will be a fairly
14516        infrequent operation, just do it each time. Kernel32 is always
14517        loaded. */
14518     Py_BEGIN_ALLOW_THREADS
14519     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14520         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14521             hKernel32, "AddDllDirectory")) ||
14522         !(cookie = (*AddDllDirectory)(path->wide))) {
14523         err = GetLastError();
14524     }
14525     Py_END_ALLOW_THREADS
14526 
14527     if (err) {
14528         return win32_error_object_err("add_dll_directory",
14529                                       path->object, err);
14530     }
14531 
14532     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14533 }
14534 
14535 /*[clinic input]
14536 os._remove_dll_directory
14537 
14538     cookie: object
14539 
14540 Removes a path from the DLL search path.
14541 
14542 The parameter is an opaque value that was returned from
14543 os.add_dll_directory. You can only remove directories that you added
14544 yourself.
14545 [clinic start generated code]*/
14546 
14547 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14548 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14549 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14550 {
14551     HMODULE hKernel32;
14552     PRemoveDllDirectory RemoveDllDirectory;
14553     DLL_DIRECTORY_COOKIE cookieValue;
14554     DWORD err = 0;
14555 
14556     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14557         PyErr_SetString(PyExc_TypeError,
14558             "Provided cookie was not returned from os.add_dll_directory");
14559         return NULL;
14560     }
14561 
14562     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14563         cookie, "DLL directory cookie");
14564 
14565     /* For Windows 7, we have to load this. As this will be a fairly
14566        infrequent operation, just do it each time. Kernel32 is always
14567        loaded. */
14568     Py_BEGIN_ALLOW_THREADS
14569     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14570         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14571             hKernel32, "RemoveDllDirectory")) ||
14572         !(*RemoveDllDirectory)(cookieValue)) {
14573         err = GetLastError();
14574     }
14575     Py_END_ALLOW_THREADS
14576 
14577     if (err) {
14578         return win32_error_object_err("remove_dll_directory",
14579                                       NULL, err);
14580     }
14581 
14582     if (PyCapsule_SetName(cookie, NULL)) {
14583         return NULL;
14584     }
14585 
14586     Py_RETURN_NONE;
14587 }
14588 
14589 #endif
14590 
14591 
14592 /* Only check if WIFEXITED is available: expect that it comes
14593    with WEXITSTATUS, WIFSIGNALED, etc.
14594 
14595    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14596    subprocess can safely call it during late Python finalization without
14597    risking that used os attributes were set to None by finalize_modules(). */
14598 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14599 /*[clinic input]
14600 os.waitstatus_to_exitcode
14601 
14602     status as status_obj: object
14603 
14604 Convert a wait status to an exit code.
14605 
14606 On Unix:
14607 
14608 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14609 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14610 * Otherwise, raise a ValueError.
14611 
14612 On Windows, return status shifted right by 8 bits.
14613 
14614 On Unix, if the process is being traced or if waitpid() was called with
14615 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14616 This function must not be called if WIFSTOPPED(status) is true.
14617 [clinic start generated code]*/
14618 
14619 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14620 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14621 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14622 {
14623 #ifndef MS_WINDOWS
14624     int status = _PyLong_AsInt(status_obj);
14625     if (status == -1 && PyErr_Occurred()) {
14626         return NULL;
14627     }
14628 
14629     WAIT_TYPE wait_status;
14630     WAIT_STATUS_INT(wait_status) = status;
14631     int exitcode;
14632     if (WIFEXITED(wait_status)) {
14633         exitcode = WEXITSTATUS(wait_status);
14634         /* Sanity check to provide warranty on the function behavior.
14635            It should not occur in practice */
14636         if (exitcode < 0) {
14637             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14638             return NULL;
14639         }
14640     }
14641     else if (WIFSIGNALED(wait_status)) {
14642         int signum = WTERMSIG(wait_status);
14643         /* Sanity check to provide warranty on the function behavior.
14644            It should not occurs in practice */
14645         if (signum <= 0) {
14646             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14647             return NULL;
14648         }
14649         exitcode = -signum;
14650     } else if (WIFSTOPPED(wait_status)) {
14651         /* Status only received if the process is being traced
14652            or if waitpid() was called with WUNTRACED option. */
14653         int signum = WSTOPSIG(wait_status);
14654         PyErr_Format(PyExc_ValueError,
14655                      "process stopped by delivery of signal %i",
14656                      signum);
14657         return NULL;
14658     }
14659     else {
14660         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14661         return NULL;
14662     }
14663     return PyLong_FromLong(exitcode);
14664 #else
14665     /* Windows implementation: see os.waitpid() implementation
14666        which uses _cwait(). */
14667     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14668     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14669         return NULL;
14670     }
14671 
14672     unsigned long long exitcode = (status >> 8);
14673     /* ExitProcess() accepts an UINT type:
14674        reject exit code which doesn't fit in an UINT */
14675     if (exitcode > UINT_MAX) {
14676         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14677         return NULL;
14678     }
14679     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14680 #endif
14681 }
14682 #endif
14683 
14684 
14685 static PyMethodDef posix_methods[] = {
14686 
14687     OS_STAT_METHODDEF
14688     OS_ACCESS_METHODDEF
14689     OS_TTYNAME_METHODDEF
14690     OS_CHDIR_METHODDEF
14691     OS_CHFLAGS_METHODDEF
14692     OS_CHMOD_METHODDEF
14693     OS_FCHMOD_METHODDEF
14694     OS_LCHMOD_METHODDEF
14695     OS_CHOWN_METHODDEF
14696     OS_FCHOWN_METHODDEF
14697     OS_LCHOWN_METHODDEF
14698     OS_LCHFLAGS_METHODDEF
14699     OS_CHROOT_METHODDEF
14700     OS_CTERMID_METHODDEF
14701     OS_GETCWD_METHODDEF
14702     OS_GETCWDB_METHODDEF
14703     OS_LINK_METHODDEF
14704     OS_LISTDIR_METHODDEF
14705     OS_LSTAT_METHODDEF
14706     OS_MKDIR_METHODDEF
14707     OS_NICE_METHODDEF
14708     OS_GETPRIORITY_METHODDEF
14709     OS_SETPRIORITY_METHODDEF
14710     OS_POSIX_SPAWN_METHODDEF
14711     OS_POSIX_SPAWNP_METHODDEF
14712     OS_READLINK_METHODDEF
14713     OS_COPY_FILE_RANGE_METHODDEF
14714     OS_SPLICE_METHODDEF
14715     OS_RENAME_METHODDEF
14716     OS_REPLACE_METHODDEF
14717     OS_RMDIR_METHODDEF
14718     OS_SYMLINK_METHODDEF
14719     OS_SYSTEM_METHODDEF
14720     OS_UMASK_METHODDEF
14721     OS_UNAME_METHODDEF
14722     OS_UNLINK_METHODDEF
14723     OS_REMOVE_METHODDEF
14724     OS_UTIME_METHODDEF
14725     OS_TIMES_METHODDEF
14726     OS__EXIT_METHODDEF
14727     OS__FCOPYFILE_METHODDEF
14728     OS_EXECV_METHODDEF
14729     OS_EXECVE_METHODDEF
14730     OS_SPAWNV_METHODDEF
14731     OS_SPAWNVE_METHODDEF
14732     OS_FORK1_METHODDEF
14733     OS_FORK_METHODDEF
14734     OS_REGISTER_AT_FORK_METHODDEF
14735     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14736     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14737     OS_SCHED_GETPARAM_METHODDEF
14738     OS_SCHED_GETSCHEDULER_METHODDEF
14739     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14740     OS_SCHED_SETPARAM_METHODDEF
14741     OS_SCHED_SETSCHEDULER_METHODDEF
14742     OS_SCHED_YIELD_METHODDEF
14743     OS_SCHED_SETAFFINITY_METHODDEF
14744     OS_SCHED_GETAFFINITY_METHODDEF
14745     OS_OPENPTY_METHODDEF
14746     OS_FORKPTY_METHODDEF
14747     OS_GETEGID_METHODDEF
14748     OS_GETEUID_METHODDEF
14749     OS_GETGID_METHODDEF
14750     OS_GETGROUPLIST_METHODDEF
14751     OS_GETGROUPS_METHODDEF
14752     OS_GETPID_METHODDEF
14753     OS_GETPGRP_METHODDEF
14754     OS_GETPPID_METHODDEF
14755     OS_GETUID_METHODDEF
14756     OS_GETLOGIN_METHODDEF
14757     OS_KILL_METHODDEF
14758     OS_KILLPG_METHODDEF
14759     OS_PLOCK_METHODDEF
14760     OS_STARTFILE_METHODDEF
14761     OS_SETUID_METHODDEF
14762     OS_SETEUID_METHODDEF
14763     OS_SETREUID_METHODDEF
14764     OS_SETGID_METHODDEF
14765     OS_SETEGID_METHODDEF
14766     OS_SETREGID_METHODDEF
14767     OS_SETGROUPS_METHODDEF
14768     OS_INITGROUPS_METHODDEF
14769     OS_GETPGID_METHODDEF
14770     OS_SETPGRP_METHODDEF
14771     OS_WAIT_METHODDEF
14772     OS_WAIT3_METHODDEF
14773     OS_WAIT4_METHODDEF
14774     OS_WAITID_METHODDEF
14775     OS_WAITPID_METHODDEF
14776     OS_PIDFD_OPEN_METHODDEF
14777     OS_GETSID_METHODDEF
14778     OS_SETSID_METHODDEF
14779     OS_SETPGID_METHODDEF
14780     OS_TCGETPGRP_METHODDEF
14781     OS_TCSETPGRP_METHODDEF
14782     OS_OPEN_METHODDEF
14783     OS_CLOSE_METHODDEF
14784     OS_CLOSERANGE_METHODDEF
14785     OS_DEVICE_ENCODING_METHODDEF
14786     OS_DUP_METHODDEF
14787     OS_DUP2_METHODDEF
14788     OS_LOCKF_METHODDEF
14789     OS_LSEEK_METHODDEF
14790     OS_READ_METHODDEF
14791     OS_READV_METHODDEF
14792     OS_PREAD_METHODDEF
14793     OS_PREADV_METHODDEF
14794     OS_WRITE_METHODDEF
14795     OS_WRITEV_METHODDEF
14796     OS_PWRITE_METHODDEF
14797     OS_PWRITEV_METHODDEF
14798     OS_SENDFILE_METHODDEF
14799     OS_FSTAT_METHODDEF
14800     OS_ISATTY_METHODDEF
14801     OS_PIPE_METHODDEF
14802     OS_PIPE2_METHODDEF
14803     OS_MKFIFO_METHODDEF
14804     OS_MKNOD_METHODDEF
14805     OS_MAJOR_METHODDEF
14806     OS_MINOR_METHODDEF
14807     OS_MAKEDEV_METHODDEF
14808     OS_FTRUNCATE_METHODDEF
14809     OS_TRUNCATE_METHODDEF
14810     OS_POSIX_FALLOCATE_METHODDEF
14811     OS_POSIX_FADVISE_METHODDEF
14812     OS_PUTENV_METHODDEF
14813     OS_UNSETENV_METHODDEF
14814     OS_STRERROR_METHODDEF
14815     OS_FCHDIR_METHODDEF
14816     OS_FSYNC_METHODDEF
14817     OS_SYNC_METHODDEF
14818     OS_FDATASYNC_METHODDEF
14819     OS_WCOREDUMP_METHODDEF
14820     OS_WIFCONTINUED_METHODDEF
14821     OS_WIFSTOPPED_METHODDEF
14822     OS_WIFSIGNALED_METHODDEF
14823     OS_WIFEXITED_METHODDEF
14824     OS_WEXITSTATUS_METHODDEF
14825     OS_WTERMSIG_METHODDEF
14826     OS_WSTOPSIG_METHODDEF
14827     OS_FSTATVFS_METHODDEF
14828     OS_STATVFS_METHODDEF
14829     OS_CONFSTR_METHODDEF
14830     OS_SYSCONF_METHODDEF
14831     OS_FPATHCONF_METHODDEF
14832     OS_PATHCONF_METHODDEF
14833     OS_ABORT_METHODDEF
14834     OS__GETFULLPATHNAME_METHODDEF
14835     OS__GETDISKUSAGE_METHODDEF
14836     OS__GETFINALPATHNAME_METHODDEF
14837     OS__GETVOLUMEPATHNAME_METHODDEF
14838     OS__PATH_SPLITROOT_METHODDEF
14839     OS_GETLOADAVG_METHODDEF
14840     OS_URANDOM_METHODDEF
14841     OS_SETRESUID_METHODDEF
14842     OS_SETRESGID_METHODDEF
14843     OS_GETRESUID_METHODDEF
14844     OS_GETRESGID_METHODDEF
14845 
14846     OS_GETXATTR_METHODDEF
14847     OS_SETXATTR_METHODDEF
14848     OS_REMOVEXATTR_METHODDEF
14849     OS_LISTXATTR_METHODDEF
14850 
14851     OS_GET_TERMINAL_SIZE_METHODDEF
14852     OS_CPU_COUNT_METHODDEF
14853     OS_GET_INHERITABLE_METHODDEF
14854     OS_SET_INHERITABLE_METHODDEF
14855     OS_GET_HANDLE_INHERITABLE_METHODDEF
14856     OS_SET_HANDLE_INHERITABLE_METHODDEF
14857     OS_GET_BLOCKING_METHODDEF
14858     OS_SET_BLOCKING_METHODDEF
14859     OS_SCANDIR_METHODDEF
14860     OS_FSPATH_METHODDEF
14861     OS_GETRANDOM_METHODDEF
14862     OS_MEMFD_CREATE_METHODDEF
14863     OS_EVENTFD_METHODDEF
14864     OS_EVENTFD_READ_METHODDEF
14865     OS_EVENTFD_WRITE_METHODDEF
14866     OS__ADD_DLL_DIRECTORY_METHODDEF
14867     OS__REMOVE_DLL_DIRECTORY_METHODDEF
14868     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
14869     {NULL,              NULL}            /* Sentinel */
14870 };
14871 
14872 static int
all_ins(PyObject * m)14873 all_ins(PyObject *m)
14874 {
14875 #ifdef F_OK
14876     if (PyModule_AddIntMacro(m, F_OK)) return -1;
14877 #endif
14878 #ifdef R_OK
14879     if (PyModule_AddIntMacro(m, R_OK)) return -1;
14880 #endif
14881 #ifdef W_OK
14882     if (PyModule_AddIntMacro(m, W_OK)) return -1;
14883 #endif
14884 #ifdef X_OK
14885     if (PyModule_AddIntMacro(m, X_OK)) return -1;
14886 #endif
14887 #ifdef NGROUPS_MAX
14888     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
14889 #endif
14890 #ifdef TMP_MAX
14891     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
14892 #endif
14893 #ifdef WCONTINUED
14894     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
14895 #endif
14896 #ifdef WNOHANG
14897     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
14898 #endif
14899 #ifdef WUNTRACED
14900     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
14901 #endif
14902 #ifdef O_RDONLY
14903     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
14904 #endif
14905 #ifdef O_WRONLY
14906     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
14907 #endif
14908 #ifdef O_RDWR
14909     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
14910 #endif
14911 #ifdef O_NDELAY
14912     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
14913 #endif
14914 #ifdef O_NONBLOCK
14915     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
14916 #endif
14917 #ifdef O_APPEND
14918     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
14919 #endif
14920 #ifdef O_DSYNC
14921     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
14922 #endif
14923 #ifdef O_RSYNC
14924     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
14925 #endif
14926 #ifdef O_SYNC
14927     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
14928 #endif
14929 #ifdef O_NOCTTY
14930     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
14931 #endif
14932 #ifdef O_CREAT
14933     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
14934 #endif
14935 #ifdef O_EXCL
14936     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
14937 #endif
14938 #ifdef O_TRUNC
14939     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
14940 #endif
14941 #ifdef O_BINARY
14942     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
14943 #endif
14944 #ifdef O_TEXT
14945     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
14946 #endif
14947 #ifdef O_XATTR
14948     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
14949 #endif
14950 #ifdef O_LARGEFILE
14951     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
14952 #endif
14953 #ifndef __GNU__
14954 #ifdef O_SHLOCK
14955     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
14956 #endif
14957 #ifdef O_EXLOCK
14958     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
14959 #endif
14960 #endif
14961 #ifdef O_EXEC
14962     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
14963 #endif
14964 #ifdef O_SEARCH
14965     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
14966 #endif
14967 #ifdef O_PATH
14968     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
14969 #endif
14970 #ifdef O_TTY_INIT
14971     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
14972 #endif
14973 #ifdef O_TMPFILE
14974     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
14975 #endif
14976 #ifdef PRIO_PROCESS
14977     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
14978 #endif
14979 #ifdef PRIO_PGRP
14980     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
14981 #endif
14982 #ifdef PRIO_USER
14983     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
14984 #endif
14985 #ifdef O_CLOEXEC
14986     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
14987 #endif
14988 #ifdef O_ACCMODE
14989     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
14990 #endif
14991 #ifdef O_EVTONLY
14992     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
14993 #endif
14994 #ifdef O_FSYNC
14995     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
14996 #endif
14997 #ifdef O_SYMLINK
14998     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
14999 #endif
15000 
15001 #ifdef SEEK_HOLE
15002     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15003 #endif
15004 #ifdef SEEK_DATA
15005     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15006 #endif
15007 
15008 /* MS Windows */
15009 #ifdef O_NOINHERIT
15010     /* Don't inherit in child processes. */
15011     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15012 #endif
15013 #ifdef _O_SHORT_LIVED
15014     /* Optimize for short life (keep in memory). */
15015     /* MS forgot to define this one with a non-underscore form too. */
15016     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15017 #endif
15018 #ifdef O_TEMPORARY
15019     /* Automatically delete when last handle is closed. */
15020     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15021 #endif
15022 #ifdef O_RANDOM
15023     /* Optimize for random access. */
15024     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15025 #endif
15026 #ifdef O_SEQUENTIAL
15027     /* Optimize for sequential access. */
15028     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15029 #endif
15030 
15031 /* GNU extensions. */
15032 #ifdef O_ASYNC
15033     /* Send a SIGIO signal whenever input or output
15034        becomes available on file descriptor */
15035     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15036 #endif
15037 #ifdef O_DIRECT
15038     /* Direct disk access. */
15039     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15040 #endif
15041 #ifdef O_DIRECTORY
15042     /* Must be a directory.      */
15043     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15044 #endif
15045 #ifdef O_NOFOLLOW
15046     /* Do not follow links.      */
15047     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15048 #endif
15049 #ifdef O_NOFOLLOW_ANY
15050     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15051 #endif
15052 #ifdef O_NOLINKS
15053     /* Fails if link count of the named file is greater than 1 */
15054     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15055 #endif
15056 #ifdef O_NOATIME
15057     /* Do not update the access time. */
15058     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15059 #endif
15060 
15061     /* These come from sysexits.h */
15062 #ifdef EX_OK
15063     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15064 #endif /* EX_OK */
15065 #ifdef EX_USAGE
15066     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15067 #endif /* EX_USAGE */
15068 #ifdef EX_DATAERR
15069     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15070 #endif /* EX_DATAERR */
15071 #ifdef EX_NOINPUT
15072     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15073 #endif /* EX_NOINPUT */
15074 #ifdef EX_NOUSER
15075     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15076 #endif /* EX_NOUSER */
15077 #ifdef EX_NOHOST
15078     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15079 #endif /* EX_NOHOST */
15080 #ifdef EX_UNAVAILABLE
15081     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15082 #endif /* EX_UNAVAILABLE */
15083 #ifdef EX_SOFTWARE
15084     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15085 #endif /* EX_SOFTWARE */
15086 #ifdef EX_OSERR
15087     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15088 #endif /* EX_OSERR */
15089 #ifdef EX_OSFILE
15090     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15091 #endif /* EX_OSFILE */
15092 #ifdef EX_CANTCREAT
15093     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15094 #endif /* EX_CANTCREAT */
15095 #ifdef EX_IOERR
15096     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15097 #endif /* EX_IOERR */
15098 #ifdef EX_TEMPFAIL
15099     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15100 #endif /* EX_TEMPFAIL */
15101 #ifdef EX_PROTOCOL
15102     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15103 #endif /* EX_PROTOCOL */
15104 #ifdef EX_NOPERM
15105     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15106 #endif /* EX_NOPERM */
15107 #ifdef EX_CONFIG
15108     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15109 #endif /* EX_CONFIG */
15110 #ifdef EX_NOTFOUND
15111     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15112 #endif /* EX_NOTFOUND */
15113 
15114     /* statvfs */
15115 #ifdef ST_RDONLY
15116     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15117 #endif /* ST_RDONLY */
15118 #ifdef ST_NOSUID
15119     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15120 #endif /* ST_NOSUID */
15121 
15122        /* GNU extensions */
15123 #ifdef ST_NODEV
15124     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15125 #endif /* ST_NODEV */
15126 #ifdef ST_NOEXEC
15127     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15128 #endif /* ST_NOEXEC */
15129 #ifdef ST_SYNCHRONOUS
15130     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15131 #endif /* ST_SYNCHRONOUS */
15132 #ifdef ST_MANDLOCK
15133     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15134 #endif /* ST_MANDLOCK */
15135 #ifdef ST_WRITE
15136     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15137 #endif /* ST_WRITE */
15138 #ifdef ST_APPEND
15139     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15140 #endif /* ST_APPEND */
15141 #ifdef ST_NOATIME
15142     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15143 #endif /* ST_NOATIME */
15144 #ifdef ST_NODIRATIME
15145     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15146 #endif /* ST_NODIRATIME */
15147 #ifdef ST_RELATIME
15148     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15149 #endif /* ST_RELATIME */
15150 
15151     /* FreeBSD sendfile() constants */
15152 #ifdef SF_NODISKIO
15153     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15154 #endif
15155 #ifdef SF_MNOWAIT
15156     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15157 #endif
15158 #ifdef SF_SYNC
15159     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15160 #endif
15161 
15162     /* constants for posix_fadvise */
15163 #ifdef POSIX_FADV_NORMAL
15164     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15165 #endif
15166 #ifdef POSIX_FADV_SEQUENTIAL
15167     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15168 #endif
15169 #ifdef POSIX_FADV_RANDOM
15170     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15171 #endif
15172 #ifdef POSIX_FADV_NOREUSE
15173     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15174 #endif
15175 #ifdef POSIX_FADV_WILLNEED
15176     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15177 #endif
15178 #ifdef POSIX_FADV_DONTNEED
15179     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15180 #endif
15181 
15182     /* constants for waitid */
15183 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15184     if (PyModule_AddIntMacro(m, P_PID)) return -1;
15185     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15186     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15187 #ifdef P_PIDFD
15188     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15189 #endif
15190 #endif
15191 #ifdef WEXITED
15192     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15193 #endif
15194 #ifdef WNOWAIT
15195     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15196 #endif
15197 #ifdef WSTOPPED
15198     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15199 #endif
15200 #ifdef CLD_EXITED
15201     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15202 #endif
15203 #ifdef CLD_KILLED
15204     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15205 #endif
15206 #ifdef CLD_DUMPED
15207     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15208 #endif
15209 #ifdef CLD_TRAPPED
15210     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15211 #endif
15212 #ifdef CLD_STOPPED
15213     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15214 #endif
15215 #ifdef CLD_CONTINUED
15216     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15217 #endif
15218 
15219     /* constants for lockf */
15220 #ifdef F_LOCK
15221     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15222 #endif
15223 #ifdef F_TLOCK
15224     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15225 #endif
15226 #ifdef F_ULOCK
15227     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15228 #endif
15229 #ifdef F_TEST
15230     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15231 #endif
15232 
15233 #ifdef RWF_DSYNC
15234     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15235 #endif
15236 #ifdef RWF_HIPRI
15237     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15238 #endif
15239 #ifdef RWF_SYNC
15240     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15241 #endif
15242 #ifdef RWF_NOWAIT
15243     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15244 #endif
15245 #ifdef RWF_APPEND
15246     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15247 #endif
15248 
15249 /* constants for splice */
15250 #if defined(HAVE_SPLICE) && defined(__linux__)
15251     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15252     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15253     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15254 #endif
15255 
15256 /* constants for posix_spawn */
15257 #ifdef HAVE_POSIX_SPAWN
15258     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15259     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15260     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15261 #endif
15262 
15263 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15264     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15265     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15266     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15267 #endif
15268 #ifdef HAVE_SPAWNV
15269     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15270     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15271 #endif
15272 
15273 #ifdef HAVE_SCHED_H
15274 #ifdef SCHED_OTHER
15275     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15276 #endif
15277 #ifdef SCHED_FIFO
15278     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15279 #endif
15280 #ifdef SCHED_RR
15281     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15282 #endif
15283 #ifdef SCHED_SPORADIC
15284     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15285 #endif
15286 #ifdef SCHED_BATCH
15287     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15288 #endif
15289 #ifdef SCHED_IDLE
15290     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15291 #endif
15292 #ifdef SCHED_RESET_ON_FORK
15293     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15294 #endif
15295 #ifdef SCHED_SYS
15296     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15297 #endif
15298 #ifdef SCHED_IA
15299     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15300 #endif
15301 #ifdef SCHED_FSS
15302     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15303 #endif
15304 #ifdef SCHED_FX
15305     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15306 #endif
15307 #endif
15308 
15309 #ifdef USE_XATTRS
15310     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15311     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15312     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15313 #endif
15314 
15315 #if HAVE_DECL_RTLD_LAZY
15316     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15317 #endif
15318 #if HAVE_DECL_RTLD_NOW
15319     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15320 #endif
15321 #if HAVE_DECL_RTLD_GLOBAL
15322     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15323 #endif
15324 #if HAVE_DECL_RTLD_LOCAL
15325     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15326 #endif
15327 #if HAVE_DECL_RTLD_NODELETE
15328     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15329 #endif
15330 #if HAVE_DECL_RTLD_NOLOAD
15331     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15332 #endif
15333 #if HAVE_DECL_RTLD_DEEPBIND
15334     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15335 #endif
15336 #if HAVE_DECL_RTLD_MEMBER
15337     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15338 #endif
15339 
15340 #ifdef HAVE_GETRANDOM_SYSCALL
15341     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15342     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15343 #endif
15344 #ifdef HAVE_MEMFD_CREATE
15345     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15346     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15347 #ifdef MFD_HUGETLB
15348     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15349 #endif
15350 #ifdef MFD_HUGE_SHIFT
15351     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15352 #endif
15353 #ifdef MFD_HUGE_MASK
15354     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15355 #endif
15356 #ifdef MFD_HUGE_64KB
15357     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15358 #endif
15359 #ifdef MFD_HUGE_512KB
15360     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15361 #endif
15362 #ifdef MFD_HUGE_1MB
15363     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15364 #endif
15365 #ifdef MFD_HUGE_2MB
15366     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15367 #endif
15368 #ifdef MFD_HUGE_8MB
15369     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15370 #endif
15371 #ifdef MFD_HUGE_16MB
15372     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15373 #endif
15374 #ifdef MFD_HUGE_32MB
15375     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15376 #endif
15377 #ifdef MFD_HUGE_256MB
15378     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15379 #endif
15380 #ifdef MFD_HUGE_512MB
15381     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15382 #endif
15383 #ifdef MFD_HUGE_1GB
15384     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15385 #endif
15386 #ifdef MFD_HUGE_2GB
15387     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15388 #endif
15389 #ifdef MFD_HUGE_16GB
15390     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15391 #endif
15392 #endif /* HAVE_MEMFD_CREATE */
15393 
15394 #ifdef HAVE_EVENTFD
15395     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15396     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15397     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15398 #endif
15399 
15400 #if defined(__APPLE__)
15401     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15402 #endif
15403 
15404 #ifdef MS_WINDOWS
15405     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15406     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15407     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15408     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15409     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15410 #endif
15411 
15412     return 0;
15413 }
15414 
15415 
15416 
15417 #define PROBE(name, test) \
15418    static int name(void)  \
15419    {                      \
15420       if (test) {        \
15421           return 1;       \
15422       } else {            \
15423           return 0;       \
15424       }                   \
15425    }
15426 
15427 #ifdef HAVE_FSTATAT
15428 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15429 #endif
15430 
15431 #ifdef HAVE_FACCESSAT
15432 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15433 #endif
15434 
15435 #ifdef HAVE_FCHMODAT
15436 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15437 #endif
15438 
15439 #ifdef HAVE_FCHOWNAT
15440 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15441 #endif
15442 
15443 #ifdef HAVE_LINKAT
15444 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15445 #endif
15446 
15447 #ifdef HAVE_FDOPENDIR
15448 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15449 #endif
15450 
15451 #ifdef HAVE_MKDIRAT
15452 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15453 #endif
15454 
15455 #ifdef HAVE_RENAMEAT
15456 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15457 #endif
15458 
15459 #ifdef HAVE_UNLINKAT
15460 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15461 #endif
15462 
15463 #ifdef HAVE_OPENAT
15464 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15465 #endif
15466 
15467 #ifdef HAVE_READLINKAT
15468 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15469 #endif
15470 
15471 #ifdef HAVE_SYMLINKAT
15472 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15473 #endif
15474 
15475 #ifdef HAVE_FUTIMENS
15476 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15477 #endif
15478 
15479 #ifdef HAVE_UTIMENSAT
15480 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15481 #endif
15482 
15483 
15484 
15485 
15486 static const struct have_function {
15487     const char * const label;
15488     int (*probe)(void);
15489 } have_functions[] = {
15490 
15491 #ifdef HAVE_EVENTFD
15492     {"HAVE_EVENTFD", NULL},
15493 #endif
15494 
15495 #ifdef HAVE_FACCESSAT
15496     { "HAVE_FACCESSAT", probe_faccessat },
15497 #endif
15498 
15499 #ifdef HAVE_FCHDIR
15500     { "HAVE_FCHDIR", NULL },
15501 #endif
15502 
15503 #ifdef HAVE_FCHMOD
15504     { "HAVE_FCHMOD", NULL },
15505 #endif
15506 
15507 #ifdef HAVE_FCHMODAT
15508     { "HAVE_FCHMODAT", probe_fchmodat },
15509 #endif
15510 
15511 #ifdef HAVE_FCHOWN
15512     { "HAVE_FCHOWN", NULL },
15513 #endif
15514 
15515 #ifdef HAVE_FCHOWNAT
15516     { "HAVE_FCHOWNAT", probe_fchownat },
15517 #endif
15518 
15519 #ifdef HAVE_FEXECVE
15520     { "HAVE_FEXECVE", NULL },
15521 #endif
15522 
15523 #ifdef HAVE_FDOPENDIR
15524     { "HAVE_FDOPENDIR", probe_fdopendir },
15525 #endif
15526 
15527 #ifdef HAVE_FPATHCONF
15528     { "HAVE_FPATHCONF", NULL },
15529 #endif
15530 
15531 #ifdef HAVE_FSTATAT
15532     { "HAVE_FSTATAT", probe_fstatat },
15533 #endif
15534 
15535 #ifdef HAVE_FSTATVFS
15536     { "HAVE_FSTATVFS", NULL },
15537 #endif
15538 
15539 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15540     { "HAVE_FTRUNCATE", NULL },
15541 #endif
15542 
15543 #ifdef HAVE_FUTIMENS
15544     { "HAVE_FUTIMENS", probe_futimens },
15545 #endif
15546 
15547 #ifdef HAVE_FUTIMES
15548     { "HAVE_FUTIMES", NULL },
15549 #endif
15550 
15551 #ifdef HAVE_FUTIMESAT
15552     { "HAVE_FUTIMESAT", NULL },
15553 #endif
15554 
15555 #ifdef HAVE_LINKAT
15556     { "HAVE_LINKAT", probe_linkat },
15557 #endif
15558 
15559 #ifdef HAVE_LCHFLAGS
15560     { "HAVE_LCHFLAGS", NULL },
15561 #endif
15562 
15563 #ifdef HAVE_LCHMOD
15564     { "HAVE_LCHMOD", NULL },
15565 #endif
15566 
15567 #ifdef HAVE_LCHOWN
15568     { "HAVE_LCHOWN", NULL },
15569 #endif
15570 
15571 #ifdef HAVE_LSTAT
15572     { "HAVE_LSTAT", NULL },
15573 #endif
15574 
15575 #ifdef HAVE_LUTIMES
15576     { "HAVE_LUTIMES", NULL },
15577 #endif
15578 
15579 #ifdef HAVE_MEMFD_CREATE
15580     { "HAVE_MEMFD_CREATE", NULL },
15581 #endif
15582 
15583 #ifdef HAVE_MKDIRAT
15584     { "HAVE_MKDIRAT", probe_mkdirat },
15585 #endif
15586 
15587 #ifdef HAVE_MKFIFOAT
15588     { "HAVE_MKFIFOAT", NULL },
15589 #endif
15590 
15591 #ifdef HAVE_MKNODAT
15592     { "HAVE_MKNODAT", NULL },
15593 #endif
15594 
15595 #ifdef HAVE_OPENAT
15596     { "HAVE_OPENAT", probe_openat },
15597 #endif
15598 
15599 #ifdef HAVE_READLINKAT
15600     { "HAVE_READLINKAT", probe_readlinkat },
15601 #endif
15602 
15603 #ifdef HAVE_RENAMEAT
15604     { "HAVE_RENAMEAT", probe_renameat },
15605 #endif
15606 
15607 #ifdef HAVE_SYMLINKAT
15608     { "HAVE_SYMLINKAT", probe_symlinkat },
15609 #endif
15610 
15611 #ifdef HAVE_UNLINKAT
15612     { "HAVE_UNLINKAT", probe_unlinkat },
15613 #endif
15614 
15615 #ifdef HAVE_UTIMENSAT
15616     { "HAVE_UTIMENSAT", probe_utimensat },
15617 #endif
15618 
15619 #ifdef MS_WINDOWS
15620     { "MS_WINDOWS", NULL },
15621 #endif
15622 
15623     { NULL, NULL }
15624 };
15625 
15626 
15627 static int
posixmodule_exec(PyObject * m)15628 posixmodule_exec(PyObject *m)
15629 {
15630     _posixstate *state = get_posix_state(m);
15631 
15632 #if defined(HAVE_PWRITEV)
15633     if (HAVE_PWRITEV_RUNTIME) {} else {
15634         PyObject* dct = PyModule_GetDict(m);
15635 
15636         if (dct == NULL) {
15637             return -1;
15638         }
15639 
15640         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15641             PyErr_Clear();
15642         }
15643         if (PyDict_DelItemString(dct, "preadv") == -1) {
15644             PyErr_Clear();
15645         }
15646     }
15647 #endif
15648 
15649     /* Initialize environ dictionary */
15650     PyObject *v = convertenviron();
15651     Py_XINCREF(v);
15652     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15653         return -1;
15654     Py_DECREF(v);
15655 
15656     if (all_ins(m))
15657         return -1;
15658 
15659     if (setup_confname_tables(m))
15660         return -1;
15661 
15662     Py_INCREF(PyExc_OSError);
15663     PyModule_AddObject(m, "error", PyExc_OSError);
15664 
15665 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15666     waitid_result_desc.name = MODNAME ".waitid_result";
15667     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15668     if (WaitidResultType == NULL) {
15669         return -1;
15670     }
15671     Py_INCREF(WaitidResultType);
15672     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15673     state->WaitidResultType = WaitidResultType;
15674 #endif
15675 
15676     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15677     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15678     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15679     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15680     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15681     if (StatResultType == NULL) {
15682         return -1;
15683     }
15684     Py_INCREF(StatResultType);
15685     PyModule_AddObject(m, "stat_result", StatResultType);
15686     state->StatResultType = StatResultType;
15687     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15688     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15689 
15690     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15691     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15692     if (StatVFSResultType == NULL) {
15693         return -1;
15694     }
15695     Py_INCREF(StatVFSResultType);
15696     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15697     state->StatVFSResultType = StatVFSResultType;
15698 #ifdef NEED_TICKS_PER_SECOND
15699 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15700     ticks_per_second = sysconf(_SC_CLK_TCK);
15701 #  elif defined(HZ)
15702     ticks_per_second = HZ;
15703 #  else
15704     ticks_per_second = 60; /* magic fallback value; may be bogus */
15705 #  endif
15706 #endif
15707 
15708 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15709     sched_param_desc.name = MODNAME ".sched_param";
15710     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15711     if (SchedParamType == NULL) {
15712         return -1;
15713     }
15714     Py_INCREF(SchedParamType);
15715     PyModule_AddObject(m, "sched_param", SchedParamType);
15716     state->SchedParamType = SchedParamType;
15717     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15718 #endif
15719 
15720     /* initialize TerminalSize_info */
15721     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15722     if (TerminalSizeType == NULL) {
15723         return -1;
15724     }
15725     Py_INCREF(TerminalSizeType);
15726     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15727     state->TerminalSizeType = TerminalSizeType;
15728 
15729     /* initialize scandir types */
15730     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15731     if (ScandirIteratorType == NULL) {
15732         return -1;
15733     }
15734     state->ScandirIteratorType = ScandirIteratorType;
15735 
15736     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15737     if (DirEntryType == NULL) {
15738         return -1;
15739     }
15740     Py_INCREF(DirEntryType);
15741     PyModule_AddObject(m, "DirEntry", DirEntryType);
15742     state->DirEntryType = DirEntryType;
15743 
15744     times_result_desc.name = MODNAME ".times_result";
15745     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15746     if (TimesResultType == NULL) {
15747         return -1;
15748     }
15749     Py_INCREF(TimesResultType);
15750     PyModule_AddObject(m, "times_result", TimesResultType);
15751     state->TimesResultType = TimesResultType;
15752 
15753     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15754     if (UnameResultType == NULL) {
15755         return -1;
15756     }
15757     Py_INCREF(UnameResultType);
15758     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15759     state->UnameResultType = (PyObject *)UnameResultType;
15760 
15761     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15762         return -1;
15763 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15764     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15765     if (state->struct_rusage == NULL)
15766         return -1;
15767 #endif
15768     state->st_mode = PyUnicode_InternFromString("st_mode");
15769     if (state->st_mode == NULL)
15770         return -1;
15771 
15772     /* suppress "function not used" warnings */
15773     {
15774     int ignored;
15775     fd_specified("", -1);
15776     follow_symlinks_specified("", 1);
15777     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15778     dir_fd_converter(Py_None, &ignored);
15779     dir_fd_unavailable(Py_None, &ignored);
15780     }
15781 
15782     /*
15783      * provide list of locally available functions
15784      * so os.py can populate support_* lists
15785      */
15786     PyObject *list = PyList_New(0);
15787     if (!list) {
15788         return -1;
15789     }
15790     for (const struct have_function *trace = have_functions; trace->label; trace++) {
15791         PyObject *unicode;
15792         if (trace->probe && !trace->probe()) continue;
15793         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15794         if (!unicode)
15795             return -1;
15796         if (PyList_Append(list, unicode))
15797             return -1;
15798         Py_DECREF(unicode);
15799     }
15800 
15801     PyModule_AddObject(m, "_have_functions", list);
15802 
15803     return 0;
15804 }
15805 
15806 
15807 static PyModuleDef_Slot posixmodile_slots[] = {
15808     {Py_mod_exec, posixmodule_exec},
15809     {0, NULL}
15810 };
15811 
15812 static struct PyModuleDef posixmodule = {
15813     PyModuleDef_HEAD_INIT,
15814     .m_name = MODNAME,
15815     .m_doc = posix__doc__,
15816     .m_size = sizeof(_posixstate),
15817     .m_methods = posix_methods,
15818     .m_slots = posixmodile_slots,
15819     .m_traverse = _posix_traverse,
15820     .m_clear = _posix_clear,
15821     .m_free = _posix_free,
15822 };
15823 
15824 PyMODINIT_FUNC
INITFUNC(void)15825 INITFUNC(void)
15826 {
15827     return PyModuleDef_Init(&posixmodule);
15828 }
15829 
15830 #ifdef __cplusplus
15831 }
15832 #endif
15833