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 <windows.h> before pycore internal headers. FSCTL_GET_REPARSE_POINT
14 // is not exported by <windows.h> if the WIN32_LEAN_AND_MEAN macro is defined,
15 // whereas pycore_condvar.h defines the WIN32_LEAN_AND_MEAN macro.
16 #ifdef MS_WINDOWS
17 #  include <windows.h>
18 #  include <pathcch.h>
19 #  include <lmcons.h>             // UNLEN
20 #  include "osdefs.h"             // SEP
21 #  define HAVE_SYMLINK
22 #endif
23 
24 #ifdef __VXWORKS__
25 #  include "pycore_bitutils.h"    // _Py_popcount32()
26 #endif
27 #include "pycore_call.h"          // _PyObject_CallNoArgs()
28 #include "pycore_ceval.h"         // _PyEval_ReInitThreads()
29 #include "pycore_fileutils.h"     // _Py_closerange()
30 #include "pycore_import.h"        // _PyImport_ReInitLock()
31 #include "pycore_initconfig.h"    // _PyStatus_EXCEPTION()
32 #include "pycore_moduleobject.h"  // _PyModule_GetState()
33 #include "pycore_object.h"        // _PyObject_LookupSpecial()
34 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
35 #include "pycore_signal.h"        // Py_NSIG
36 
37 #ifdef MS_WINDOWS
38 #  include <aclapi.h>             // SetEntriesInAcl
39 #  include <sddl.h>               // SDDL_REVISION_1
40 #endif
41 
42 #include "structmember.h"         // PyMemberDef
43 #ifndef MS_WINDOWS
44 #  include "posixmodule.h"
45 #else
46 #  include "winreparse.h"
47 #endif
48 
49 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
50 #  define EX_OK EXIT_SUCCESS
51 #endif
52 
53 /* On android API level 21, 'AT_EACCESS' is not declared although
54  * HAVE_FACCESSAT is defined. */
55 #ifdef __ANDROID__
56 #  undef HAVE_FACCESSAT
57 #endif
58 
59 #include <stdio.h>                // ctermid()
60 #include <stdlib.h>               // system()
61 
62 /*
63  * A number of APIs are available on macOS from a certain macOS version.
64  * To support building with a new SDK while deploying to older versions
65  * the availability test is split into two:
66  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
67  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
68  *
69  * The latter is always true when not on macOS, or when using a compiler
70  * that does not support __has_builtin (older versions of Xcode).
71  *
72  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
73  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
74  *
75  * In mixing the test with other tests or using negations will result in compile
76  * errors.
77  */
78 #if defined(__APPLE__)
79 
80 #if defined(__has_builtin)
81 #if __has_builtin(__builtin_available)
82 #define HAVE_BUILTIN_AVAILABLE 1
83 #endif
84 #endif
85 
86 #ifdef HAVE_BUILTIN_AVAILABLE
87 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
90 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
91 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
92 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
93 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
94 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
95 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
96 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
97 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
98 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
99 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
100 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
101 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
102 #  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
103 #  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
104 
105 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
106 
107 #else /* Xcode 8 or earlier */
108 
109    /* __builtin_available is not present in these compilers, but
110     * some of the symbols might be weak linked (10.10 SDK or later
111     * deploying on 10.9.
112     *
113     * Fall back to the older style of availability checking for
114     * symbols introduced in macOS 10.10.
115     */
116 
117 #  ifdef HAVE_FSTATAT
118 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
119 #  endif
120 
121 #  ifdef HAVE_FACCESSAT
122 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
123 #  endif
124 
125 #  ifdef HAVE_FCHMODAT
126 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
127 #  endif
128 
129 #  ifdef HAVE_FCHOWNAT
130 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
131 #  endif
132 
133 #  ifdef HAVE_LINKAT
134 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
135 #  endif
136 
137 #  ifdef HAVE_FDOPENDIR
138 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
139 #  endif
140 
141 #  ifdef HAVE_MKDIRAT
142 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
143 #  endif
144 
145 #  ifdef HAVE_RENAMEAT
146 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
147 #  endif
148 
149 #  ifdef HAVE_UNLINKAT
150 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
151 #  endif
152 
153 #  ifdef HAVE_OPENAT
154 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
155 #  endif
156 
157 #  ifdef HAVE_READLINKAT
158 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
159 #  endif
160 
161 #  ifdef HAVE_SYMLINKAT
162 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
163 #  endif
164 
165 #  ifdef HAVE_UTIMENSAT
166 #    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
167 #  endif
168 
169 #  ifdef HAVE_FUTIMENS
170 #    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
171 #  endif
172 
173 #  ifdef HAVE_PWRITEV
174 #    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
175 #  endif
176 
177 #  ifdef HAVE_MKFIFOAT
178 #    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
179 #  endif
180 
181 #  ifdef HAVE_MKNODAT
182 #    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
183 #  endif
184 
185 #endif
186 
187 #ifdef HAVE_FUTIMESAT
188 /* Some of the logic for weak linking depends on this assertion */
189 # error "HAVE_FUTIMESAT unexpectedly defined"
190 #endif
191 
192 #else
193 #  define HAVE_FSTATAT_RUNTIME 1
194 #  define HAVE_FACCESSAT_RUNTIME 1
195 #  define HAVE_FCHMODAT_RUNTIME 1
196 #  define HAVE_FCHOWNAT_RUNTIME 1
197 #  define HAVE_LINKAT_RUNTIME 1
198 #  define HAVE_FDOPENDIR_RUNTIME 1
199 #  define HAVE_MKDIRAT_RUNTIME 1
200 #  define HAVE_RENAMEAT_RUNTIME 1
201 #  define HAVE_UNLINKAT_RUNTIME 1
202 #  define HAVE_OPENAT_RUNTIME 1
203 #  define HAVE_READLINKAT_RUNTIME 1
204 #  define HAVE_SYMLINKAT_RUNTIME 1
205 #  define HAVE_FUTIMENS_RUNTIME 1
206 #  define HAVE_UTIMENSAT_RUNTIME 1
207 #  define HAVE_PWRITEV_RUNTIME 1
208 #  define HAVE_MKFIFOAT_RUNTIME 1
209 #  define HAVE_MKNODAT_RUNTIME 1
210 #endif
211 
212 
213 #ifdef __cplusplus
214 extern "C" {
215 #endif
216 
217 PyDoc_STRVAR(posix__doc__,
218 "This module provides access to operating system functionality that is\n\
219 standardized by the C Standard and the POSIX standard (a thinly\n\
220 disguised Unix interface).  Refer to the library manual and\n\
221 corresponding Unix manual entries for more information on calls.");
222 
223 
224 #ifdef HAVE_SYS_UIO_H
225 #  include <sys/uio.h>
226 #endif
227 
228 #ifdef HAVE_SYS_SYSMACROS_H
229 /* GNU C Library: major(), minor(), makedev() */
230 #  include <sys/sysmacros.h>
231 #endif
232 
233 #ifdef HAVE_SYS_TYPES_H
234 #  include <sys/types.h>
235 #endif /* HAVE_SYS_TYPES_H */
236 
237 #ifdef HAVE_SYS_STAT_H
238 #  include <sys/stat.h>
239 #endif /* HAVE_SYS_STAT_H */
240 
241 #ifdef HAVE_SYS_WAIT_H
242 #  include <sys/wait.h>           // WNOHANG
243 #endif
244 #ifdef HAVE_LINUX_WAIT_H
245 #  include <linux/wait.h>         // P_PIDFD
246 #endif
247 
248 #ifdef HAVE_SIGNAL_H
249 #  include <signal.h>
250 #endif
251 
252 #ifdef HAVE_FCNTL_H
253 #  include <fcntl.h>
254 #endif
255 
256 #ifdef HAVE_GRP_H
257 #  include <grp.h>
258 #endif
259 
260 #ifdef HAVE_SYSEXITS_H
261 #  include <sysexits.h>
262 #endif
263 
264 #ifdef HAVE_SYS_LOADAVG_H
265 #  include <sys/loadavg.h>
266 #endif
267 
268 #ifdef HAVE_SYS_SENDFILE_H
269 #  include <sys/sendfile.h>
270 #endif
271 
272 #if defined(__APPLE__)
273 #  include <copyfile.h>
274 #endif
275 
276 #ifdef HAVE_SCHED_H
277 #  include <sched.h>
278 #endif
279 
280 #ifdef HAVE_COPY_FILE_RANGE
281 #  include <unistd.h>
282 #endif
283 
284 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
285 #  undef HAVE_SCHED_SETAFFINITY
286 #endif
287 
288 #if defined(HAVE_SYS_XATTR_H) && defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
289 #  define USE_XATTRS
290 #  include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
291 #endif
292 
293 #ifdef USE_XATTRS
294 #  include <sys/xattr.h>
295 #endif
296 
297 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
298 #  ifdef HAVE_SYS_SOCKET_H
299 #    include <sys/socket.h>
300 #  endif
301 #endif
302 
303 #ifdef HAVE_DLFCN_H
304 #  include <dlfcn.h>
305 #endif
306 
307 #ifdef __hpux
308 #  include <sys/mpctl.h>
309 #endif
310 
311 #if defined(__DragonFly__) || \
312     defined(__OpenBSD__)   || \
313     defined(__FreeBSD__)   || \
314     defined(__NetBSD__)    || \
315     defined(__APPLE__)
316 #  include <sys/sysctl.h>
317 #endif
318 
319 #ifdef HAVE_LINUX_RANDOM_H
320 #  include <linux/random.h>
321 #endif
322 #ifdef HAVE_GETRANDOM_SYSCALL
323 #  include <sys/syscall.h>
324 #endif
325 
326 #if defined(MS_WINDOWS)
327 #  define TERMSIZE_USE_CONIO
328 #elif defined(HAVE_SYS_IOCTL_H)
329 #  include <sys/ioctl.h>
330 #  if defined(HAVE_TERMIOS_H)
331 #    include <termios.h>
332 #  endif
333 #  if defined(TIOCGWINSZ)
334 #    define TERMSIZE_USE_IOCTL
335 #  endif
336 #endif /* MS_WINDOWS */
337 
338 /* Various compilers have only certain posix functions */
339 /* XXX Gosh I wish these were all moved into pyconfig.h */
340 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
341 #  define HAVE_OPENDIR    1
342 #  define HAVE_SYSTEM     1
343 #  include <process.h>
344 #else
345 #  ifdef _MSC_VER
346      /* Microsoft compiler */
347 #    define HAVE_GETPPID    1
348 #    define HAVE_GETLOGIN   1
349 #    define HAVE_SPAWNV     1
350 #    define HAVE_EXECV      1
351 #    define HAVE_WSPAWNV    1
352 #    define HAVE_WEXECV     1
353 #    define HAVE_PIPE       1
354 #    define HAVE_SYSTEM     1
355 #    define HAVE_CWAIT      1
356 #    define HAVE_FSYNC      1
357 #    define fsync _commit
358 #  endif  /* _MSC_VER */
359 #endif  /* ! __WATCOMC__ || __QNX__ */
360 
361 /*[clinic input]
362 # one of the few times we lie about this name!
363 module os
364 [clinic start generated code]*/
365 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
366 
367 #ifndef _MSC_VER
368 
369 #if defined(__sgi)&&_COMPILER_VERSION>=700
370 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
371    (default) */
372 extern char        *ctermid_r(char *);
373 #endif
374 
375 #endif /* !_MSC_VER */
376 
377 #if defined(__VXWORKS__)
378 #  include <vxCpuLib.h>
379 #  include <rtpLib.h>
380 #  include <wait.h>
381 #  include <taskLib.h>
382 #  ifndef _P_WAIT
383 #    define _P_WAIT          0
384 #    define _P_NOWAIT        1
385 #    define _P_NOWAITO       1
386 #  endif
387 #endif /* __VXWORKS__ */
388 
389 #ifdef HAVE_POSIX_SPAWN
390 #  include <spawn.h>
391 #endif
392 
393 #ifdef HAVE_UTIME_H
394 #  include <utime.h>
395 #endif /* HAVE_UTIME_H */
396 
397 #ifdef HAVE_SYS_UTIME_H
398 #  include <sys/utime.h>
399 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
400 #endif /* HAVE_SYS_UTIME_H */
401 
402 #ifdef HAVE_SYS_TIMES_H
403 #  include <sys/times.h>
404 #endif /* HAVE_SYS_TIMES_H */
405 
406 #ifdef HAVE_SYS_PARAM_H
407 #  include <sys/param.h>
408 #endif /* HAVE_SYS_PARAM_H */
409 
410 #ifdef HAVE_SYS_UTSNAME_H
411 #  include <sys/utsname.h>
412 #endif /* HAVE_SYS_UTSNAME_H */
413 
414 #ifdef HAVE_DIRENT_H
415 #  include <dirent.h>
416 #  define NAMLEN(dirent) strlen((dirent)->d_name)
417 #else
418 #  if defined(__WATCOMC__) && !defined(__QNX__)
419 #    include <direct.h>
420 #    define NAMLEN(dirent) strlen((dirent)->d_name)
421 #  else
422 #    define dirent direct
423 #    define NAMLEN(dirent) (dirent)->d_namlen
424 #  endif
425 #  ifdef HAVE_SYS_NDIR_H
426 #    include <sys/ndir.h>
427 #  endif
428 #  ifdef HAVE_SYS_DIR_H
429 #    include <sys/dir.h>
430 #  endif
431 #  ifdef HAVE_NDIR_H
432 #    include <ndir.h>
433 #  endif
434 #endif
435 
436 #ifdef _MSC_VER
437 #  ifdef HAVE_DIRECT_H
438 #    include <direct.h>
439 #  endif
440 #  ifdef HAVE_IO_H
441 #    include <io.h>
442 #  endif
443 #  ifdef HAVE_PROCESS_H
444 #    include <process.h>
445 #  endif
446 #  include <malloc.h>
447 #endif /* _MSC_VER */
448 
449 #ifndef MAXPATHLEN
450 #  if defined(PATH_MAX) && PATH_MAX > 1024
451 #    define MAXPATHLEN PATH_MAX
452 #  else
453 #    define MAXPATHLEN 1024
454 #  endif
455 #endif /* MAXPATHLEN */
456 
457 #ifdef UNION_WAIT
458    /* Emulate some macros on systems that have a union instead of macros */
459 #  ifndef WIFEXITED
460 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
461 #  endif
462 #  ifndef WEXITSTATUS
463 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
464 #  endif
465 #  ifndef WTERMSIG
466 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
467 #  endif
468 #  define WAIT_TYPE union wait
469 #  define WAIT_STATUS_INT(s) (s.w_status)
470 #else
471    /* !UNION_WAIT */
472 #  define WAIT_TYPE int
473 #  define WAIT_STATUS_INT(s) (s)
474 #endif /* UNION_WAIT */
475 
476 /* Don't use the "_r" form if we don't need it (also, won't have a
477    prototype for it, at least on Solaris -- maybe others as well?). */
478 #if defined(HAVE_CTERMID_R)
479 #  define USE_CTERMID_R
480 #endif
481 
482 /* choose the appropriate stat and fstat functions and return structs */
483 #undef STAT
484 #undef FSTAT
485 #undef STRUCT_STAT
486 #ifdef MS_WINDOWS
487 #  define STAT win32_stat
488 #  define LSTAT win32_lstat
489 #  define FSTAT _Py_fstat_noraise
490 #  define STRUCT_STAT struct _Py_stat_struct
491 #else
492 #  define STAT stat
493 #  define LSTAT lstat
494 #  define FSTAT fstat
495 #  define STRUCT_STAT struct stat
496 #endif
497 
498 #if defined(MAJOR_IN_MKDEV)
499 #  include <sys/mkdev.h>
500 #else
501 #  if defined(MAJOR_IN_SYSMACROS)
502 #    include <sys/sysmacros.h>
503 #  endif
504 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
505 #    include <sys/mkdev.h>
506 #  endif
507 #endif
508 
509 #ifdef MS_WINDOWS
510 #  define INITFUNC PyInit_nt
511 #  define MODNAME "nt"
512 #else
513 #  define INITFUNC PyInit_posix
514 #  define MODNAME "posix"
515 #endif
516 
517 #if defined(__sun)
518 /* Something to implement in autoconf, not present in autoconf 2.69 */
519 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
520 #endif
521 
522 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
523  * linux/memfd.h defines additional flags
524  */
525 #ifdef HAVE_SYS_MMAN_H
526 #  include <sys/mman.h>
527 #endif
528 #ifdef HAVE_SYS_MEMFD_H
529 #  include <sys/memfd.h>
530 #endif
531 #ifdef HAVE_LINUX_MEMFD_H
532 #  include <linux/memfd.h>
533 #endif
534 
535 /* eventfd() */
536 #ifdef HAVE_SYS_EVENTFD_H
537 #  include <sys/eventfd.h>
538 #endif
539 
540 #ifdef _Py_MEMORY_SANITIZER
541 #  include <sanitizer/msan_interface.h>
542 #endif
543 
544 #ifdef HAVE_FORK
545 static void
run_at_forkers(PyObject *lst, int reverse)546 run_at_forkers(PyObject *lst, int reverse)
547 {
548     Py_ssize_t i;
549     PyObject *cpy;
550 
551     if (lst != NULL) {
552         assert(PyList_CheckExact(lst));
553 
554         /* Use a list copy in case register_at_fork() is called from
555          * one of the callbacks.
556          */
557         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
558         if (cpy == NULL)
559             PyErr_WriteUnraisable(lst);
560         else {
561             if (reverse)
562                 PyList_Reverse(cpy);
563             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
564                 PyObject *func, *res;
565                 func = PyList_GET_ITEM(cpy, i);
566                 res = _PyObject_CallNoArgs(func);
567                 if (res == NULL)
568                     PyErr_WriteUnraisable(func);
569                 else
570                     Py_DECREF(res);
571             }
572             Py_DECREF(cpy);
573         }
574     }
575 }
576 
577 void
PyOS_BeforeFork(void)578 PyOS_BeforeFork(void)
579 {
580     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
581 
582     _PyImport_AcquireLock();
583 }
584 
585 void
PyOS_AfterFork_Parent(void)586 PyOS_AfterFork_Parent(void)
587 {
588     if (_PyImport_ReleaseLock() <= 0)
589         Py_FatalError("failed releasing import lock after fork");
590 
591     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
592 }
593 
594 void
PyOS_AfterFork_Child(void)595 PyOS_AfterFork_Child(void)
596 {
597     PyStatus status;
598     _PyRuntimeState *runtime = &_PyRuntime;
599 
600     status = _PyGILState_Reinit(runtime);
601     if (_PyStatus_EXCEPTION(status)) {
602         goto fatal_error;
603     }
604 
605     PyThreadState *tstate = _PyThreadState_GET();
606     _Py_EnsureTstateNotNULL(tstate);
607 
608 #ifdef PY_HAVE_THREAD_NATIVE_ID
609     tstate->native_thread_id = PyThread_get_thread_native_id();
610 #endif
611 
612     status = _PyEval_ReInitThreads(tstate);
613     if (_PyStatus_EXCEPTION(status)) {
614         goto fatal_error;
615     }
616 
617     status = _PyImport_ReInitLock();
618     if (_PyStatus_EXCEPTION(status)) {
619         goto fatal_error;
620     }
621 
622     _PySignal_AfterFork();
623 
624     status = _PyRuntimeState_ReInitThreads(runtime);
625     if (_PyStatus_EXCEPTION(status)) {
626         goto fatal_error;
627     }
628 
629     status = _PyInterpreterState_DeleteExceptMain(runtime);
630     if (_PyStatus_EXCEPTION(status)) {
631         goto fatal_error;
632     }
633     assert(_PyThreadState_GET() == tstate);
634 
635     run_at_forkers(tstate->interp->after_forkers_child, 0);
636     return;
637 
638 fatal_error:
639     Py_ExitStatusException(status);
640 }
641 
642 static int
register_at_forker(PyObject **lst, PyObject *func)643 register_at_forker(PyObject **lst, PyObject *func)
644 {
645     if (func == NULL)  /* nothing to register? do nothing. */
646         return 0;
647     if (*lst == NULL) {
648         *lst = PyList_New(0);
649         if (*lst == NULL)
650             return -1;
651     }
652     return PyList_Append(*lst, func);
653 }
654 #endif  /* HAVE_FORK */
655 
656 
657 /* Legacy wrapper */
658 void
PyOS_AfterFork(void)659 PyOS_AfterFork(void)
660 {
661 #ifdef HAVE_FORK
662     PyOS_AfterFork_Child();
663 #endif
664 }
665 
666 
667 #ifdef MS_WINDOWS
668 /* defined in fileutils.c */
669 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
670 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
671                                             ULONG, struct _Py_stat_struct *);
672 #endif
673 
674 
675 #ifndef MS_WINDOWS
676 PyObject *
_PyLong_FromUid(uid_t uid)677 _PyLong_FromUid(uid_t uid)
678 {
679     if (uid == (uid_t)-1)
680         return PyLong_FromLong(-1);
681     return PyLong_FromUnsignedLong(uid);
682 }
683 
684 PyObject *
_PyLong_FromGid(gid_t gid)685 _PyLong_FromGid(gid_t gid)
686 {
687     if (gid == (gid_t)-1)
688         return PyLong_FromLong(-1);
689     return PyLong_FromUnsignedLong(gid);
690 }
691 
692 int
_Py_Uid_Converter(PyObject *obj, uid_t *p)693 _Py_Uid_Converter(PyObject *obj, uid_t *p)
694 {
695     uid_t uid;
696     PyObject *index;
697     int overflow;
698     long result;
699     unsigned long uresult;
700 
701     index = _PyNumber_Index(obj);
702     if (index == NULL) {
703         PyErr_Format(PyExc_TypeError,
704                      "uid should be integer, not %.200s",
705                      _PyType_Name(Py_TYPE(obj)));
706         return 0;
707     }
708 
709     /*
710      * Handling uid_t is complicated for two reasons:
711      *  * Although uid_t is (always?) unsigned, it still
712      *    accepts -1.
713      *  * We don't know its size in advance--it may be
714      *    bigger than an int, or it may be smaller than
715      *    a long.
716      *
717      * So a bit of defensive programming is in order.
718      * Start with interpreting the value passed
719      * in as a signed long and see if it works.
720      */
721 
722     result = PyLong_AsLongAndOverflow(index, &overflow);
723 
724     if (!overflow) {
725         uid = (uid_t)result;
726 
727         if (result == -1) {
728             if (PyErr_Occurred())
729                 goto fail;
730             /* It's a legitimate -1, we're done. */
731             goto success;
732         }
733 
734         /* Any other negative number is disallowed. */
735         if (result < 0)
736             goto underflow;
737 
738         /* Ensure the value wasn't truncated. */
739         if (sizeof(uid_t) < sizeof(long) &&
740             (long)uid != result)
741             goto underflow;
742         goto success;
743     }
744 
745     if (overflow < 0)
746         goto underflow;
747 
748     /*
749      * Okay, the value overflowed a signed long.  If it
750      * fits in an *unsigned* long, it may still be okay,
751      * as uid_t may be unsigned long on this platform.
752      */
753     uresult = PyLong_AsUnsignedLong(index);
754     if (PyErr_Occurred()) {
755         if (PyErr_ExceptionMatches(PyExc_OverflowError))
756             goto overflow;
757         goto fail;
758     }
759 
760     uid = (uid_t)uresult;
761 
762     /*
763      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
764      * but this value would get interpreted as (uid_t)-1  by chown
765      * and its siblings.   That's not what the user meant!  So we
766      * throw an overflow exception instead.   (We already
767      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
768      */
769     if (uid == (uid_t)-1)
770         goto overflow;
771 
772     /* Ensure the value wasn't truncated. */
773     if (sizeof(uid_t) < sizeof(long) &&
774         (unsigned long)uid != uresult)
775         goto overflow;
776     /* fallthrough */
777 
778 success:
779     Py_DECREF(index);
780     *p = uid;
781     return 1;
782 
783 underflow:
784     PyErr_SetString(PyExc_OverflowError,
785                     "uid is less than minimum");
786     goto fail;
787 
788 overflow:
789     PyErr_SetString(PyExc_OverflowError,
790                     "uid is greater than maximum");
791     /* fallthrough */
792 
793 fail:
794     Py_DECREF(index);
795     return 0;
796 }
797 
798 int
_Py_Gid_Converter(PyObject *obj, gid_t *p)799 _Py_Gid_Converter(PyObject *obj, gid_t *p)
800 {
801     gid_t gid;
802     PyObject *index;
803     int overflow;
804     long result;
805     unsigned long uresult;
806 
807     index = _PyNumber_Index(obj);
808     if (index == NULL) {
809         PyErr_Format(PyExc_TypeError,
810                      "gid should be integer, not %.200s",
811                      _PyType_Name(Py_TYPE(obj)));
812         return 0;
813     }
814 
815     /*
816      * Handling gid_t is complicated for two reasons:
817      *  * Although gid_t is (always?) unsigned, it still
818      *    accepts -1.
819      *  * We don't know its size in advance--it may be
820      *    bigger than an int, or it may be smaller than
821      *    a long.
822      *
823      * So a bit of defensive programming is in order.
824      * Start with interpreting the value passed
825      * in as a signed long and see if it works.
826      */
827 
828     result = PyLong_AsLongAndOverflow(index, &overflow);
829 
830     if (!overflow) {
831         gid = (gid_t)result;
832 
833         if (result == -1) {
834             if (PyErr_Occurred())
835                 goto fail;
836             /* It's a legitimate -1, we're done. */
837             goto success;
838         }
839 
840         /* Any other negative number is disallowed. */
841         if (result < 0) {
842             goto underflow;
843         }
844 
845         /* Ensure the value wasn't truncated. */
846         if (sizeof(gid_t) < sizeof(long) &&
847             (long)gid != result)
848             goto underflow;
849         goto success;
850     }
851 
852     if (overflow < 0)
853         goto underflow;
854 
855     /*
856      * Okay, the value overflowed a signed long.  If it
857      * fits in an *unsigned* long, it may still be okay,
858      * as gid_t may be unsigned long on this platform.
859      */
860     uresult = PyLong_AsUnsignedLong(index);
861     if (PyErr_Occurred()) {
862         if (PyErr_ExceptionMatches(PyExc_OverflowError))
863             goto overflow;
864         goto fail;
865     }
866 
867     gid = (gid_t)uresult;
868 
869     /*
870      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
871      * but this value would get interpreted as (gid_t)-1  by chown
872      * and its siblings.   That's not what the user meant!  So we
873      * throw an overflow exception instead.   (We already
874      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
875      */
876     if (gid == (gid_t)-1)
877         goto overflow;
878 
879     /* Ensure the value wasn't truncated. */
880     if (sizeof(gid_t) < sizeof(long) &&
881         (unsigned long)gid != uresult)
882         goto overflow;
883     /* fallthrough */
884 
885 success:
886     Py_DECREF(index);
887     *p = gid;
888     return 1;
889 
890 underflow:
891     PyErr_SetString(PyExc_OverflowError,
892                     "gid is less than minimum");
893     goto fail;
894 
895 overflow:
896     PyErr_SetString(PyExc_OverflowError,
897                     "gid is greater than maximum");
898     /* fallthrough */
899 
900 fail:
901     Py_DECREF(index);
902     return 0;
903 }
904 #endif /* MS_WINDOWS */
905 
906 
907 #define _PyLong_FromDev PyLong_FromLongLong
908 
909 
910 #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
911 static int
_Py_Dev_Converter(PyObject *obj, void *p)912 _Py_Dev_Converter(PyObject *obj, void *p)
913 {
914     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
915     if (PyErr_Occurred())
916         return 0;
917     return 1;
918 }
919 #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
920 
921 
922 #ifdef AT_FDCWD
923 /*
924  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
925  * without the int cast, the value gets interpreted as uint (4291925331),
926  * which doesn't play nicely with all the initializer lines in this file that
927  * look like this:
928  *      int dir_fd = DEFAULT_DIR_FD;
929  */
930 #define DEFAULT_DIR_FD (int)AT_FDCWD
931 #else
932 #define DEFAULT_DIR_FD (-100)
933 #endif
934 
935 static int
_fd_converter(PyObject *o, int *p)936 _fd_converter(PyObject *o, int *p)
937 {
938     int overflow;
939     long long_value;
940 
941     PyObject *index = _PyNumber_Index(o);
942     if (index == NULL) {
943         return 0;
944     }
945 
946     assert(PyLong_Check(index));
947     long_value = PyLong_AsLongAndOverflow(index, &overflow);
948     Py_DECREF(index);
949     assert(!PyErr_Occurred());
950     if (overflow > 0 || long_value > INT_MAX) {
951         PyErr_SetString(PyExc_OverflowError,
952                         "fd is greater than maximum");
953         return 0;
954     }
955     if (overflow < 0 || long_value < INT_MIN) {
956         PyErr_SetString(PyExc_OverflowError,
957                         "fd is less than minimum");
958         return 0;
959     }
960 
961     *p = (int)long_value;
962     return 1;
963 }
964 
965 static int
dir_fd_converter(PyObject *o, void *p)966 dir_fd_converter(PyObject *o, void *p)
967 {
968     if (o == Py_None) {
969         *(int *)p = DEFAULT_DIR_FD;
970         return 1;
971     }
972     else if (PyIndex_Check(o)) {
973         return _fd_converter(o, (int *)p);
974     }
975     else {
976         PyErr_Format(PyExc_TypeError,
977                      "argument should be integer or None, not %.200s",
978                      _PyType_Name(Py_TYPE(o)));
979         return 0;
980     }
981 }
982 
983 typedef struct {
984     PyObject *billion;
985     PyObject *DirEntryType;
986     PyObject *ScandirIteratorType;
987 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
988     PyObject *SchedParamType;
989 #endif
990     PyObject *StatResultType;
991     PyObject *StatVFSResultType;
992     PyObject *TerminalSizeType;
993     PyObject *TimesResultType;
994     PyObject *UnameResultType;
995 #if defined(HAVE_WAITID) && !defined(__APPLE__)
996     PyObject *WaitidResultType;
997 #endif
998 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
999     PyObject *struct_rusage;
1000 #endif
1001     PyObject *st_mode;
1002 } _posixstate;
1003 
1004 
1005 static inline _posixstate*
get_posix_state(PyObject *module)1006 get_posix_state(PyObject *module)
1007 {
1008     void *state = _PyModule_GetState(module);
1009     assert(state != NULL);
1010     return (_posixstate *)state;
1011 }
1012 
1013 /*
1014  * A PyArg_ParseTuple "converter" function
1015  * that handles filesystem paths in the manner
1016  * preferred by the os module.
1017  *
1018  * path_converter accepts (Unicode) strings and their
1019  * subclasses, and bytes and their subclasses.  What
1020  * it does with the argument depends on the platform:
1021  *
1022  *   * On Windows, if we get a (Unicode) string we
1023  *     extract the wchar_t * and return it; if we get
1024  *     bytes we decode to wchar_t * and return that.
1025  *
1026  *   * On all other platforms, strings are encoded
1027  *     to bytes using PyUnicode_FSConverter, then we
1028  *     extract the char * from the bytes object and
1029  *     return that.
1030  *
1031  * path_converter also optionally accepts signed
1032  * integers (representing open file descriptors) instead
1033  * of path strings.
1034  *
1035  * Input fields:
1036  *   path.nullable
1037  *     If nonzero, the path is permitted to be None.
1038  *   path.allow_fd
1039  *     If nonzero, the path is permitted to be a file handle
1040  *     (a signed int) instead of a string.
1041  *   path.function_name
1042  *     If non-NULL, path_converter will use that as the name
1043  *     of the function in error messages.
1044  *     (If path.function_name is NULL it omits the function name.)
1045  *   path.argument_name
1046  *     If non-NULL, path_converter will use that as the name
1047  *     of the parameter in error messages.
1048  *     (If path.argument_name is NULL it uses "path".)
1049  *
1050  * Output fields:
1051  *   path.wide
1052  *     Points to the path if it was expressed as Unicode
1053  *     and was not encoded.  (Only used on Windows.)
1054  *   path.narrow
1055  *     Points to the path if it was expressed as bytes,
1056  *     or it was Unicode and was encoded to bytes. (On Windows,
1057  *     is a non-zero integer if the path was expressed as bytes.
1058  *     The type is deliberately incompatible to prevent misuse.)
1059  *   path.fd
1060  *     Contains a file descriptor if path.accept_fd was true
1061  *     and the caller provided a signed integer instead of any
1062  *     sort of string.
1063  *
1064  *     WARNING: if your "path" parameter is optional, and is
1065  *     unspecified, path_converter will never get called.
1066  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1067  *     yourself!
1068  *   path.length
1069  *     The length of the path in characters, if specified as
1070  *     a string.
1071  *   path.object
1072  *     The original object passed in (if get a PathLike object,
1073  *     the result of PyOS_FSPath() is treated as the original object).
1074  *     Own a reference to the object.
1075  *   path.cleanup
1076  *     For internal use only.  May point to a temporary object.
1077  *     (Pay no attention to the man behind the curtain.)
1078  *
1079  *   At most one of path.wide or path.narrow will be non-NULL.
1080  *   If path was None and path.nullable was set,
1081  *     or if path was an integer and path.allow_fd was set,
1082  *     both path.wide and path.narrow will be NULL
1083  *     and path.length will be 0.
1084  *
1085  *   path_converter takes care to not write to the path_t
1086  *   unless it's successful.  However it must reset the
1087  *   "cleanup" field each time it's called.
1088  *
1089  * Use as follows:
1090  *      path_t path;
1091  *      memset(&path, 0, sizeof(path));
1092  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1093  *      // ... use values from path ...
1094  *      path_cleanup(&path);
1095  *
1096  * (Note that if PyArg_Parse fails you don't need to call
1097  * path_cleanup().  However it is safe to do so.)
1098  */
1099 typedef struct {
1100     const char *function_name;
1101     const char *argument_name;
1102     int nullable;
1103     int allow_fd;
1104     const wchar_t *wide;
1105 #ifdef MS_WINDOWS
1106     BOOL narrow;
1107 #else
1108     const char *narrow;
1109 #endif
1110     int fd;
1111     Py_ssize_t length;
1112     PyObject *object;
1113     PyObject *cleanup;
1114 } path_t;
1115 
1116 #ifdef MS_WINDOWS
1117 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1118     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1119 #else
1120 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1121     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1122 #endif
1123 
1124 static void
path_cleanup(path_t *path)1125 path_cleanup(path_t *path)
1126 {
1127 #if !USE_UNICODE_WCHAR_CACHE
1128     wchar_t *wide = (wchar_t *)path->wide;
1129     path->wide = NULL;
1130     PyMem_Free(wide);
1131 #endif /* USE_UNICODE_WCHAR_CACHE */
1132     Py_CLEAR(path->object);
1133     Py_CLEAR(path->cleanup);
1134 }
1135 
1136 static int
path_converter(PyObject *o, void *p)1137 path_converter(PyObject *o, void *p)
1138 {
1139     path_t *path = (path_t *)p;
1140     PyObject *bytes = NULL;
1141     Py_ssize_t length = 0;
1142     int is_index, is_buffer, is_bytes, is_unicode;
1143     const char *narrow;
1144 #ifdef MS_WINDOWS
1145     PyObject *wo = NULL;
1146     wchar_t *wide = NULL;
1147 #endif
1148 
1149 #define FORMAT_EXCEPTION(exc, fmt) \
1150     PyErr_Format(exc, "%s%s" fmt, \
1151         path->function_name ? path->function_name : "", \
1152         path->function_name ? ": "                : "", \
1153         path->argument_name ? path->argument_name : "path")
1154 
1155     /* Py_CLEANUP_SUPPORTED support */
1156     if (o == NULL) {
1157         path_cleanup(path);
1158         return 1;
1159     }
1160 
1161     /* Ensure it's always safe to call path_cleanup(). */
1162     path->object = path->cleanup = NULL;
1163     /* path->object owns a reference to the original object */
1164     Py_INCREF(o);
1165 
1166     if ((o == Py_None) && path->nullable) {
1167         path->wide = NULL;
1168 #ifdef MS_WINDOWS
1169         path->narrow = FALSE;
1170 #else
1171         path->narrow = NULL;
1172 #endif
1173         path->fd = -1;
1174         goto success_exit;
1175     }
1176 
1177     /* Only call this here so that we don't treat the return value of
1178        os.fspath() as an fd or buffer. */
1179     is_index = path->allow_fd && PyIndex_Check(o);
1180     is_buffer = PyObject_CheckBuffer(o);
1181     is_bytes = PyBytes_Check(o);
1182     is_unicode = PyUnicode_Check(o);
1183 
1184     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1185         /* Inline PyOS_FSPath() for better error messages. */
1186         PyObject *func, *res;
1187 
1188         func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1189         if (NULL == func) {
1190             goto error_format;
1191         }
1192         res = _PyObject_CallNoArgs(func);
1193         Py_DECREF(func);
1194         if (NULL == res) {
1195             goto error_exit;
1196         }
1197         else if (PyUnicode_Check(res)) {
1198             is_unicode = 1;
1199         }
1200         else if (PyBytes_Check(res)) {
1201             is_bytes = 1;
1202         }
1203         else {
1204             PyErr_Format(PyExc_TypeError,
1205                  "expected %.200s.__fspath__() to return str or bytes, "
1206                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1207                  _PyType_Name(Py_TYPE(res)));
1208             Py_DECREF(res);
1209             goto error_exit;
1210         }
1211 
1212         /* still owns a reference to the original object */
1213         Py_DECREF(o);
1214         o = res;
1215     }
1216 
1217     if (is_unicode) {
1218 #ifdef MS_WINDOWS
1219 #if USE_UNICODE_WCHAR_CACHE
1220 _Py_COMP_DIAG_PUSH
1221 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1222         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1223 _Py_COMP_DIAG_POP
1224 #else /* USE_UNICODE_WCHAR_CACHE */
1225         wide = PyUnicode_AsWideCharString(o, &length);
1226 #endif /* USE_UNICODE_WCHAR_CACHE */
1227         if (!wide) {
1228             goto error_exit;
1229         }
1230         if (length > 32767) {
1231             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1232             goto error_exit;
1233         }
1234         if (wcslen(wide) != length) {
1235             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1236             goto error_exit;
1237         }
1238 
1239         path->wide = wide;
1240         path->narrow = FALSE;
1241         path->fd = -1;
1242 #if !USE_UNICODE_WCHAR_CACHE
1243         wide = NULL;
1244 #endif /* USE_UNICODE_WCHAR_CACHE */
1245         goto success_exit;
1246 #else
1247         if (!PyUnicode_FSConverter(o, &bytes)) {
1248             goto error_exit;
1249         }
1250 #endif
1251     }
1252     else if (is_bytes) {
1253         bytes = o;
1254         Py_INCREF(bytes);
1255     }
1256     else if (is_buffer) {
1257         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1258            after removing support of non-bytes buffer objects. */
1259         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1260             "%s%s%s should be %s, not %.200s",
1261             path->function_name ? path->function_name : "",
1262             path->function_name ? ": "                : "",
1263             path->argument_name ? path->argument_name : "path",
1264             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1265                                                "integer or None" :
1266             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1267             path->nullable ? "string, bytes, os.PathLike or None" :
1268                              "string, bytes or os.PathLike",
1269             _PyType_Name(Py_TYPE(o)))) {
1270             goto error_exit;
1271         }
1272         bytes = PyBytes_FromObject(o);
1273         if (!bytes) {
1274             goto error_exit;
1275         }
1276     }
1277     else if (is_index) {
1278         if (!_fd_converter(o, &path->fd)) {
1279             goto error_exit;
1280         }
1281         path->wide = NULL;
1282 #ifdef MS_WINDOWS
1283         path->narrow = FALSE;
1284 #else
1285         path->narrow = NULL;
1286 #endif
1287         goto success_exit;
1288     }
1289     else {
1290  error_format:
1291         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1292             path->function_name ? path->function_name : "",
1293             path->function_name ? ": "                : "",
1294             path->argument_name ? path->argument_name : "path",
1295             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1296                                                "integer or None" :
1297             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1298             path->nullable ? "string, bytes, os.PathLike or None" :
1299                              "string, bytes or os.PathLike",
1300             _PyType_Name(Py_TYPE(o)));
1301         goto error_exit;
1302     }
1303 
1304     length = PyBytes_GET_SIZE(bytes);
1305     narrow = PyBytes_AS_STRING(bytes);
1306     if ((size_t)length != strlen(narrow)) {
1307         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1308         goto error_exit;
1309     }
1310 
1311 #ifdef MS_WINDOWS
1312     wo = PyUnicode_DecodeFSDefaultAndSize(
1313         narrow,
1314         length
1315     );
1316     if (!wo) {
1317         goto error_exit;
1318     }
1319 
1320 #if USE_UNICODE_WCHAR_CACHE
1321 _Py_COMP_DIAG_PUSH
1322 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1323     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1324 _Py_COMP_DIAG_POP
1325 #else /* USE_UNICODE_WCHAR_CACHE */
1326     wide = PyUnicode_AsWideCharString(wo, &length);
1327     Py_DECREF(wo);
1328 #endif /* USE_UNICODE_WCHAR_CACHE */
1329     if (!wide) {
1330         goto error_exit;
1331     }
1332     if (length > 32767) {
1333         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1334         goto error_exit;
1335     }
1336     if (wcslen(wide) != length) {
1337         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1338         goto error_exit;
1339     }
1340     path->wide = wide;
1341     path->narrow = TRUE;
1342     Py_DECREF(bytes);
1343 #if USE_UNICODE_WCHAR_CACHE
1344     path->cleanup = wo;
1345 #else /* USE_UNICODE_WCHAR_CACHE */
1346     wide = NULL;
1347 #endif /* USE_UNICODE_WCHAR_CACHE */
1348 #else
1349     path->wide = NULL;
1350     path->narrow = narrow;
1351     if (bytes == o) {
1352         /* Still a reference owned by path->object, don't have to
1353            worry about path->narrow is used after free. */
1354         Py_DECREF(bytes);
1355     }
1356     else {
1357         path->cleanup = bytes;
1358     }
1359 #endif
1360     path->fd = -1;
1361 
1362  success_exit:
1363     path->length = length;
1364     path->object = o;
1365     return Py_CLEANUP_SUPPORTED;
1366 
1367  error_exit:
1368     Py_XDECREF(o);
1369     Py_XDECREF(bytes);
1370 #ifdef MS_WINDOWS
1371 #if USE_UNICODE_WCHAR_CACHE
1372     Py_XDECREF(wo);
1373 #else /* USE_UNICODE_WCHAR_CACHE */
1374     PyMem_Free(wide);
1375 #endif /* USE_UNICODE_WCHAR_CACHE */
1376 #endif
1377     return 0;
1378 }
1379 
1380 static void
argument_unavailable_error(const char *function_name, const char *argument_name)1381 argument_unavailable_error(const char *function_name, const char *argument_name)
1382 {
1383     PyErr_Format(PyExc_NotImplementedError,
1384         "%s%s%s unavailable on this platform",
1385         (function_name != NULL) ? function_name : "",
1386         (function_name != NULL) ? ": ": "",
1387         argument_name);
1388 }
1389 
1390 static int
dir_fd_unavailable(PyObject *o, void *p)1391 dir_fd_unavailable(PyObject *o, void *p)
1392 {
1393     int dir_fd;
1394     if (!dir_fd_converter(o, &dir_fd))
1395         return 0;
1396     if (dir_fd != DEFAULT_DIR_FD) {
1397         argument_unavailable_error(NULL, "dir_fd");
1398         return 0;
1399     }
1400     *(int *)p = dir_fd;
1401     return 1;
1402 }
1403 
1404 static int
fd_specified(const char *function_name, int fd)1405 fd_specified(const char *function_name, int fd)
1406 {
1407     if (fd == -1)
1408         return 0;
1409 
1410     argument_unavailable_error(function_name, "fd");
1411     return 1;
1412 }
1413 
1414 static int
follow_symlinks_specified(const char *function_name, int follow_symlinks)1415 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1416 {
1417     if (follow_symlinks)
1418         return 0;
1419 
1420     argument_unavailable_error(function_name, "follow_symlinks");
1421     return 1;
1422 }
1423 
1424 static int
path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)1425 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1426 {
1427     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1428 #ifndef MS_WINDOWS
1429         && !path->narrow
1430 #endif
1431     ) {
1432         PyErr_Format(PyExc_ValueError,
1433                      "%s: can't specify dir_fd without matching path",
1434                      function_name);
1435         return 1;
1436     }
1437     return 0;
1438 }
1439 
1440 static int
dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)1441 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1442 {
1443     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1444         PyErr_Format(PyExc_ValueError,
1445                      "%s: can't specify both dir_fd and fd",
1446                      function_name);
1447         return 1;
1448     }
1449     return 0;
1450 }
1451 
1452 static int
fd_and_follow_symlinks_invalid(const char *function_name, int fd, int follow_symlinks)1453 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1454                                int follow_symlinks)
1455 {
1456     if ((fd > 0) && (!follow_symlinks)) {
1457         PyErr_Format(PyExc_ValueError,
1458                      "%s: cannot use fd and follow_symlinks together",
1459                      function_name);
1460         return 1;
1461     }
1462     return 0;
1463 }
1464 
1465 static int
dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd, int follow_symlinks)1466 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1467                                    int follow_symlinks)
1468 {
1469     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1470         PyErr_Format(PyExc_ValueError,
1471                      "%s: cannot use dir_fd and follow_symlinks together",
1472                      function_name);
1473         return 1;
1474     }
1475     return 0;
1476 }
1477 
1478 #ifdef MS_WINDOWS
1479     typedef long long Py_off_t;
1480 #else
1481     typedef off_t Py_off_t;
1482 #endif
1483 
1484 static int
Py_off_t_converter(PyObject *arg, void *addr)1485 Py_off_t_converter(PyObject *arg, void *addr)
1486 {
1487 #ifdef HAVE_LARGEFILE_SUPPORT
1488     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1489 #else
1490     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1491 #endif
1492     if (PyErr_Occurred())
1493         return 0;
1494     return 1;
1495 }
1496 
1497 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1498 PyLong_FromPy_off_t(Py_off_t offset)
1499 {
1500 #ifdef HAVE_LARGEFILE_SUPPORT
1501     return PyLong_FromLongLong(offset);
1502 #else
1503     return PyLong_FromLong(offset);
1504 #endif
1505 }
1506 
1507 #ifdef HAVE_SIGSET_T
1508 /* Convert an iterable of integers to a sigset.
1509    Return 1 on success, return 0 and raise an exception on error. */
1510 int
_Py_Sigset_Converter(PyObject *obj, void *addr)1511 _Py_Sigset_Converter(PyObject *obj, void *addr)
1512 {
1513     sigset_t *mask = (sigset_t *)addr;
1514     PyObject *iterator, *item;
1515     long signum;
1516     int overflow;
1517 
1518     // The extra parens suppress the unreachable-code warning with clang on MacOS
1519     if (sigemptyset(mask) < (0)) {
1520         /* Probably only if mask == NULL. */
1521         PyErr_SetFromErrno(PyExc_OSError);
1522         return 0;
1523     }
1524 
1525     iterator = PyObject_GetIter(obj);
1526     if (iterator == NULL) {
1527         return 0;
1528     }
1529 
1530     while ((item = PyIter_Next(iterator)) != NULL) {
1531         signum = PyLong_AsLongAndOverflow(item, &overflow);
1532         Py_DECREF(item);
1533         if (signum <= 0 || signum >= Py_NSIG) {
1534             if (overflow || signum != -1 || !PyErr_Occurred()) {
1535                 PyErr_Format(PyExc_ValueError,
1536                              "signal number %ld out of range [1; %i]",
1537                              signum, Py_NSIG - 1);
1538             }
1539             goto error;
1540         }
1541         if (sigaddset(mask, (int)signum)) {
1542             if (errno != EINVAL) {
1543                 /* Probably impossible */
1544                 PyErr_SetFromErrno(PyExc_OSError);
1545                 goto error;
1546             }
1547             /* For backwards compatibility, allow idioms such as
1548              * `range(1, NSIG)` but warn about invalid signal numbers
1549              */
1550             const char msg[] =
1551                 "invalid signal number %ld, please use valid_signals()";
1552             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1553                 goto error;
1554             }
1555         }
1556     }
1557     if (!PyErr_Occurred()) {
1558         Py_DECREF(iterator);
1559         return 1;
1560     }
1561 
1562 error:
1563     Py_DECREF(iterator);
1564     return 0;
1565 }
1566 #endif /* HAVE_SIGSET_T */
1567 
1568 #ifdef MS_WINDOWS
1569 
1570 static int
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)1571 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1572 {
1573     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1574     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1575     DWORD n_bytes_returned;
1576 
1577     if (0 == DeviceIoControl(
1578         reparse_point_handle,
1579         FSCTL_GET_REPARSE_POINT,
1580         NULL, 0, /* in buffer */
1581         target_buffer, sizeof(target_buffer),
1582         &n_bytes_returned,
1583         NULL)) /* we're not using OVERLAPPED_IO */
1584         return FALSE;
1585 
1586     if (reparse_tag)
1587         *reparse_tag = rdb->ReparseTag;
1588 
1589     return TRUE;
1590 }
1591 
1592 #endif /* MS_WINDOWS */
1593 
1594 /* Return a dictionary corresponding to the POSIX environment table */
1595 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1596 /* On Darwin/MacOSX a shared library or framework has no access to
1597 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1598 ** man environ(7).
1599 */
1600 #include <crt_externs.h>
1601 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1602 extern char **environ;
1603 #endif /* !_MSC_VER */
1604 
1605 static PyObject *
convertenviron(void)1606 convertenviron(void)
1607 {
1608     PyObject *d;
1609 #ifdef MS_WINDOWS
1610     wchar_t **e;
1611 #else
1612     char **e;
1613 #endif
1614 
1615     d = PyDict_New();
1616     if (d == NULL)
1617         return NULL;
1618 #ifdef MS_WINDOWS
1619     /* _wenviron must be initialized in this way if the program is started
1620        through main() instead of wmain(). */
1621     _wgetenv(L"");
1622     e = _wenviron;
1623 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1624     /* environ is not accessible as an extern in a shared object on OSX; use
1625        _NSGetEnviron to resolve it. The value changes if you add environment
1626        variables between calls to Py_Initialize, so don't cache the value. */
1627     e = *_NSGetEnviron();
1628 #else
1629     e = environ;
1630 #endif
1631     if (e == NULL)
1632         return d;
1633     for (; *e != NULL; e++) {
1634         PyObject *k;
1635         PyObject *v;
1636 #ifdef MS_WINDOWS
1637         const wchar_t *p = wcschr(*e, L'=');
1638 #else
1639         const char *p = strchr(*e, '=');
1640 #endif
1641         if (p == NULL)
1642             continue;
1643 #ifdef MS_WINDOWS
1644         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1645 #else
1646         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1647 #endif
1648         if (k == NULL) {
1649             Py_DECREF(d);
1650             return NULL;
1651         }
1652 #ifdef MS_WINDOWS
1653         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1654 #else
1655         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1656 #endif
1657         if (v == NULL) {
1658             Py_DECREF(k);
1659             Py_DECREF(d);
1660             return NULL;
1661         }
1662         if (PyDict_SetDefault(d, k, v) == NULL) {
1663             Py_DECREF(v);
1664             Py_DECREF(k);
1665             Py_DECREF(d);
1666             return NULL;
1667         }
1668         Py_DECREF(k);
1669         Py_DECREF(v);
1670     }
1671     return d;
1672 }
1673 
1674 /* Set a POSIX-specific error from errno, and return NULL */
1675 
1676 static PyObject *
posix_error(void)1677 posix_error(void)
1678 {
1679     return PyErr_SetFromErrno(PyExc_OSError);
1680 }
1681 
1682 #ifdef MS_WINDOWS
1683 static PyObject *
win32_error(const char* function, const char* filename)1684 win32_error(const char* function, const char* filename)
1685 {
1686     /* XXX We should pass the function name along in the future.
1687        (winreg.c also wants to pass the function name.)
1688        This would however require an additional param to the
1689        Windows error object, which is non-trivial.
1690     */
1691     errno = GetLastError();
1692     if (filename)
1693         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1694     else
1695         return PyErr_SetFromWindowsErr(errno);
1696 }
1697 
1698 static PyObject *
win32_error_object_err(const char* function, PyObject* filename, DWORD err)1699 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1700 {
1701     /* XXX - see win32_error for comments on 'function' */
1702     if (filename)
1703         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1704                     PyExc_OSError,
1705                     err,
1706                     filename);
1707     else
1708         return PyErr_SetFromWindowsErr(err);
1709 }
1710 
1711 static PyObject *
win32_error_object(const char* function, PyObject* filename)1712 win32_error_object(const char* function, PyObject* filename)
1713 {
1714     errno = GetLastError();
1715     return win32_error_object_err(function, filename, errno);
1716 }
1717 
1718 #endif /* MS_WINDOWS */
1719 
1720 static PyObject *
posix_path_object_error(PyObject *path)1721 posix_path_object_error(PyObject *path)
1722 {
1723     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1724 }
1725 
1726 static PyObject *
path_object_error(PyObject *path)1727 path_object_error(PyObject *path)
1728 {
1729 #ifdef MS_WINDOWS
1730     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1731                 PyExc_OSError, 0, path);
1732 #else
1733     return posix_path_object_error(path);
1734 #endif
1735 }
1736 
1737 static PyObject *
path_object_error2(PyObject *path, PyObject *path2)1738 path_object_error2(PyObject *path, PyObject *path2)
1739 {
1740 #ifdef MS_WINDOWS
1741     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1742                 PyExc_OSError, 0, path, path2);
1743 #else
1744     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1745 #endif
1746 }
1747 
1748 static PyObject *
path_error(path_t *path)1749 path_error(path_t *path)
1750 {
1751     return path_object_error(path->object);
1752 }
1753 
1754 static PyObject *
posix_path_error(path_t *path)1755 posix_path_error(path_t *path)
1756 {
1757     return posix_path_object_error(path->object);
1758 }
1759 
1760 static PyObject *
path_error2(path_t *path, path_t *path2)1761 path_error2(path_t *path, path_t *path2)
1762 {
1763     return path_object_error2(path->object, path2->object);
1764 }
1765 
1766 
1767 /* POSIX generic methods */
1768 
1769 static PyObject *
posix_fildes_fd(int fd, int (*func)(int))1770 posix_fildes_fd(int fd, int (*func)(int))
1771 {
1772     int res;
1773     int async_err = 0;
1774 
1775     do {
1776         Py_BEGIN_ALLOW_THREADS
1777         _Py_BEGIN_SUPPRESS_IPH
1778         res = (*func)(fd);
1779         _Py_END_SUPPRESS_IPH
1780         Py_END_ALLOW_THREADS
1781     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1782     if (res != 0)
1783         return (!async_err) ? posix_error() : NULL;
1784     Py_RETURN_NONE;
1785 }
1786 
1787 
1788 #ifdef MS_WINDOWS
1789 /* This is a reimplementation of the C library's chdir function,
1790    but one that produces Win32 errors instead of DOS error codes.
1791    chdir is essentially a wrapper around SetCurrentDirectory; however,
1792    it also needs to set "magic" environment variables indicating
1793    the per-drive current directory, which are of the form =<drive>: */
1794 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1795 win32_wchdir(LPCWSTR path)
1796 {
1797     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1798     int result;
1799     wchar_t env[4] = L"=x:";
1800 
1801     if(!SetCurrentDirectoryW(path))
1802         return FALSE;
1803     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1804     if (!result)
1805         return FALSE;
1806     if (result > Py_ARRAY_LENGTH(path_buf)) {
1807         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1808         if (!new_path) {
1809             SetLastError(ERROR_OUTOFMEMORY);
1810             return FALSE;
1811         }
1812         result = GetCurrentDirectoryW(result, new_path);
1813         if (!result) {
1814             PyMem_RawFree(new_path);
1815             return FALSE;
1816         }
1817     }
1818     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1819                             wcsncmp(new_path, L"//", 2) == 0);
1820     if (!is_unc_like_path) {
1821         env[1] = new_path[0];
1822         result = SetEnvironmentVariableW(env, new_path);
1823     }
1824     if (new_path != path_buf)
1825         PyMem_RawFree(new_path);
1826     return result ? TRUE : FALSE;
1827 }
1828 #endif
1829 
1830 #ifdef MS_WINDOWS
1831 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1832    - time stamps are restricted to second resolution
1833    - file modification times suffer from forth-and-back conversions between
1834      UTC and local time
1835    Therefore, we implement our own stat, based on the Win32 API directly.
1836 */
1837 #define HAVE_STAT_NSEC 1
1838 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1839 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1840 
1841 static void
find_data_to_file_info(WIN32_FIND_DATAW *pFileData, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)1842 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1843                        BY_HANDLE_FILE_INFORMATION *info,
1844                        ULONG *reparse_tag)
1845 {
1846     memset(info, 0, sizeof(*info));
1847     info->dwFileAttributes = pFileData->dwFileAttributes;
1848     info->ftCreationTime   = pFileData->ftCreationTime;
1849     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1850     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1851     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1852     info->nFileSizeLow     = pFileData->nFileSizeLow;
1853 /*  info->nNumberOfLinks   = 1; */
1854     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1855         *reparse_tag = pFileData->dwReserved0;
1856     else
1857         *reparse_tag = 0;
1858 }
1859 
1860 static BOOL
attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)1861 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1862 {
1863     HANDLE hFindFile;
1864     WIN32_FIND_DATAW FileData;
1865     LPCWSTR filename = pszFile;
1866     size_t n = wcslen(pszFile);
1867     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1868         // cannot use PyMem_Malloc here because we do not hold the GIL
1869         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1870         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1871         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1872             ((LPWSTR)filename)[n] = L'\0';
1873         }
1874         if (!n || (n == 1 && filename[1] == L':')) {
1875             // Nothing left to query
1876             free((void *)filename);
1877             return FALSE;
1878         }
1879     }
1880     hFindFile = FindFirstFileW(filename, &FileData);
1881     if (pszFile != filename) {
1882         free((void *)filename);
1883     }
1884     if (hFindFile == INVALID_HANDLE_VALUE) {
1885         return FALSE;
1886     }
1887     FindClose(hFindFile);
1888     find_data_to_file_info(&FileData, info, reparse_tag);
1889     return TRUE;
1890 }
1891 
1892 static int
win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)1893 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1894                  BOOL traverse)
1895 {
1896     HANDLE hFile;
1897     BY_HANDLE_FILE_INFORMATION fileInfo;
1898     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1899     DWORD fileType, error;
1900     BOOL isUnhandledTag = FALSE;
1901     int retval = 0;
1902 
1903     DWORD access = FILE_READ_ATTRIBUTES;
1904     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1905     if (!traverse) {
1906         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1907     }
1908 
1909     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1910     if (hFile == INVALID_HANDLE_VALUE) {
1911         /* Either the path doesn't exist, or the caller lacks access. */
1912         error = GetLastError();
1913         switch (error) {
1914         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1915         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1916             /* Try reading the parent directory. */
1917             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1918                 /* Cannot read the parent directory. */
1919                 switch (GetLastError()) {
1920                 case ERROR_FILE_NOT_FOUND: /* File cannot be found */
1921                 case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
1922                 case ERROR_NOT_READY: /* Drive exists but unavailable */
1923                 case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
1924                     break;
1925                 /* Restore the error from CreateFileW(). */
1926                 default:
1927                     SetLastError(error);
1928                 }
1929 
1930                 return -1;
1931             }
1932             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1933                 if (traverse ||
1934                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1935                     /* The stat call has to traverse but cannot, so fail. */
1936                     SetLastError(error);
1937                     return -1;
1938                 }
1939             }
1940             break;
1941 
1942         case ERROR_INVALID_PARAMETER:
1943             /* \\.\con requires read or write access. */
1944             hFile = CreateFileW(path, access | GENERIC_READ,
1945                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1946                         OPEN_EXISTING, flags, NULL);
1947             if (hFile == INVALID_HANDLE_VALUE) {
1948                 SetLastError(error);
1949                 return -1;
1950             }
1951             break;
1952 
1953         case ERROR_CANT_ACCESS_FILE:
1954             /* bpo37834: open unhandled reparse points if traverse fails. */
1955             if (traverse) {
1956                 traverse = FALSE;
1957                 isUnhandledTag = TRUE;
1958                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1959                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1960             }
1961             if (hFile == INVALID_HANDLE_VALUE) {
1962                 SetLastError(error);
1963                 return -1;
1964             }
1965             break;
1966 
1967         default:
1968             return -1;
1969         }
1970     }
1971 
1972     if (hFile != INVALID_HANDLE_VALUE) {
1973         /* Handle types other than files on disk. */
1974         fileType = GetFileType(hFile);
1975         if (fileType != FILE_TYPE_DISK) {
1976             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1977                 retval = -1;
1978                 goto cleanup;
1979             }
1980             DWORD fileAttributes = GetFileAttributesW(path);
1981             memset(result, 0, sizeof(*result));
1982             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1983                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1984                 /* \\.\pipe\ or \\.\mailslot\ */
1985                 result->st_mode = _S_IFDIR;
1986             } else if (fileType == FILE_TYPE_CHAR) {
1987                 /* \\.\nul */
1988                 result->st_mode = _S_IFCHR;
1989             } else if (fileType == FILE_TYPE_PIPE) {
1990                 /* \\.\pipe\spam */
1991                 result->st_mode = _S_IFIFO;
1992             }
1993             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1994             goto cleanup;
1995         }
1996 
1997         /* Query the reparse tag, and traverse a non-link. */
1998         if (!traverse) {
1999             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
2000                     &tagInfo, sizeof(tagInfo))) {
2001                 /* Allow devices that do not support FileAttributeTagInfo. */
2002                 switch (GetLastError()) {
2003                 case ERROR_INVALID_PARAMETER:
2004                 case ERROR_INVALID_FUNCTION:
2005                 case ERROR_NOT_SUPPORTED:
2006                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2007                     tagInfo.ReparseTag = 0;
2008                     break;
2009                 default:
2010                     retval = -1;
2011                     goto cleanup;
2012                 }
2013             } else if (tagInfo.FileAttributes &
2014                          FILE_ATTRIBUTE_REPARSE_POINT) {
2015                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2016                     if (isUnhandledTag) {
2017                         /* Traversing previously failed for either this link
2018                            or its target. */
2019                         SetLastError(ERROR_CANT_ACCESS_FILE);
2020                         retval = -1;
2021                         goto cleanup;
2022                     }
2023                 /* Traverse a non-link, but not if traversing already failed
2024                    for an unhandled tag. */
2025                 } else if (!isUnhandledTag) {
2026                     CloseHandle(hFile);
2027                     return win32_xstat_impl(path, result, TRUE);
2028                 }
2029             }
2030         }
2031 
2032         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
2033             switch (GetLastError()) {
2034             case ERROR_INVALID_PARAMETER:
2035             case ERROR_INVALID_FUNCTION:
2036             case ERROR_NOT_SUPPORTED:
2037                 /* Volumes and physical disks are block devices, e.g.
2038                    \\.\C: and \\.\PhysicalDrive0. */
2039                 memset(result, 0, sizeof(*result));
2040                 result->st_mode = 0x6000; /* S_IFBLK */
2041                 goto cleanup;
2042             }
2043             retval = -1;
2044             goto cleanup;
2045         }
2046     }
2047 
2048     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2049 
2050     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2051         /* Fix the file execute permissions. This hack sets S_IEXEC if
2052            the filename has an extension that is commonly used by files
2053            that CreateProcessW can execute. A real implementation calls
2054            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2055            AccessCheck to check for generic read, write, and execute
2056            access. */
2057         const wchar_t *fileExtension = wcsrchr(path, '.');
2058         if (fileExtension) {
2059             if (_wcsicmp(fileExtension, L".exe") == 0 ||
2060                 _wcsicmp(fileExtension, L".bat") == 0 ||
2061                 _wcsicmp(fileExtension, L".cmd") == 0 ||
2062                 _wcsicmp(fileExtension, L".com") == 0) {
2063                 result->st_mode |= 0111;
2064             }
2065         }
2066     }
2067 
2068 cleanup:
2069     if (hFile != INVALID_HANDLE_VALUE) {
2070         /* Preserve last error if we are failing */
2071         error = retval ? GetLastError() : 0;
2072         if (!CloseHandle(hFile)) {
2073             retval = -1;
2074         } else if (retval) {
2075             /* Restore last error */
2076             SetLastError(error);
2077         }
2078     }
2079 
2080     return retval;
2081 }
2082 
2083 static int
win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)2084 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2085 {
2086     /* Protocol violation: we explicitly clear errno, instead of
2087        setting it to a POSIX error. Callers should use GetLastError. */
2088     int code = win32_xstat_impl(path, result, traverse);
2089     errno = 0;
2090     return code;
2091 }
2092 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2093 
2094    In Posix, stat automatically traverses symlinks and returns the stat
2095    structure for the target.  In Windows, the equivalent GetFileAttributes by
2096    default does not traverse symlinks and instead returns attributes for
2097    the symlink.
2098 
2099    Instead, we will open the file (which *does* traverse symlinks by default)
2100    and GetFileInformationByHandle(). */
2101 
2102 static int
win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)2103 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2104 {
2105     return win32_xstat(path, result, FALSE);
2106 }
2107 
2108 static int
win32_stat(const wchar_t* path, struct _Py_stat_struct *result)2109 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2110 {
2111     return win32_xstat(path, result, TRUE);
2112 }
2113 
2114 #endif /* MS_WINDOWS */
2115 
2116 PyDoc_STRVAR(stat_result__doc__,
2117 "stat_result: Result from stat, fstat, or lstat.\n\n\
2118 This object may be accessed either as a tuple of\n\
2119   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2120 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2121 \n\
2122 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2123 or st_flags, they are available as attributes only.\n\
2124 \n\
2125 See os.stat for more information.");
2126 
2127 static PyStructSequence_Field stat_result_fields[] = {
2128     {"st_mode",    "protection bits"},
2129     {"st_ino",     "inode"},
2130     {"st_dev",     "device"},
2131     {"st_nlink",   "number of hard links"},
2132     {"st_uid",     "user ID of owner"},
2133     {"st_gid",     "group ID of owner"},
2134     {"st_size",    "total size, in bytes"},
2135     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2136     {NULL,   "integer time of last access"},
2137     {NULL,   "integer time of last modification"},
2138     {NULL,   "integer time of last change"},
2139     {"st_atime",   "time of last access"},
2140     {"st_mtime",   "time of last modification"},
2141     {"st_ctime",   "time of last change"},
2142     {"st_atime_ns",   "time of last access in nanoseconds"},
2143     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2144     {"st_ctime_ns",   "time of last change in nanoseconds"},
2145 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2146     {"st_blksize", "blocksize for filesystem I/O"},
2147 #endif
2148 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2149     {"st_blocks",  "number of blocks allocated"},
2150 #endif
2151 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2152     {"st_rdev",    "device type (if inode device)"},
2153 #endif
2154 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2155     {"st_flags",   "user defined flags for file"},
2156 #endif
2157 #ifdef HAVE_STRUCT_STAT_ST_GEN
2158     {"st_gen",    "generation number"},
2159 #endif
2160 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2161     {"st_birthtime",   "time of creation"},
2162 #endif
2163 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2164     {"st_file_attributes", "Windows file attribute bits"},
2165 #endif
2166 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2167     {"st_fstype",  "Type of filesystem"},
2168 #endif
2169 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2170     {"st_reparse_tag", "Windows reparse tag"},
2171 #endif
2172     {0}
2173 };
2174 
2175 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2176 #define ST_BLKSIZE_IDX 16
2177 #else
2178 #define ST_BLKSIZE_IDX 15
2179 #endif
2180 
2181 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2182 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2183 #else
2184 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2185 #endif
2186 
2187 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2188 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2189 #else
2190 #define ST_RDEV_IDX ST_BLOCKS_IDX
2191 #endif
2192 
2193 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2194 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2195 #else
2196 #define ST_FLAGS_IDX ST_RDEV_IDX
2197 #endif
2198 
2199 #ifdef HAVE_STRUCT_STAT_ST_GEN
2200 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2201 #else
2202 #define ST_GEN_IDX ST_FLAGS_IDX
2203 #endif
2204 
2205 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2206 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2207 #else
2208 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2209 #endif
2210 
2211 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2212 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2213 #else
2214 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2215 #endif
2216 
2217 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2218 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2219 #else
2220 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2221 #endif
2222 
2223 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2224 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2225 #else
2226 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2227 #endif
2228 
2229 static PyStructSequence_Desc stat_result_desc = {
2230     "stat_result", /* name */
2231     stat_result__doc__, /* doc */
2232     stat_result_fields,
2233     10
2234 };
2235 
2236 PyDoc_STRVAR(statvfs_result__doc__,
2237 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2238 This object may be accessed either as a tuple of\n\
2239   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2240 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2241 \n\
2242 See os.statvfs for more information.");
2243 
2244 static PyStructSequence_Field statvfs_result_fields[] = {
2245     {"f_bsize",  },
2246     {"f_frsize", },
2247     {"f_blocks", },
2248     {"f_bfree",  },
2249     {"f_bavail", },
2250     {"f_files",  },
2251     {"f_ffree",  },
2252     {"f_favail", },
2253     {"f_flag",   },
2254     {"f_namemax",},
2255     {"f_fsid",   },
2256     {0}
2257 };
2258 
2259 static PyStructSequence_Desc statvfs_result_desc = {
2260     "statvfs_result", /* name */
2261     statvfs_result__doc__, /* doc */
2262     statvfs_result_fields,
2263     10
2264 };
2265 
2266 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2267 PyDoc_STRVAR(waitid_result__doc__,
2268 "waitid_result: Result from waitid.\n\n\
2269 This object may be accessed either as a tuple of\n\
2270   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2271 or via the attributes si_pid, si_uid, and so on.\n\
2272 \n\
2273 See os.waitid for more information.");
2274 
2275 static PyStructSequence_Field waitid_result_fields[] = {
2276     {"si_pid",  },
2277     {"si_uid", },
2278     {"si_signo", },
2279     {"si_status",  },
2280     {"si_code", },
2281     {0}
2282 };
2283 
2284 static PyStructSequence_Desc waitid_result_desc = {
2285     "waitid_result", /* name */
2286     waitid_result__doc__, /* doc */
2287     waitid_result_fields,
2288     5
2289 };
2290 #endif
2291 static newfunc structseq_new;
2292 
2293 static PyObject *
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)2294 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2295 {
2296     PyStructSequence *result;
2297     int i;
2298 
2299     result = (PyStructSequence*)structseq_new(type, args, kwds);
2300     if (!result)
2301         return NULL;
2302     /* If we have been initialized from a tuple,
2303        st_?time might be set to None. Initialize it
2304        from the int slots.  */
2305     for (i = 7; i <= 9; i++) {
2306         if (result->ob_item[i+3] == Py_None) {
2307             Py_DECREF(Py_None);
2308             Py_INCREF(result->ob_item[i]);
2309             result->ob_item[i+3] = result->ob_item[i];
2310         }
2311     }
2312     return (PyObject*)result;
2313 }
2314 
2315 static int
_posix_clear(PyObject *module)2316 _posix_clear(PyObject *module)
2317 {
2318     _posixstate *state = get_posix_state(module);
2319     Py_CLEAR(state->billion);
2320     Py_CLEAR(state->DirEntryType);
2321     Py_CLEAR(state->ScandirIteratorType);
2322 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2323     Py_CLEAR(state->SchedParamType);
2324 #endif
2325     Py_CLEAR(state->StatResultType);
2326     Py_CLEAR(state->StatVFSResultType);
2327     Py_CLEAR(state->TerminalSizeType);
2328     Py_CLEAR(state->TimesResultType);
2329     Py_CLEAR(state->UnameResultType);
2330 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2331     Py_CLEAR(state->WaitidResultType);
2332 #endif
2333 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2334     Py_CLEAR(state->struct_rusage);
2335 #endif
2336     Py_CLEAR(state->st_mode);
2337     return 0;
2338 }
2339 
2340 static int
_posix_traverse(PyObject *module, visitproc visit, void *arg)2341 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2342 {
2343     _posixstate *state = get_posix_state(module);
2344     Py_VISIT(state->billion);
2345     Py_VISIT(state->DirEntryType);
2346     Py_VISIT(state->ScandirIteratorType);
2347 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2348     Py_VISIT(state->SchedParamType);
2349 #endif
2350     Py_VISIT(state->StatResultType);
2351     Py_VISIT(state->StatVFSResultType);
2352     Py_VISIT(state->TerminalSizeType);
2353     Py_VISIT(state->TimesResultType);
2354     Py_VISIT(state->UnameResultType);
2355 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2356     Py_VISIT(state->WaitidResultType);
2357 #endif
2358 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2359     Py_VISIT(state->struct_rusage);
2360 #endif
2361     Py_VISIT(state->st_mode);
2362     return 0;
2363 }
2364 
2365 static void
_posix_free(void *module)2366 _posix_free(void *module)
2367 {
2368    _posix_clear((PyObject *)module);
2369 }
2370 
2371 static void
fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)2372 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2373 {
2374     PyObject *s = _PyLong_FromTime_t(sec);
2375     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2376     PyObject *s_in_ns = NULL;
2377     PyObject *ns_total = NULL;
2378     PyObject *float_s = NULL;
2379 
2380     if (!(s && ns_fractional))
2381         goto exit;
2382 
2383     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2384     if (!s_in_ns)
2385         goto exit;
2386 
2387     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2388     if (!ns_total)
2389         goto exit;
2390 
2391     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2392     if (!float_s) {
2393         goto exit;
2394     }
2395 
2396     PyStructSequence_SET_ITEM(v, index, s);
2397     PyStructSequence_SET_ITEM(v, index+3, float_s);
2398     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2399     s = NULL;
2400     float_s = NULL;
2401     ns_total = NULL;
2402 exit:
2403     Py_XDECREF(s);
2404     Py_XDECREF(ns_fractional);
2405     Py_XDECREF(s_in_ns);
2406     Py_XDECREF(ns_total);
2407     Py_XDECREF(float_s);
2408 }
2409 
2410 /* pack a system stat C structure into the Python stat tuple
2411    (used by posix_stat() and posix_fstat()) */
2412 static PyObject*
_pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)2413 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2414 {
2415     unsigned long ansec, mnsec, cnsec;
2416     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2417     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2418     if (v == NULL)
2419         return NULL;
2420 
2421     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2422     static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2423                   "stat.st_ino is larger than unsigned long long");
2424     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2425 #ifdef MS_WINDOWS
2426     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2427 #else
2428     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2429 #endif
2430     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2431 #if defined(MS_WINDOWS)
2432     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2433     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2434 #else
2435     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2436     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2437 #endif
2438     static_assert(sizeof(long long) >= sizeof(st->st_size),
2439                   "stat.st_size is larger than long long");
2440     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2441 
2442 #if defined(HAVE_STAT_TV_NSEC)
2443     ansec = st->st_atim.tv_nsec;
2444     mnsec = st->st_mtim.tv_nsec;
2445     cnsec = st->st_ctim.tv_nsec;
2446 #elif defined(HAVE_STAT_TV_NSEC2)
2447     ansec = st->st_atimespec.tv_nsec;
2448     mnsec = st->st_mtimespec.tv_nsec;
2449     cnsec = st->st_ctimespec.tv_nsec;
2450 #elif defined(HAVE_STAT_NSEC)
2451     ansec = st->st_atime_nsec;
2452     mnsec = st->st_mtime_nsec;
2453     cnsec = st->st_ctime_nsec;
2454 #else
2455     ansec = mnsec = cnsec = 0;
2456 #endif
2457     fill_time(module, v, 7, st->st_atime, ansec);
2458     fill_time(module, v, 8, st->st_mtime, mnsec);
2459     fill_time(module, v, 9, st->st_ctime, cnsec);
2460 
2461 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2462     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2463                               PyLong_FromLong((long)st->st_blksize));
2464 #endif
2465 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2466     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2467                               PyLong_FromLong((long)st->st_blocks));
2468 #endif
2469 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2470     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2471                               PyLong_FromLong((long)st->st_rdev));
2472 #endif
2473 #ifdef HAVE_STRUCT_STAT_ST_GEN
2474     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2475                               PyLong_FromLong((long)st->st_gen));
2476 #endif
2477 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2478     {
2479       PyObject *val;
2480       unsigned long bsec,bnsec;
2481       bsec = (long)st->st_birthtime;
2482 #ifdef HAVE_STAT_TV_NSEC2
2483       bnsec = st->st_birthtimespec.tv_nsec;
2484 #else
2485       bnsec = 0;
2486 #endif
2487       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2488       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2489                                 val);
2490     }
2491 #endif
2492 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2493     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2494                               PyLong_FromLong((long)st->st_flags));
2495 #endif
2496 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2497     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2498                               PyLong_FromUnsignedLong(st->st_file_attributes));
2499 #endif
2500 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2501    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2502                               PyUnicode_FromString(st->st_fstype));
2503 #endif
2504 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2505     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2506                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2507 #endif
2508 
2509     if (PyErr_Occurred()) {
2510         Py_DECREF(v);
2511         return NULL;
2512     }
2513 
2514     return v;
2515 }
2516 
2517 /* POSIX methods */
2518 
2519 
2520 static PyObject *
posix_do_stat(PyObject *module, const char *function_name, path_t *path, int dir_fd, int follow_symlinks)2521 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2522               int dir_fd, int follow_symlinks)
2523 {
2524     STRUCT_STAT st;
2525     int result;
2526 
2527 #ifdef HAVE_FSTATAT
2528     int fstatat_unavailable = 0;
2529 #endif
2530 
2531 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2532     if (follow_symlinks_specified(function_name, follow_symlinks))
2533         return NULL;
2534 #endif
2535 
2536     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2537         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2538         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2539         return NULL;
2540 
2541     Py_BEGIN_ALLOW_THREADS
2542     if (path->fd != -1)
2543         result = FSTAT(path->fd, &st);
2544 #ifdef MS_WINDOWS
2545     else if (follow_symlinks)
2546         result = win32_stat(path->wide, &st);
2547     else
2548         result = win32_lstat(path->wide, &st);
2549 #else
2550     else
2551 #if defined(HAVE_LSTAT)
2552     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2553         result = LSTAT(path->narrow, &st);
2554     else
2555 #endif /* HAVE_LSTAT */
2556 #ifdef HAVE_FSTATAT
2557     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2558         if (HAVE_FSTATAT_RUNTIME) {
2559             result = fstatat(dir_fd, path->narrow, &st,
2560                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2561 
2562         } else {
2563             fstatat_unavailable = 1;
2564         }
2565     } else
2566 #endif /* HAVE_FSTATAT */
2567         result = STAT(path->narrow, &st);
2568 #endif /* MS_WINDOWS */
2569     Py_END_ALLOW_THREADS
2570 
2571 #ifdef HAVE_FSTATAT
2572     if (fstatat_unavailable) {
2573         argument_unavailable_error("stat", "dir_fd");
2574         return NULL;
2575     }
2576 #endif
2577 
2578     if (result != 0) {
2579         return path_error(path);
2580     }
2581 
2582     return _pystat_fromstructstat(module, &st);
2583 }
2584 
2585 /*[python input]
2586 
2587 for s in """
2588 
2589 FACCESSAT
2590 FCHMODAT
2591 FCHOWNAT
2592 FSTATAT
2593 LINKAT
2594 MKDIRAT
2595 MKFIFOAT
2596 MKNODAT
2597 OPENAT
2598 READLINKAT
2599 SYMLINKAT
2600 UNLINKAT
2601 
2602 """.strip().split():
2603     s = s.strip()
2604     print("""
2605 #ifdef HAVE_{s}
2606     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2607 #else
2608     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2609 #endif
2610 """.rstrip().format(s=s))
2611 
2612 for s in """
2613 
2614 FCHDIR
2615 FCHMOD
2616 FCHOWN
2617 FDOPENDIR
2618 FEXECVE
2619 FPATHCONF
2620 FSTATVFS
2621 FTRUNCATE
2622 
2623 """.strip().split():
2624     s = s.strip()
2625     print("""
2626 #ifdef HAVE_{s}
2627     #define PATH_HAVE_{s} 1
2628 #else
2629     #define PATH_HAVE_{s} 0
2630 #endif
2631 
2632 """.rstrip().format(s=s))
2633 [python start generated code]*/
2634 
2635 #ifdef HAVE_FACCESSAT
2636     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2637 #else
2638     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2639 #endif
2640 
2641 #ifdef HAVE_FCHMODAT
2642     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2643 #else
2644     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2645 #endif
2646 
2647 #ifdef HAVE_FCHOWNAT
2648     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2649 #else
2650     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2651 #endif
2652 
2653 #ifdef HAVE_FSTATAT
2654     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2655 #else
2656     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2657 #endif
2658 
2659 #ifdef HAVE_LINKAT
2660     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2661 #else
2662     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2663 #endif
2664 
2665 #ifdef HAVE_MKDIRAT
2666     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2667 #else
2668     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2669 #endif
2670 
2671 #ifdef HAVE_MKFIFOAT
2672     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2673 #else
2674     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2675 #endif
2676 
2677 #ifdef HAVE_MKNODAT
2678     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2679 #else
2680     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2681 #endif
2682 
2683 #ifdef HAVE_OPENAT
2684     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2685 #else
2686     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2687 #endif
2688 
2689 #ifdef HAVE_READLINKAT
2690     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2691 #else
2692     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2693 #endif
2694 
2695 #ifdef HAVE_SYMLINKAT
2696     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2697 #else
2698     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2699 #endif
2700 
2701 #ifdef HAVE_UNLINKAT
2702     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2703 #else
2704     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2705 #endif
2706 
2707 #ifdef HAVE_FCHDIR
2708     #define PATH_HAVE_FCHDIR 1
2709 #else
2710     #define PATH_HAVE_FCHDIR 0
2711 #endif
2712 
2713 #ifdef HAVE_FCHMOD
2714     #define PATH_HAVE_FCHMOD 1
2715 #else
2716     #define PATH_HAVE_FCHMOD 0
2717 #endif
2718 
2719 #ifdef HAVE_FCHOWN
2720     #define PATH_HAVE_FCHOWN 1
2721 #else
2722     #define PATH_HAVE_FCHOWN 0
2723 #endif
2724 
2725 #ifdef HAVE_FDOPENDIR
2726     #define PATH_HAVE_FDOPENDIR 1
2727 #else
2728     #define PATH_HAVE_FDOPENDIR 0
2729 #endif
2730 
2731 #ifdef HAVE_FEXECVE
2732     #define PATH_HAVE_FEXECVE 1
2733 #else
2734     #define PATH_HAVE_FEXECVE 0
2735 #endif
2736 
2737 #ifdef HAVE_FPATHCONF
2738     #define PATH_HAVE_FPATHCONF 1
2739 #else
2740     #define PATH_HAVE_FPATHCONF 0
2741 #endif
2742 
2743 #ifdef HAVE_FSTATVFS
2744     #define PATH_HAVE_FSTATVFS 1
2745 #else
2746     #define PATH_HAVE_FSTATVFS 0
2747 #endif
2748 
2749 #ifdef HAVE_FTRUNCATE
2750     #define PATH_HAVE_FTRUNCATE 1
2751 #else
2752     #define PATH_HAVE_FTRUNCATE 0
2753 #endif
2754 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2755 
2756 #ifdef MS_WINDOWS
2757     #undef PATH_HAVE_FTRUNCATE
2758     #define PATH_HAVE_FTRUNCATE 1
2759 #endif
2760 
2761 /*[python input]
2762 
2763 class path_t_converter(CConverter):
2764 
2765     type = "path_t"
2766     impl_by_reference = True
2767     parse_by_reference = True
2768 
2769     converter = 'path_converter'
2770 
2771     def converter_init(self, *, allow_fd=False, nullable=False):
2772         # right now path_t doesn't support default values.
2773         # to support a default value, you'll need to override initialize().
2774         if self.default not in (unspecified, None):
2775             fail("Can't specify a default to the path_t converter!")
2776 
2777         if self.c_default not in (None, 'Py_None'):
2778             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2779 
2780         self.nullable = nullable
2781         self.allow_fd = allow_fd
2782 
2783     def pre_render(self):
2784         def strify(value):
2785             if isinstance(value, str):
2786                 return value
2787             return str(int(bool(value)))
2788 
2789         # add self.py_name here when merging with posixmodule conversion
2790         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2791             self.function.name,
2792             self.name,
2793             strify(self.nullable),
2794             strify(self.allow_fd),
2795             )
2796 
2797     def cleanup(self):
2798         return "path_cleanup(&" + self.name + ");\n"
2799 
2800 
2801 class dir_fd_converter(CConverter):
2802     type = 'int'
2803 
2804     def converter_init(self, requires=None):
2805         if self.default in (unspecified, None):
2806             self.c_default = 'DEFAULT_DIR_FD'
2807         if isinstance(requires, str):
2808             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2809         else:
2810             self.converter = 'dir_fd_converter'
2811 
2812 class uid_t_converter(CConverter):
2813     type = "uid_t"
2814     converter = '_Py_Uid_Converter'
2815 
2816 class gid_t_converter(CConverter):
2817     type = "gid_t"
2818     converter = '_Py_Gid_Converter'
2819 
2820 class dev_t_converter(CConverter):
2821     type = 'dev_t'
2822     converter = '_Py_Dev_Converter'
2823 
2824 class dev_t_return_converter(unsigned_long_return_converter):
2825     type = 'dev_t'
2826     conversion_fn = '_PyLong_FromDev'
2827     unsigned_cast = '(dev_t)'
2828 
2829 class FSConverter_converter(CConverter):
2830     type = 'PyObject *'
2831     converter = 'PyUnicode_FSConverter'
2832     def converter_init(self):
2833         if self.default is not unspecified:
2834             fail("FSConverter_converter does not support default values")
2835         self.c_default = 'NULL'
2836 
2837     def cleanup(self):
2838         return "Py_XDECREF(" + self.name + ");\n"
2839 
2840 class pid_t_converter(CConverter):
2841     type = 'pid_t'
2842     format_unit = '" _Py_PARSE_PID "'
2843 
2844 class idtype_t_converter(int_converter):
2845     type = 'idtype_t'
2846 
2847 class id_t_converter(CConverter):
2848     type = 'id_t'
2849     format_unit = '" _Py_PARSE_PID "'
2850 
2851 class intptr_t_converter(CConverter):
2852     type = 'intptr_t'
2853     format_unit = '" _Py_PARSE_INTPTR "'
2854 
2855 class Py_off_t_converter(CConverter):
2856     type = 'Py_off_t'
2857     converter = 'Py_off_t_converter'
2858 
2859 class Py_off_t_return_converter(long_return_converter):
2860     type = 'Py_off_t'
2861     conversion_fn = 'PyLong_FromPy_off_t'
2862 
2863 class path_confname_converter(CConverter):
2864     type="int"
2865     converter="conv_path_confname"
2866 
2867 class confstr_confname_converter(path_confname_converter):
2868     converter='conv_confstr_confname'
2869 
2870 class sysconf_confname_converter(path_confname_converter):
2871     converter="conv_sysconf_confname"
2872 
2873 [python start generated code]*/
2874 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2875 
2876 /*[clinic input]
2877 
2878 os.stat
2879 
2880     path : path_t(allow_fd=True)
2881         Path to be examined; can be string, bytes, a path-like object or
2882         open-file-descriptor int.
2883 
2884     *
2885 
2886     dir_fd : dir_fd(requires='fstatat') = None
2887         If not None, it should be a file descriptor open to a directory,
2888         and path should be a relative string; path will then be relative to
2889         that directory.
2890 
2891     follow_symlinks: bool = True
2892         If False, and the last element of the path is a symbolic link,
2893         stat will examine the symbolic link itself instead of the file
2894         the link points to.
2895 
2896 Perform a stat system call on the given path.
2897 
2898 dir_fd and follow_symlinks may not be implemented
2899   on your platform.  If they are unavailable, using them will raise a
2900   NotImplementedError.
2901 
2902 It's an error to use dir_fd or follow_symlinks when specifying path as
2903   an open file descriptor.
2904 
2905 [clinic start generated code]*/
2906 
2907 static PyObject *
os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)2908 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2909 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2910 {
2911     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2912 }
2913 
2914 
2915 /*[clinic input]
2916 os.lstat
2917 
2918     path : path_t
2919 
2920     *
2921 
2922     dir_fd : dir_fd(requires='fstatat') = None
2923 
2924 Perform a stat system call on the given path, without following symbolic links.
2925 
2926 Like stat(), but do not follow symbolic links.
2927 Equivalent to stat(path, follow_symlinks=False).
2928 [clinic start generated code]*/
2929 
2930 static PyObject *
os_lstat_impl(PyObject *module, path_t *path, int dir_fd)2931 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2932 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2933 {
2934     int follow_symlinks = 0;
2935     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2936 }
2937 
2938 
2939 /*[clinic input]
2940 os.access -> bool
2941 
2942     path: path_t
2943         Path to be tested; can be string, bytes, or a path-like object.
2944 
2945     mode: int
2946         Operating-system mode bitfield.  Can be F_OK to test existence,
2947         or the inclusive-OR of R_OK, W_OK, and X_OK.
2948 
2949     *
2950 
2951     dir_fd : dir_fd(requires='faccessat') = None
2952         If not None, it should be a file descriptor open to a directory,
2953         and path should be relative; path will then be relative to that
2954         directory.
2955 
2956     effective_ids: bool = False
2957         If True, access will use the effective uid/gid instead of
2958         the real uid/gid.
2959 
2960     follow_symlinks: bool = True
2961         If False, and the last element of the path is a symbolic link,
2962         access will examine the symbolic link itself instead of the file
2963         the link points to.
2964 
2965 Use the real uid/gid to test for access to a path.
2966 
2967 {parameters}
2968 dir_fd, effective_ids, and follow_symlinks may not be implemented
2969   on your platform.  If they are unavailable, using them will raise a
2970   NotImplementedError.
2971 
2972 Note that most operations will use the effective uid/gid, therefore this
2973   routine can be used in a suid/sgid environment to test if the invoking user
2974   has the specified access to the path.
2975 
2976 [clinic start generated code]*/
2977 
2978 static int
os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks)2979 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2980                int effective_ids, int follow_symlinks)
2981 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2982 {
2983     int return_value;
2984 
2985 #ifdef MS_WINDOWS
2986     DWORD attr;
2987 #else
2988     int result;
2989 #endif
2990 
2991 #ifdef HAVE_FACCESSAT
2992     int faccessat_unavailable = 0;
2993 #endif
2994 
2995 #ifndef HAVE_FACCESSAT
2996     if (follow_symlinks_specified("access", follow_symlinks))
2997         return -1;
2998 
2999     if (effective_ids) {
3000         argument_unavailable_error("access", "effective_ids");
3001         return -1;
3002     }
3003 #endif
3004 
3005 #ifdef MS_WINDOWS
3006     Py_BEGIN_ALLOW_THREADS
3007     attr = GetFileAttributesW(path->wide);
3008     Py_END_ALLOW_THREADS
3009 
3010     /*
3011      * Access is possible if
3012      *   * we didn't get a -1, and
3013      *     * write access wasn't requested,
3014      *     * or the file isn't read-only,
3015      *     * or it's a directory.
3016      * (Directories cannot be read-only on Windows.)
3017     */
3018     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3019             (!(mode & 2) ||
3020             !(attr & FILE_ATTRIBUTE_READONLY) ||
3021             (attr & FILE_ATTRIBUTE_DIRECTORY));
3022 #else
3023 
3024     Py_BEGIN_ALLOW_THREADS
3025 #ifdef HAVE_FACCESSAT
3026     if ((dir_fd != DEFAULT_DIR_FD) ||
3027         effective_ids ||
3028         !follow_symlinks) {
3029 
3030         if (HAVE_FACCESSAT_RUNTIME) {
3031             int flags = 0;
3032             if (!follow_symlinks)
3033                 flags |= AT_SYMLINK_NOFOLLOW;
3034             if (effective_ids)
3035                 flags |= AT_EACCESS;
3036             result = faccessat(dir_fd, path->narrow, mode, flags);
3037         } else {
3038             faccessat_unavailable = 1;
3039         }
3040     }
3041     else
3042 #endif
3043         result = access(path->narrow, mode);
3044     Py_END_ALLOW_THREADS
3045 
3046 #ifdef HAVE_FACCESSAT
3047     if (faccessat_unavailable) {
3048         if (dir_fd != DEFAULT_DIR_FD) {
3049             argument_unavailable_error("access", "dir_fd");
3050             return -1;
3051         }
3052         if (follow_symlinks_specified("access", follow_symlinks))
3053             return -1;
3054 
3055         if (effective_ids) {
3056             argument_unavailable_error("access", "effective_ids");
3057             return -1;
3058         }
3059         /* should be unreachable */
3060         return -1;
3061     }
3062 #endif
3063     return_value = !result;
3064 #endif
3065 
3066     return return_value;
3067 }
3068 
3069 #ifndef F_OK
3070 #define F_OK 0
3071 #endif
3072 #ifndef R_OK
3073 #define R_OK 4
3074 #endif
3075 #ifndef W_OK
3076 #define W_OK 2
3077 #endif
3078 #ifndef X_OK
3079 #define X_OK 1
3080 #endif
3081 
3082 
3083 #ifdef HAVE_TTYNAME
3084 /*[clinic input]
3085 os.ttyname
3086 
3087     fd: int
3088         Integer file descriptor handle.
3089 
3090     /
3091 
3092 Return the name of the terminal device connected to 'fd'.
3093 [clinic start generated code]*/
3094 
3095 static PyObject *
os_ttyname_impl(PyObject *module, int fd)3096 os_ttyname_impl(PyObject *module, int fd)
3097 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3098 {
3099 
3100     long size = sysconf(_SC_TTY_NAME_MAX);
3101     if (size == -1) {
3102         return posix_error();
3103     }
3104     char *buffer = (char *)PyMem_RawMalloc(size);
3105     if (buffer == NULL) {
3106         return PyErr_NoMemory();
3107     }
3108     int ret = ttyname_r(fd, buffer, size);
3109     if (ret != 0) {
3110         PyMem_RawFree(buffer);
3111         errno = ret;
3112         return posix_error();
3113     }
3114     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3115     PyMem_RawFree(buffer);
3116     return res;
3117 }
3118 #endif
3119 
3120 #ifdef HAVE_CTERMID
3121 /*[clinic input]
3122 os.ctermid
3123 
3124 Return the name of the controlling terminal for this process.
3125 [clinic start generated code]*/
3126 
3127 static PyObject *
os_ctermid_impl(PyObject *module)3128 os_ctermid_impl(PyObject *module)
3129 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3130 {
3131     char *ret;
3132     char buffer[L_ctermid];
3133 
3134 #ifdef USE_CTERMID_R
3135     ret = ctermid_r(buffer);
3136 #else
3137     ret = ctermid(buffer);
3138 #endif
3139     if (ret == NULL)
3140         return posix_error();
3141     return PyUnicode_DecodeFSDefault(buffer);
3142 }
3143 #endif /* HAVE_CTERMID */
3144 
3145 
3146 /*[clinic input]
3147 os.chdir
3148 
3149     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3150 
3151 Change the current working directory to the specified path.
3152 
3153 path may always be specified as a string.
3154 On some platforms, path may also be specified as an open file descriptor.
3155   If this functionality is unavailable, using it raises an exception.
3156 [clinic start generated code]*/
3157 
3158 static PyObject *
os_chdir_impl(PyObject *module, path_t *path)3159 os_chdir_impl(PyObject *module, path_t *path)
3160 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3161 {
3162     int result;
3163 
3164     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3165         return NULL;
3166     }
3167 
3168     Py_BEGIN_ALLOW_THREADS
3169 #ifdef MS_WINDOWS
3170     /* on unix, success = 0, on windows, success = !0 */
3171     result = !win32_wchdir(path->wide);
3172 #else
3173 #ifdef HAVE_FCHDIR
3174     if (path->fd != -1)
3175         result = fchdir(path->fd);
3176     else
3177 #endif
3178         result = chdir(path->narrow);
3179 #endif
3180     Py_END_ALLOW_THREADS
3181 
3182     if (result) {
3183         return path_error(path);
3184     }
3185 
3186     Py_RETURN_NONE;
3187 }
3188 
3189 
3190 #ifdef HAVE_FCHDIR
3191 /*[clinic input]
3192 os.fchdir
3193 
3194     fd: fildes
3195 
3196 Change to the directory of the given file descriptor.
3197 
3198 fd must be opened on a directory, not a file.
3199 Equivalent to os.chdir(fd).
3200 
3201 [clinic start generated code]*/
3202 
3203 static PyObject *
os_fchdir_impl(PyObject *module, int fd)3204 os_fchdir_impl(PyObject *module, int fd)
3205 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3206 {
3207     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3208         return NULL;
3209     }
3210     return posix_fildes_fd(fd, fchdir);
3211 }
3212 #endif /* HAVE_FCHDIR */
3213 
3214 
3215 /*[clinic input]
3216 os.chmod
3217 
3218     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3219         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3220         On some platforms, path may also be specified as an open file descriptor.
3221         If this functionality is unavailable, using it raises an exception.
3222 
3223     mode: int
3224         Operating-system mode bitfield.
3225 
3226     *
3227 
3228     dir_fd : dir_fd(requires='fchmodat') = None
3229         If not None, it should be a file descriptor open to a directory,
3230         and path should be relative; path will then be relative to that
3231         directory.
3232 
3233     follow_symlinks: bool = True
3234         If False, and the last element of the path is a symbolic link,
3235         chmod will modify the symbolic link itself instead of the file
3236         the link points to.
3237 
3238 Change the access permissions of a file.
3239 
3240 It is an error to use dir_fd or follow_symlinks when specifying path as
3241   an open file descriptor.
3242 dir_fd and follow_symlinks may not be implemented on your platform.
3243   If they are unavailable, using them will raise a NotImplementedError.
3244 
3245 [clinic start generated code]*/
3246 
3247 static PyObject *
os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd, int follow_symlinks)3248 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3249               int follow_symlinks)
3250 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3251 {
3252     int result;
3253 
3254 #ifdef MS_WINDOWS
3255     DWORD attr;
3256 #endif
3257 
3258 #ifdef HAVE_FCHMODAT
3259     int fchmodat_nofollow_unsupported = 0;
3260     int fchmodat_unsupported = 0;
3261 #endif
3262 
3263 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3264     if (follow_symlinks_specified("chmod", follow_symlinks))
3265         return NULL;
3266 #endif
3267 
3268     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3269                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3270         return NULL;
3271     }
3272 
3273 #ifdef MS_WINDOWS
3274     Py_BEGIN_ALLOW_THREADS
3275     attr = GetFileAttributesW(path->wide);
3276     if (attr == INVALID_FILE_ATTRIBUTES)
3277         result = 0;
3278     else {
3279         if (mode & _S_IWRITE)
3280             attr &= ~FILE_ATTRIBUTE_READONLY;
3281         else
3282             attr |= FILE_ATTRIBUTE_READONLY;
3283         result = SetFileAttributesW(path->wide, attr);
3284     }
3285     Py_END_ALLOW_THREADS
3286 
3287     if (!result) {
3288         return path_error(path);
3289     }
3290 #else /* MS_WINDOWS */
3291     Py_BEGIN_ALLOW_THREADS
3292 #ifdef HAVE_FCHMOD
3293     if (path->fd != -1)
3294         result = fchmod(path->fd, mode);
3295     else
3296 #endif /* HAVE_CHMOD */
3297 #ifdef HAVE_LCHMOD
3298     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3299         result = lchmod(path->narrow, mode);
3300     else
3301 #endif /* HAVE_LCHMOD */
3302 #ifdef HAVE_FCHMODAT
3303     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3304         if (HAVE_FCHMODAT_RUNTIME) {
3305             /*
3306              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3307              * The documentation specifically shows how to use it,
3308              * and then says it isn't implemented yet.
3309              * (true on linux with glibc 2.15, and openindiana 3.x)
3310              *
3311              * Once it is supported, os.chmod will automatically
3312              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3313              * Until then, we need to be careful what exception we raise.
3314              */
3315             result = fchmodat(dir_fd, path->narrow, mode,
3316                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3317             /*
3318              * But wait!  We can't throw the exception without allowing threads,
3319              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3320              */
3321             fchmodat_nofollow_unsupported =
3322                              result &&
3323                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3324                              !follow_symlinks;
3325         } else {
3326             fchmodat_unsupported = 1;
3327             fchmodat_nofollow_unsupported = 1;
3328 
3329             result = -1;
3330         }
3331     }
3332     else
3333 #endif /* HAVE_FHCMODAT */
3334     {
3335 #ifdef HAVE_CHMOD
3336         result = chmod(path->narrow, mode);
3337 #elif defined(__wasi__)
3338         // WASI SDK 15.0 does not support chmod.
3339         // Ignore missing syscall for now.
3340         result = 0;
3341 #else
3342         result = -1;
3343         errno = ENOSYS;
3344 #endif
3345     }
3346     Py_END_ALLOW_THREADS
3347 
3348     if (result) {
3349 #ifdef HAVE_FCHMODAT
3350         if (fchmodat_unsupported) {
3351             if (dir_fd != DEFAULT_DIR_FD) {
3352                 argument_unavailable_error("chmod", "dir_fd");
3353                 return NULL;
3354             }
3355         }
3356 
3357         if (fchmodat_nofollow_unsupported) {
3358             if (dir_fd != DEFAULT_DIR_FD)
3359                 dir_fd_and_follow_symlinks_invalid("chmod",
3360                                                    dir_fd, follow_symlinks);
3361             else
3362                 follow_symlinks_specified("chmod", follow_symlinks);
3363             return NULL;
3364         }
3365         else
3366 #endif /* HAVE_FCHMODAT */
3367         return path_error(path);
3368     }
3369 #endif /* MS_WINDOWS */
3370 
3371     Py_RETURN_NONE;
3372 }
3373 
3374 
3375 #ifdef HAVE_FCHMOD
3376 /*[clinic input]
3377 os.fchmod
3378 
3379     fd: int
3380     mode: int
3381 
3382 Change the access permissions of the file given by file descriptor fd.
3383 
3384 Equivalent to os.chmod(fd, mode).
3385 [clinic start generated code]*/
3386 
3387 static PyObject *
os_fchmod_impl(PyObject *module, int fd, int mode)3388 os_fchmod_impl(PyObject *module, int fd, int mode)
3389 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3390 {
3391     int res;
3392     int async_err = 0;
3393 
3394     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3395         return NULL;
3396     }
3397 
3398     do {
3399         Py_BEGIN_ALLOW_THREADS
3400         res = fchmod(fd, mode);
3401         Py_END_ALLOW_THREADS
3402     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3403     if (res != 0)
3404         return (!async_err) ? posix_error() : NULL;
3405 
3406     Py_RETURN_NONE;
3407 }
3408 #endif /* HAVE_FCHMOD */
3409 
3410 
3411 #ifdef HAVE_LCHMOD
3412 /*[clinic input]
3413 os.lchmod
3414 
3415     path: path_t
3416     mode: int
3417 
3418 Change the access permissions of a file, without following symbolic links.
3419 
3420 If path is a symlink, this affects the link itself rather than the target.
3421 Equivalent to chmod(path, mode, follow_symlinks=False)."
3422 [clinic start generated code]*/
3423 
3424 static PyObject *
os_lchmod_impl(PyObject *module, path_t *path, int mode)3425 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3426 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3427 {
3428     int res;
3429     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3430         return NULL;
3431     }
3432     Py_BEGIN_ALLOW_THREADS
3433     res = lchmod(path->narrow, mode);
3434     Py_END_ALLOW_THREADS
3435     if (res < 0) {
3436         path_error(path);
3437         return NULL;
3438     }
3439     Py_RETURN_NONE;
3440 }
3441 #endif /* HAVE_LCHMOD */
3442 
3443 
3444 #ifdef HAVE_CHFLAGS
3445 /*[clinic input]
3446 os.chflags
3447 
3448     path: path_t
3449     flags: unsigned_long(bitwise=True)
3450     follow_symlinks: bool=True
3451 
3452 Set file flags.
3453 
3454 If follow_symlinks is False, and the last element of the path is a symbolic
3455   link, chflags will change flags on the symbolic link itself instead of the
3456   file the link points to.
3457 follow_symlinks may not be implemented on your platform.  If it is
3458 unavailable, using it will raise a NotImplementedError.
3459 
3460 [clinic start generated code]*/
3461 
3462 static PyObject *
os_chflags_impl(PyObject *module, path_t *path, unsigned long flags, int follow_symlinks)3463 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3464                 int follow_symlinks)
3465 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3466 {
3467     int result;
3468 
3469 #ifndef HAVE_LCHFLAGS
3470     if (follow_symlinks_specified("chflags", follow_symlinks))
3471         return NULL;
3472 #endif
3473 
3474     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3475         return NULL;
3476     }
3477 
3478     Py_BEGIN_ALLOW_THREADS
3479 #ifdef HAVE_LCHFLAGS
3480     if (!follow_symlinks)
3481         result = lchflags(path->narrow, flags);
3482     else
3483 #endif
3484         result = chflags(path->narrow, flags);
3485     Py_END_ALLOW_THREADS
3486 
3487     if (result)
3488         return path_error(path);
3489 
3490     Py_RETURN_NONE;
3491 }
3492 #endif /* HAVE_CHFLAGS */
3493 
3494 
3495 #ifdef HAVE_LCHFLAGS
3496 /*[clinic input]
3497 os.lchflags
3498 
3499     path: path_t
3500     flags: unsigned_long(bitwise=True)
3501 
3502 Set file flags.
3503 
3504 This function will not follow symbolic links.
3505 Equivalent to chflags(path, flags, follow_symlinks=False).
3506 [clinic start generated code]*/
3507 
3508 static PyObject *
os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)3509 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3510 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3511 {
3512     int res;
3513     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3514         return NULL;
3515     }
3516     Py_BEGIN_ALLOW_THREADS
3517     res = lchflags(path->narrow, flags);
3518     Py_END_ALLOW_THREADS
3519     if (res < 0) {
3520         return path_error(path);
3521     }
3522     Py_RETURN_NONE;
3523 }
3524 #endif /* HAVE_LCHFLAGS */
3525 
3526 
3527 #ifdef HAVE_CHROOT
3528 /*[clinic input]
3529 os.chroot
3530     path: path_t
3531 
3532 Change root directory to path.
3533 
3534 [clinic start generated code]*/
3535 
3536 static PyObject *
os_chroot_impl(PyObject *module, path_t *path)3537 os_chroot_impl(PyObject *module, path_t *path)
3538 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3539 {
3540     int res;
3541     Py_BEGIN_ALLOW_THREADS
3542     res = chroot(path->narrow);
3543     Py_END_ALLOW_THREADS
3544     if (res < 0)
3545         return path_error(path);
3546     Py_RETURN_NONE;
3547 }
3548 #endif /* HAVE_CHROOT */
3549 
3550 
3551 #ifdef HAVE_FSYNC
3552 /*[clinic input]
3553 os.fsync
3554 
3555     fd: fildes
3556 
3557 Force write of fd to disk.
3558 [clinic start generated code]*/
3559 
3560 static PyObject *
os_fsync_impl(PyObject *module, int fd)3561 os_fsync_impl(PyObject *module, int fd)
3562 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3563 {
3564     return posix_fildes_fd(fd, fsync);
3565 }
3566 #endif /* HAVE_FSYNC */
3567 
3568 
3569 #ifdef HAVE_SYNC
3570 /*[clinic input]
3571 os.sync
3572 
3573 Force write of everything to disk.
3574 [clinic start generated code]*/
3575 
3576 static PyObject *
os_sync_impl(PyObject *module)3577 os_sync_impl(PyObject *module)
3578 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3579 {
3580     Py_BEGIN_ALLOW_THREADS
3581     sync();
3582     Py_END_ALLOW_THREADS
3583     Py_RETURN_NONE;
3584 }
3585 #endif /* HAVE_SYNC */
3586 
3587 
3588 #ifdef HAVE_FDATASYNC
3589 #ifdef __hpux
3590 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3591 #endif
3592 
3593 /*[clinic input]
3594 os.fdatasync
3595 
3596     fd: fildes
3597 
3598 Force write of fd to disk without forcing update of metadata.
3599 [clinic start generated code]*/
3600 
3601 static PyObject *
os_fdatasync_impl(PyObject *module, int fd)3602 os_fdatasync_impl(PyObject *module, int fd)
3603 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3604 {
3605     return posix_fildes_fd(fd, fdatasync);
3606 }
3607 #endif /* HAVE_FDATASYNC */
3608 
3609 
3610 #ifdef HAVE_CHOWN
3611 /*[clinic input]
3612 os.chown
3613 
3614     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3615         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3616 
3617     uid: uid_t
3618 
3619     gid: gid_t
3620 
3621     *
3622 
3623     dir_fd : dir_fd(requires='fchownat') = None
3624         If not None, it should be a file descriptor open to a directory,
3625         and path should be relative; path will then be relative to that
3626         directory.
3627 
3628     follow_symlinks: bool = True
3629         If False, and the last element of the path is a symbolic link,
3630         stat will examine the symbolic link itself instead of the file
3631         the link points to.
3632 
3633 Change the owner and group id of path to the numeric uid and gid.\
3634 
3635 path may always be specified as a string.
3636 On some platforms, path may also be specified as an open file descriptor.
3637   If this functionality is unavailable, using it raises an exception.
3638 If dir_fd is not None, it should be a file descriptor open to a directory,
3639   and path should be relative; path will then be relative to that directory.
3640 If follow_symlinks is False, and the last element of the path is a symbolic
3641   link, chown will modify the symbolic link itself instead of the file the
3642   link points to.
3643 It is an error to use dir_fd or follow_symlinks when specifying path as
3644   an open file descriptor.
3645 dir_fd and follow_symlinks may not be implemented on your platform.
3646   If they are unavailable, using them will raise a NotImplementedError.
3647 
3648 [clinic start generated code]*/
3649 
3650 static PyObject *
os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks)3651 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3652               int dir_fd, int follow_symlinks)
3653 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3654 {
3655     int result;
3656 
3657 #if defined(HAVE_FCHOWNAT)
3658     int fchownat_unsupported = 0;
3659 #endif
3660 
3661 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3662     if (follow_symlinks_specified("chown", follow_symlinks))
3663         return NULL;
3664 #endif
3665     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3666         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3667         return NULL;
3668 
3669     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3670                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3671         return NULL;
3672     }
3673 
3674     Py_BEGIN_ALLOW_THREADS
3675 #ifdef HAVE_FCHOWN
3676     if (path->fd != -1)
3677         result = fchown(path->fd, uid, gid);
3678     else
3679 #endif
3680 #ifdef HAVE_LCHOWN
3681     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3682         result = lchown(path->narrow, uid, gid);
3683     else
3684 #endif
3685 #ifdef HAVE_FCHOWNAT
3686     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3687       if (HAVE_FCHOWNAT_RUNTIME) {
3688         result = fchownat(dir_fd, path->narrow, uid, gid,
3689                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3690       } else {
3691          fchownat_unsupported = 1;
3692       }
3693     } else
3694 #endif
3695         result = chown(path->narrow, uid, gid);
3696     Py_END_ALLOW_THREADS
3697 
3698 #ifdef HAVE_FCHOWNAT
3699     if (fchownat_unsupported) {
3700         /* This would be incorrect if the current platform
3701          * doesn't support lchown.
3702          */
3703         argument_unavailable_error(NULL, "dir_fd");
3704         return NULL;
3705     }
3706 #endif
3707 
3708     if (result)
3709         return path_error(path);
3710 
3711     Py_RETURN_NONE;
3712 }
3713 #endif /* HAVE_CHOWN */
3714 
3715 
3716 #ifdef HAVE_FCHOWN
3717 /*[clinic input]
3718 os.fchown
3719 
3720     fd: int
3721     uid: uid_t
3722     gid: gid_t
3723 
3724 Change the owner and group id of the file specified by file descriptor.
3725 
3726 Equivalent to os.chown(fd, uid, gid).
3727 
3728 [clinic start generated code]*/
3729 
3730 static PyObject *
os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)3731 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3732 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3733 {
3734     int res;
3735     int async_err = 0;
3736 
3737     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3738         return NULL;
3739     }
3740 
3741     do {
3742         Py_BEGIN_ALLOW_THREADS
3743         res = fchown(fd, uid, gid);
3744         Py_END_ALLOW_THREADS
3745     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3746     if (res != 0)
3747         return (!async_err) ? posix_error() : NULL;
3748 
3749     Py_RETURN_NONE;
3750 }
3751 #endif /* HAVE_FCHOWN */
3752 
3753 
3754 #ifdef HAVE_LCHOWN
3755 /*[clinic input]
3756 os.lchown
3757 
3758     path : path_t
3759     uid: uid_t
3760     gid: gid_t
3761 
3762 Change the owner and group id of path to the numeric uid and gid.
3763 
3764 This function will not follow symbolic links.
3765 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3766 [clinic start generated code]*/
3767 
3768 static PyObject *
os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)3769 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3770 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3771 {
3772     int res;
3773     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3774         return NULL;
3775     }
3776     Py_BEGIN_ALLOW_THREADS
3777     res = lchown(path->narrow, uid, gid);
3778     Py_END_ALLOW_THREADS
3779     if (res < 0) {
3780         return path_error(path);
3781     }
3782     Py_RETURN_NONE;
3783 }
3784 #endif /* HAVE_LCHOWN */
3785 
3786 
3787 static PyObject *
posix_getcwd(int use_bytes)3788 posix_getcwd(int use_bytes)
3789 {
3790 #ifdef MS_WINDOWS
3791     wchar_t wbuf[MAXPATHLEN];
3792     wchar_t *wbuf2 = wbuf;
3793     DWORD len;
3794 
3795     Py_BEGIN_ALLOW_THREADS
3796     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3797     /* If the buffer is large enough, len does not include the
3798        terminating \0. If the buffer is too small, len includes
3799        the space needed for the terminator. */
3800     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3801         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3802             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3803         }
3804         else {
3805             wbuf2 = NULL;
3806         }
3807         if (wbuf2) {
3808             len = GetCurrentDirectoryW(len, wbuf2);
3809         }
3810     }
3811     Py_END_ALLOW_THREADS
3812 
3813     if (!wbuf2) {
3814         PyErr_NoMemory();
3815         return NULL;
3816     }
3817     if (!len) {
3818         if (wbuf2 != wbuf)
3819             PyMem_RawFree(wbuf2);
3820         return PyErr_SetFromWindowsErr(0);
3821     }
3822 
3823     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3824     if (wbuf2 != wbuf) {
3825         PyMem_RawFree(wbuf2);
3826     }
3827 
3828     if (use_bytes) {
3829         if (resobj == NULL) {
3830             return NULL;
3831         }
3832         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3833     }
3834 
3835     return resobj;
3836 #else
3837     const size_t chunk = 1024;
3838 
3839     char *buf = NULL;
3840     char *cwd = NULL;
3841     size_t buflen = 0;
3842 
3843     Py_BEGIN_ALLOW_THREADS
3844     do {
3845         char *newbuf;
3846         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3847             buflen += chunk;
3848             newbuf = PyMem_RawRealloc(buf, buflen);
3849         }
3850         else {
3851             newbuf = NULL;
3852         }
3853         if (newbuf == NULL) {
3854             PyMem_RawFree(buf);
3855             buf = NULL;
3856             break;
3857         }
3858         buf = newbuf;
3859 
3860         cwd = getcwd(buf, buflen);
3861     } while (cwd == NULL && errno == ERANGE);
3862     Py_END_ALLOW_THREADS
3863 
3864     if (buf == NULL) {
3865         return PyErr_NoMemory();
3866     }
3867     if (cwd == NULL) {
3868         PyMem_RawFree(buf);
3869         return posix_error();
3870     }
3871 
3872     PyObject *obj;
3873     if (use_bytes) {
3874         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3875     }
3876     else {
3877         obj = PyUnicode_DecodeFSDefault(buf);
3878     }
3879     PyMem_RawFree(buf);
3880 
3881     return obj;
3882 #endif   /* !MS_WINDOWS */
3883 }
3884 
3885 
3886 /*[clinic input]
3887 os.getcwd
3888 
3889 Return a unicode string representing the current working directory.
3890 [clinic start generated code]*/
3891 
3892 static PyObject *
os_getcwd_impl(PyObject *module)3893 os_getcwd_impl(PyObject *module)
3894 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3895 {
3896     return posix_getcwd(0);
3897 }
3898 
3899 
3900 /*[clinic input]
3901 os.getcwdb
3902 
3903 Return a bytes string representing the current working directory.
3904 [clinic start generated code]*/
3905 
3906 static PyObject *
os_getcwdb_impl(PyObject *module)3907 os_getcwdb_impl(PyObject *module)
3908 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3909 {
3910     return posix_getcwd(1);
3911 }
3912 
3913 
3914 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3915 #define HAVE_LINK 1
3916 #endif
3917 
3918 #ifdef HAVE_LINK
3919 /*[clinic input]
3920 
3921 os.link
3922 
3923     src : path_t
3924     dst : path_t
3925     *
3926     src_dir_fd : dir_fd = None
3927     dst_dir_fd : dir_fd = None
3928     follow_symlinks: bool = True
3929 
3930 Create a hard link to a file.
3931 
3932 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3933   descriptor open to a directory, and the respective path string (src or dst)
3934   should be relative; the path will then be relative to that directory.
3935 If follow_symlinks is False, and the last element of src is a symbolic
3936   link, link will create a link to the symbolic link itself instead of the
3937   file the link points to.
3938 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3939   platform.  If they are unavailable, using them will raise a
3940   NotImplementedError.
3941 [clinic start generated code]*/
3942 
3943 static PyObject *
os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks)3944 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3945              int dst_dir_fd, int follow_symlinks)
3946 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3947 {
3948 #ifdef MS_WINDOWS
3949     BOOL result = FALSE;
3950 #else
3951     int result;
3952 #endif
3953 #if defined(HAVE_LINKAT)
3954     int linkat_unavailable = 0;
3955 #endif
3956 
3957 #ifndef HAVE_LINKAT
3958     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3959         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3960         return NULL;
3961     }
3962 #endif
3963 
3964 #ifndef MS_WINDOWS
3965     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3966         PyErr_SetString(PyExc_NotImplementedError,
3967                         "link: src and dst must be the same type");
3968         return NULL;
3969     }
3970 #endif
3971 
3972     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3973                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3974                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3975         return NULL;
3976     }
3977 
3978 #ifdef MS_WINDOWS
3979     Py_BEGIN_ALLOW_THREADS
3980     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3981     Py_END_ALLOW_THREADS
3982 
3983     if (!result)
3984         return path_error2(src, dst);
3985 #else
3986     Py_BEGIN_ALLOW_THREADS
3987 #ifdef HAVE_LINKAT
3988     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3989         (dst_dir_fd != DEFAULT_DIR_FD) ||
3990         (!follow_symlinks)) {
3991 
3992         if (HAVE_LINKAT_RUNTIME) {
3993 
3994             result = linkat(src_dir_fd, src->narrow,
3995                 dst_dir_fd, dst->narrow,
3996                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3997 
3998         }
3999 #ifdef __APPLE__
4000         else {
4001             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
4002                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
4003                 result = link(src->narrow, dst->narrow);
4004             } else {
4005                 linkat_unavailable = 1;
4006             }
4007         }
4008 #endif
4009     }
4010     else
4011 #endif /* HAVE_LINKAT */
4012         result = link(src->narrow, dst->narrow);
4013     Py_END_ALLOW_THREADS
4014 
4015 #ifdef HAVE_LINKAT
4016     if (linkat_unavailable) {
4017         /* Either or both dir_fd arguments were specified */
4018         if (src_dir_fd  != DEFAULT_DIR_FD) {
4019             argument_unavailable_error("link", "src_dir_fd");
4020         } else {
4021             argument_unavailable_error("link", "dst_dir_fd");
4022         }
4023         return NULL;
4024     }
4025 #endif
4026 
4027     if (result)
4028         return path_error2(src, dst);
4029 #endif /* MS_WINDOWS */
4030 
4031     Py_RETURN_NONE;
4032 }
4033 #endif
4034 
4035 
4036 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4037 static PyObject *
_listdir_windows_no_opendir(path_t *path, PyObject *list)4038 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4039 {
4040     PyObject *v;
4041     HANDLE hFindFile = INVALID_HANDLE_VALUE;
4042     BOOL result;
4043     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4044     /* only claim to have space for MAX_PATH */
4045     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4046     wchar_t *wnamebuf = NULL;
4047 
4048     WIN32_FIND_DATAW wFileData;
4049     const wchar_t *po_wchars;
4050 
4051     if (!path->wide) { /* Default arg: "." */
4052         po_wchars = L".";
4053         len = 1;
4054     } else {
4055         po_wchars = path->wide;
4056         len = wcslen(path->wide);
4057     }
4058     /* The +5 is so we can append "\\*.*\0" */
4059     wnamebuf = PyMem_New(wchar_t, len + 5);
4060     if (!wnamebuf) {
4061         PyErr_NoMemory();
4062         goto exit;
4063     }
4064     wcscpy(wnamebuf, po_wchars);
4065     if (len > 0) {
4066         wchar_t wch = wnamebuf[len-1];
4067         if (wch != SEP && wch != ALTSEP && wch != L':')
4068             wnamebuf[len++] = SEP;
4069         wcscpy(wnamebuf + len, L"*.*");
4070     }
4071     if ((list = PyList_New(0)) == NULL) {
4072         goto exit;
4073     }
4074     Py_BEGIN_ALLOW_THREADS
4075     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4076     Py_END_ALLOW_THREADS
4077     if (hFindFile == INVALID_HANDLE_VALUE) {
4078         int error = GetLastError();
4079         if (error == ERROR_FILE_NOT_FOUND)
4080             goto exit;
4081         Py_DECREF(list);
4082         list = path_error(path);
4083         goto exit;
4084     }
4085     do {
4086         /* Skip over . and .. */
4087         if (wcscmp(wFileData.cFileName, L".") != 0 &&
4088             wcscmp(wFileData.cFileName, L"..") != 0) {
4089             v = PyUnicode_FromWideChar(wFileData.cFileName,
4090                                        wcslen(wFileData.cFileName));
4091             if (path->narrow && v) {
4092                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4093             }
4094             if (v == NULL) {
4095                 Py_DECREF(list);
4096                 list = NULL;
4097                 break;
4098             }
4099             if (PyList_Append(list, v) != 0) {
4100                 Py_DECREF(v);
4101                 Py_DECREF(list);
4102                 list = NULL;
4103                 break;
4104             }
4105             Py_DECREF(v);
4106         }
4107         Py_BEGIN_ALLOW_THREADS
4108         result = FindNextFileW(hFindFile, &wFileData);
4109         Py_END_ALLOW_THREADS
4110         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4111            it got to the end of the directory. */
4112         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4113             Py_DECREF(list);
4114             list = path_error(path);
4115             goto exit;
4116         }
4117     } while (result == TRUE);
4118 
4119 exit:
4120     if (hFindFile != INVALID_HANDLE_VALUE) {
4121         if (FindClose(hFindFile) == FALSE) {
4122             if (list != NULL) {
4123                 Py_DECREF(list);
4124                 list = path_error(path);
4125             }
4126         }
4127     }
4128     PyMem_Free(wnamebuf);
4129 
4130     return list;
4131 }  /* end of _listdir_windows_no_opendir */
4132 
4133 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4134 
4135 static PyObject *
_posix_listdir(path_t *path, PyObject *list)4136 _posix_listdir(path_t *path, PyObject *list)
4137 {
4138     PyObject *v;
4139     DIR *dirp = NULL;
4140     struct dirent *ep;
4141     int return_str; /* if false, return bytes */
4142 #ifdef HAVE_FDOPENDIR
4143     int fd = -1;
4144 #endif
4145 
4146     errno = 0;
4147 #ifdef HAVE_FDOPENDIR
4148     if (path->fd != -1) {
4149       if (HAVE_FDOPENDIR_RUNTIME) {
4150         /* closedir() closes the FD, so we duplicate it */
4151         fd = _Py_dup(path->fd);
4152         if (fd == -1)
4153             return NULL;
4154 
4155         return_str = 1;
4156 
4157         Py_BEGIN_ALLOW_THREADS
4158         dirp = fdopendir(fd);
4159         Py_END_ALLOW_THREADS
4160       } else {
4161         PyErr_SetString(PyExc_TypeError,
4162             "listdir: path should be string, bytes, os.PathLike or None, not int");
4163         return NULL;
4164       }
4165     }
4166     else
4167 #endif
4168     {
4169         const char *name;
4170         if (path->narrow) {
4171             name = path->narrow;
4172             /* only return bytes if they specified a bytes-like object */
4173             return_str = !PyObject_CheckBuffer(path->object);
4174         }
4175         else {
4176             name = ".";
4177             return_str = 1;
4178         }
4179 
4180         Py_BEGIN_ALLOW_THREADS
4181         dirp = opendir(name);
4182         Py_END_ALLOW_THREADS
4183     }
4184 
4185     if (dirp == NULL) {
4186         list = path_error(path);
4187 #ifdef HAVE_FDOPENDIR
4188         if (fd != -1) {
4189             Py_BEGIN_ALLOW_THREADS
4190             close(fd);
4191             Py_END_ALLOW_THREADS
4192         }
4193 #endif
4194         goto exit;
4195     }
4196     if ((list = PyList_New(0)) == NULL) {
4197         goto exit;
4198     }
4199     for (;;) {
4200         errno = 0;
4201         Py_BEGIN_ALLOW_THREADS
4202         ep = readdir(dirp);
4203         Py_END_ALLOW_THREADS
4204         if (ep == NULL) {
4205             if (errno == 0) {
4206                 break;
4207             } else {
4208                 Py_DECREF(list);
4209                 list = path_error(path);
4210                 goto exit;
4211             }
4212         }
4213         if (ep->d_name[0] == '.' &&
4214             (NAMLEN(ep) == 1 ||
4215              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4216             continue;
4217         if (return_str)
4218             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4219         else
4220             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4221         if (v == NULL) {
4222             Py_CLEAR(list);
4223             break;
4224         }
4225         if (PyList_Append(list, v) != 0) {
4226             Py_DECREF(v);
4227             Py_CLEAR(list);
4228             break;
4229         }
4230         Py_DECREF(v);
4231     }
4232 
4233 exit:
4234     if (dirp != NULL) {
4235         Py_BEGIN_ALLOW_THREADS
4236 #ifdef HAVE_FDOPENDIR
4237         if (fd > -1)
4238             rewinddir(dirp);
4239 #endif
4240         closedir(dirp);
4241         Py_END_ALLOW_THREADS
4242     }
4243 
4244     return list;
4245 }  /* end of _posix_listdir */
4246 #endif  /* which OS */
4247 
4248 
4249 /*[clinic input]
4250 os.listdir
4251 
4252     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4253 
4254 Return a list containing the names of the files in the directory.
4255 
4256 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4257   the filenames returned will also be bytes; in all other circumstances
4258   the filenames returned will be str.
4259 If path is None, uses the path='.'.
4260 On some platforms, path may also be specified as an open file descriptor;\
4261   the file descriptor must refer to a directory.
4262   If this functionality is unavailable, using it raises NotImplementedError.
4263 
4264 The list is in arbitrary order.  It does not include the special
4265 entries '.' and '..' even if they are present in the directory.
4266 
4267 
4268 [clinic start generated code]*/
4269 
4270 static PyObject *
os_listdir_impl(PyObject *module, path_t *path)4271 os_listdir_impl(PyObject *module, path_t *path)
4272 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4273 {
4274     if (PySys_Audit("os.listdir", "O",
4275                     path->object ? path->object : Py_None) < 0) {
4276         return NULL;
4277     }
4278 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4279     return _listdir_windows_no_opendir(path, NULL);
4280 #else
4281     return _posix_listdir(path, NULL);
4282 #endif
4283 }
4284 
4285 #ifdef MS_WINDOWS
4286 int
_PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)4287 _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4288 {
4289     wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4290     DWORD result;
4291 
4292     result = GetFullPathNameW(path,
4293                               Py_ARRAY_LENGTH(woutbuf), woutbuf,
4294                               NULL);
4295     if (!result) {
4296         return -1;
4297     }
4298 
4299     if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4300         if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4301             woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4302         }
4303         else {
4304             woutbufp = NULL;
4305         }
4306         if (!woutbufp) {
4307             *abspath_p = NULL;
4308             return 0;
4309         }
4310 
4311         result = GetFullPathNameW(path, result, woutbufp, NULL);
4312         if (!result) {
4313             PyMem_RawFree(woutbufp);
4314             return -1;
4315         }
4316     }
4317 
4318     if (woutbufp != woutbuf) {
4319         *abspath_p = woutbufp;
4320         return 0;
4321     }
4322 
4323     *abspath_p = _PyMem_RawWcsdup(woutbufp);
4324     return 0;
4325 }
4326 
4327 
4328 /* A helper function for abspath on win32 */
4329 /*[clinic input]
4330 os._getfullpathname
4331 
4332     path: path_t
4333     /
4334 
4335 [clinic start generated code]*/
4336 
4337 static PyObject *
os__getfullpathname_impl(PyObject *module, path_t *path)4338 os__getfullpathname_impl(PyObject *module, path_t *path)
4339 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4340 {
4341     wchar_t *abspath;
4342 
4343     if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4344         return win32_error_object("GetFullPathNameW", path->object);
4345     }
4346     if (abspath == NULL) {
4347         return PyErr_NoMemory();
4348     }
4349 
4350     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4351     PyMem_RawFree(abspath);
4352     if (str == NULL) {
4353         return NULL;
4354     }
4355     if (path->narrow) {
4356         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4357     }
4358     return str;
4359 }
4360 
4361 
4362 /*[clinic input]
4363 os._getfinalpathname
4364 
4365     path: path_t
4366     /
4367 
4368 A helper function for samepath on windows.
4369 [clinic start generated code]*/
4370 
4371 static PyObject *
os__getfinalpathname_impl(PyObject *module, path_t *path)4372 os__getfinalpathname_impl(PyObject *module, path_t *path)
4373 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4374 {
4375     HANDLE hFile;
4376     wchar_t buf[MAXPATHLEN], *target_path = buf;
4377     int buf_size = Py_ARRAY_LENGTH(buf);
4378     int result_length;
4379     PyObject *result;
4380 
4381     Py_BEGIN_ALLOW_THREADS
4382     hFile = CreateFileW(
4383         path->wide,
4384         0, /* desired access */
4385         0, /* share mode */
4386         NULL, /* security attributes */
4387         OPEN_EXISTING,
4388         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4389         FILE_FLAG_BACKUP_SEMANTICS,
4390         NULL);
4391     Py_END_ALLOW_THREADS
4392 
4393     if (hFile == INVALID_HANDLE_VALUE) {
4394         return win32_error_object("CreateFileW", path->object);
4395     }
4396 
4397     /* We have a good handle to the target, use it to determine the
4398        target path name. */
4399     while (1) {
4400         Py_BEGIN_ALLOW_THREADS
4401         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4402                                                   buf_size, VOLUME_NAME_DOS);
4403         Py_END_ALLOW_THREADS
4404 
4405         if (!result_length) {
4406             result = win32_error_object("GetFinalPathNameByHandleW",
4407                                          path->object);
4408             goto cleanup;
4409         }
4410 
4411         if (result_length < buf_size) {
4412             break;
4413         }
4414 
4415         wchar_t *tmp;
4416         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4417                             result_length * sizeof(*tmp));
4418         if (!tmp) {
4419             result = PyErr_NoMemory();
4420             goto cleanup;
4421         }
4422 
4423         buf_size = result_length;
4424         target_path = tmp;
4425     }
4426 
4427     result = PyUnicode_FromWideChar(target_path, result_length);
4428     if (result && path->narrow) {
4429         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4430     }
4431 
4432 cleanup:
4433     if (target_path != buf) {
4434         PyMem_Free(target_path);
4435     }
4436     CloseHandle(hFile);
4437     return result;
4438 }
4439 
4440 
4441 /*[clinic input]
4442 os._getvolumepathname
4443 
4444     path: path_t
4445 
4446 A helper function for ismount on Win32.
4447 [clinic start generated code]*/
4448 
4449 static PyObject *
os__getvolumepathname_impl(PyObject *module, path_t *path)4450 os__getvolumepathname_impl(PyObject *module, path_t *path)
4451 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4452 {
4453     PyObject *result;
4454     wchar_t *mountpath=NULL;
4455     size_t buflen;
4456     BOOL ret;
4457 
4458     /* Volume path should be shorter than entire path */
4459     buflen = Py_MAX(path->length, MAX_PATH);
4460 
4461     if (buflen > PY_DWORD_MAX) {
4462         PyErr_SetString(PyExc_OverflowError, "path too long");
4463         return NULL;
4464     }
4465 
4466     mountpath = PyMem_New(wchar_t, buflen);
4467     if (mountpath == NULL)
4468         return PyErr_NoMemory();
4469 
4470     Py_BEGIN_ALLOW_THREADS
4471     ret = GetVolumePathNameW(path->wide, mountpath,
4472                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4473     Py_END_ALLOW_THREADS
4474 
4475     if (!ret) {
4476         result = win32_error_object("_getvolumepathname", path->object);
4477         goto exit;
4478     }
4479     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4480     if (path->narrow)
4481         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4482 
4483 exit:
4484     PyMem_Free(mountpath);
4485     return result;
4486 }
4487 
4488 
4489 /*[clinic input]
4490 os._path_splitroot
4491 
4492     path: path_t
4493 
4494 Removes everything after the root on Win32.
4495 [clinic start generated code]*/
4496 
4497 static PyObject *
os__path_splitroot_impl(PyObject *module, path_t *path)4498 os__path_splitroot_impl(PyObject *module, path_t *path)
4499 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4500 {
4501     wchar_t *buffer;
4502     wchar_t *end;
4503     PyObject *result = NULL;
4504     HRESULT ret;
4505 
4506     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4507     if (!buffer) {
4508         return NULL;
4509     }
4510     wcscpy(buffer, path->wide);
4511     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4512         *p = L'\\';
4513     }
4514 
4515     Py_BEGIN_ALLOW_THREADS
4516     ret = PathCchSkipRoot(buffer, &end);
4517     Py_END_ALLOW_THREADS
4518     if (FAILED(ret)) {
4519         result = Py_BuildValue("sO", "", path->object);
4520     } else if (end != buffer) {
4521         size_t rootLen = (size_t)(end - buffer);
4522         result = Py_BuildValue("NN",
4523             PyUnicode_FromWideChar(path->wide, rootLen),
4524             PyUnicode_FromWideChar(path->wide + rootLen, -1)
4525         );
4526     } else {
4527         result = Py_BuildValue("Os", path->object, "");
4528     }
4529     PyMem_Free(buffer);
4530 
4531     return result;
4532 }
4533 
4534 
4535 #endif /* MS_WINDOWS */
4536 
4537 
4538 /*[clinic input]
4539 os._path_normpath
4540 
4541     path: object
4542 
4543 Basic path normalization.
4544 [clinic start generated code]*/
4545 
4546 static PyObject *
os__path_normpath_impl(PyObject *module, PyObject *path)4547 os__path_normpath_impl(PyObject *module, PyObject *path)
4548 /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4549 {
4550     if (!PyUnicode_Check(path)) {
4551         PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4552             Py_TYPE(path)->tp_name);
4553         return NULL;
4554     }
4555     Py_ssize_t len;
4556     wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4557     if (!buffer) {
4558         return NULL;
4559     }
4560     Py_ssize_t norm_len;
4561     wchar_t *norm_path = _Py_normpath_and_size(buffer, len, &norm_len);
4562     PyObject *result = PyUnicode_FromWideChar(norm_path, norm_len);
4563     PyMem_Free(buffer);
4564     return result;
4565 }
4566 
4567 /*[clinic input]
4568 os.mkdir
4569 
4570     path : path_t
4571 
4572     mode: int = 0o777
4573 
4574     *
4575 
4576     dir_fd : dir_fd(requires='mkdirat') = None
4577 
4578 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4579 
4580 Create a directory.
4581 
4582 If dir_fd is not None, it should be a file descriptor open to a directory,
4583   and path should be relative; path will then be relative to that directory.
4584 dir_fd may not be implemented on your platform.
4585   If it is unavailable, using it will raise a NotImplementedError.
4586 
4587 The mode argument is ignored on Windows. Where it is used, the current umask
4588 value is first masked out.
4589 [clinic start generated code]*/
4590 
4591 static PyObject *
os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)4592 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4593 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
4594 {
4595     int result;
4596 #ifdef MS_WINDOWS
4597     int error = 0;
4598     int pathError = 0;
4599     SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
4600     SECURITY_ATTRIBUTES *pSecAttr = NULL;
4601 #endif
4602 #ifdef HAVE_MKDIRAT
4603     int mkdirat_unavailable = 0;
4604 #endif
4605 
4606     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4607                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4608         return NULL;
4609     }
4610 
4611 #ifdef MS_WINDOWS
4612     Py_BEGIN_ALLOW_THREADS
4613     if (mode == 0700 /* 0o700 */) {
4614         ULONG sdSize;
4615         pSecAttr = &secAttr;
4616         // Set a discretionary ACL (D) that is protected (P) and includes
4617         // inheritable (OICI) entries that allow (A) full control (FA) to
4618         // SYSTEM (SY), Administrators (BA), and the owner (OW).
4619         if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
4620             L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
4621             SDDL_REVISION_1,
4622             &secAttr.lpSecurityDescriptor,
4623             &sdSize
4624         )) {
4625             error = GetLastError();
4626         }
4627     }
4628     if (!error) {
4629         result = CreateDirectoryW(path->wide, pSecAttr);
4630         if (secAttr.lpSecurityDescriptor &&
4631             // uncommonly, LocalFree returns non-zero on error, but still uses
4632             // GetLastError() to see what the error code is
4633             LocalFree(secAttr.lpSecurityDescriptor)) {
4634             error = GetLastError();
4635         }
4636     }
4637     Py_END_ALLOW_THREADS
4638 
4639     if (error) {
4640         return PyErr_SetFromWindowsErr(error);
4641     }
4642     if (!result) {
4643         return path_error(path);
4644     }
4645 #else
4646     Py_BEGIN_ALLOW_THREADS
4647 #if HAVE_MKDIRAT
4648     if (dir_fd != DEFAULT_DIR_FD) {
4649       if (HAVE_MKDIRAT_RUNTIME) {
4650         result = mkdirat(dir_fd, path->narrow, mode);
4651 
4652       } else {
4653         mkdirat_unavailable = 1;
4654       }
4655     } else
4656 #endif
4657 #if defined(__WATCOMC__) && !defined(__QNX__)
4658         result = mkdir(path->narrow);
4659 #else
4660         result = mkdir(path->narrow, mode);
4661 #endif
4662     Py_END_ALLOW_THREADS
4663 
4664 #if HAVE_MKDIRAT
4665     if (mkdirat_unavailable) {
4666         argument_unavailable_error(NULL, "dir_fd");
4667         return NULL;
4668     }
4669 #endif
4670 
4671     if (result < 0)
4672         return path_error(path);
4673 #endif /* MS_WINDOWS */
4674     Py_RETURN_NONE;
4675 }
4676 
4677 
4678 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4679 #if defined(HAVE_SYS_RESOURCE_H)
4680 #include <sys/resource.h>
4681 #endif
4682 
4683 
4684 #ifdef HAVE_NICE
4685 /*[clinic input]
4686 os.nice
4687 
4688     increment: int
4689     /
4690 
4691 Add increment to the priority of process and return the new priority.
4692 [clinic start generated code]*/
4693 
4694 static PyObject *
os_nice_impl(PyObject *module, int increment)4695 os_nice_impl(PyObject *module, int increment)
4696 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4697 {
4698     int value;
4699 
4700     /* There are two flavours of 'nice': one that returns the new
4701        priority (as required by almost all standards out there) and the
4702        Linux/FreeBSD one, which returns '0' on success and advices
4703        the use of getpriority() to get the new priority.
4704 
4705        If we are of the nice family that returns the new priority, we
4706        need to clear errno before the call, and check if errno is filled
4707        before calling posix_error() on a returnvalue of -1, because the
4708        -1 may be the actual new priority! */
4709 
4710     errno = 0;
4711     value = nice(increment);
4712 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4713     if (value == 0)
4714         value = getpriority(PRIO_PROCESS, 0);
4715 #endif
4716     if (value == -1 && errno != 0)
4717         /* either nice() or getpriority() returned an error */
4718         return posix_error();
4719     return PyLong_FromLong((long) value);
4720 }
4721 #endif /* HAVE_NICE */
4722 
4723 
4724 #ifdef HAVE_GETPRIORITY
4725 /*[clinic input]
4726 os.getpriority
4727 
4728     which: int
4729     who: int
4730 
4731 Return program scheduling priority.
4732 [clinic start generated code]*/
4733 
4734 static PyObject *
os_getpriority_impl(PyObject *module, int which, int who)4735 os_getpriority_impl(PyObject *module, int which, int who)
4736 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4737 {
4738     int retval;
4739 
4740     errno = 0;
4741     retval = getpriority(which, who);
4742     if (errno != 0)
4743         return posix_error();
4744     return PyLong_FromLong((long)retval);
4745 }
4746 #endif /* HAVE_GETPRIORITY */
4747 
4748 
4749 #ifdef HAVE_SETPRIORITY
4750 /*[clinic input]
4751 os.setpriority
4752 
4753     which: int
4754     who: int
4755     priority: int
4756 
4757 Set program scheduling priority.
4758 [clinic start generated code]*/
4759 
4760 static PyObject *
os_setpriority_impl(PyObject *module, int which, int who, int priority)4761 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4762 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4763 {
4764     int retval;
4765 
4766     retval = setpriority(which, who, priority);
4767     if (retval == -1)
4768         return posix_error();
4769     Py_RETURN_NONE;
4770 }
4771 #endif /* HAVE_SETPRIORITY */
4772 
4773 
4774 static PyObject *
internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)4775 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4776 {
4777     const char *function_name = is_replace ? "replace" : "rename";
4778     int dir_fd_specified;
4779 
4780 #ifdef HAVE_RENAMEAT
4781     int renameat_unavailable = 0;
4782 #endif
4783 
4784 #ifdef MS_WINDOWS
4785     BOOL result;
4786     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4787 #else
4788     int result;
4789 #endif
4790 
4791     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4792                        (dst_dir_fd != DEFAULT_DIR_FD);
4793 #ifndef HAVE_RENAMEAT
4794     if (dir_fd_specified) {
4795         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4796         return NULL;
4797     }
4798 #endif
4799 
4800     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4801                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4802                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4803         return NULL;
4804     }
4805 
4806 #ifdef MS_WINDOWS
4807     Py_BEGIN_ALLOW_THREADS
4808     result = MoveFileExW(src->wide, dst->wide, flags);
4809     Py_END_ALLOW_THREADS
4810 
4811     if (!result)
4812         return path_error2(src, dst);
4813 
4814 #else
4815     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4816         PyErr_Format(PyExc_ValueError,
4817                      "%s: src and dst must be the same type", function_name);
4818         return NULL;
4819     }
4820 
4821     Py_BEGIN_ALLOW_THREADS
4822 #ifdef HAVE_RENAMEAT
4823     if (dir_fd_specified) {
4824         if (HAVE_RENAMEAT_RUNTIME) {
4825             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4826         } else {
4827             renameat_unavailable = 1;
4828         }
4829     } else
4830 #endif
4831     result = rename(src->narrow, dst->narrow);
4832     Py_END_ALLOW_THREADS
4833 
4834 
4835 #ifdef HAVE_RENAMEAT
4836     if (renameat_unavailable) {
4837         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4838         return NULL;
4839     }
4840 #endif
4841 
4842     if (result)
4843         return path_error2(src, dst);
4844 #endif
4845     Py_RETURN_NONE;
4846 }
4847 
4848 
4849 /*[clinic input]
4850 os.rename
4851 
4852     src : path_t
4853     dst : path_t
4854     *
4855     src_dir_fd : dir_fd = None
4856     dst_dir_fd : dir_fd = None
4857 
4858 Rename a file or directory.
4859 
4860 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4861   descriptor open to a directory, and the respective path string (src or dst)
4862   should be relative; the path will then be relative to that directory.
4863 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4864   If they are unavailable, using them will raise a NotImplementedError.
4865 [clinic start generated code]*/
4866 
4867 static PyObject *
os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd)4868 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4869                int dst_dir_fd)
4870 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4871 {
4872     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4873 }
4874 
4875 
4876 /*[clinic input]
4877 os.replace = os.rename
4878 
4879 Rename a file or directory, overwriting the destination.
4880 
4881 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4882   descriptor open to a directory, and the respective path string (src or dst)
4883   should be relative; the path will then be relative to that directory.
4884 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4885   If they are unavailable, using them will raise a NotImplementedError.
4886 [clinic start generated code]*/
4887 
4888 static PyObject *
os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd)4889 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4890                 int dst_dir_fd)
4891 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4892 {
4893     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4894 }
4895 
4896 
4897 /*[clinic input]
4898 os.rmdir
4899 
4900     path: path_t
4901     *
4902     dir_fd: dir_fd(requires='unlinkat') = None
4903 
4904 Remove a directory.
4905 
4906 If dir_fd is not None, it should be a file descriptor open to a directory,
4907   and path should be relative; path will then be relative to that directory.
4908 dir_fd may not be implemented on your platform.
4909   If it is unavailable, using it will raise a NotImplementedError.
4910 [clinic start generated code]*/
4911 
4912 static PyObject *
os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)4913 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4914 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4915 {
4916     int result;
4917 #ifdef HAVE_UNLINKAT
4918     int unlinkat_unavailable = 0;
4919 #endif
4920 
4921     if (PySys_Audit("os.rmdir", "Oi", path->object,
4922                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4923         return NULL;
4924     }
4925 
4926     Py_BEGIN_ALLOW_THREADS
4927 #ifdef MS_WINDOWS
4928     /* Windows, success=1, UNIX, success=0 */
4929     result = !RemoveDirectoryW(path->wide);
4930 #else
4931 #ifdef HAVE_UNLINKAT
4932     if (dir_fd != DEFAULT_DIR_FD) {
4933       if (HAVE_UNLINKAT_RUNTIME) {
4934         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4935       } else {
4936         unlinkat_unavailable = 1;
4937         result = -1;
4938       }
4939     } else
4940 #endif
4941         result = rmdir(path->narrow);
4942 #endif
4943     Py_END_ALLOW_THREADS
4944 
4945 #ifdef HAVE_UNLINKAT
4946     if (unlinkat_unavailable) {
4947         argument_unavailable_error("rmdir", "dir_fd");
4948         return NULL;
4949     }
4950 #endif
4951 
4952     if (result)
4953         return path_error(path);
4954 
4955     Py_RETURN_NONE;
4956 }
4957 
4958 
4959 #ifdef HAVE_SYSTEM
4960 #ifdef MS_WINDOWS
4961 /*[clinic input]
4962 os.system -> long
4963 
4964     command: Py_UNICODE
4965 
4966 Execute the command in a subshell.
4967 [clinic start generated code]*/
4968 
4969 static long
os_system_impl(PyObject *module, const Py_UNICODE *command)4970 os_system_impl(PyObject *module, const Py_UNICODE *command)
4971 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4972 {
4973     long result;
4974 
4975     if (PySys_Audit("os.system", "(u)", command) < 0) {
4976         return -1;
4977     }
4978 
4979     Py_BEGIN_ALLOW_THREADS
4980     _Py_BEGIN_SUPPRESS_IPH
4981     result = _wsystem(command);
4982     _Py_END_SUPPRESS_IPH
4983     Py_END_ALLOW_THREADS
4984     return result;
4985 }
4986 #else /* MS_WINDOWS */
4987 /*[clinic input]
4988 os.system -> long
4989 
4990     command: FSConverter
4991 
4992 Execute the command in a subshell.
4993 [clinic start generated code]*/
4994 
4995 static long
os_system_impl(PyObject *module, PyObject *command)4996 os_system_impl(PyObject *module, PyObject *command)
4997 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4998 {
4999     long result;
5000     const char *bytes = PyBytes_AsString(command);
5001 
5002     if (PySys_Audit("os.system", "(O)", command) < 0) {
5003         return -1;
5004     }
5005 
5006     Py_BEGIN_ALLOW_THREADS
5007     result = system(bytes);
5008     Py_END_ALLOW_THREADS
5009     return result;
5010 }
5011 #endif
5012 #endif /* HAVE_SYSTEM */
5013 
5014 
5015 #ifdef HAVE_UMASK
5016 /*[clinic input]
5017 os.umask
5018 
5019     mask: int
5020     /
5021 
5022 Set the current numeric umask and return the previous umask.
5023 [clinic start generated code]*/
5024 
5025 static PyObject *
os_umask_impl(PyObject *module, int mask)5026 os_umask_impl(PyObject *module, int mask)
5027 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
5028 {
5029     int i = (int)umask(mask);
5030     if (i < 0)
5031         return posix_error();
5032     return PyLong_FromLong((long)i);
5033 }
5034 #endif
5035 
5036 #ifdef MS_WINDOWS
5037 
5038 /* override the default DeleteFileW behavior so that directory
5039 symlinks can be removed with this function, the same as with
5040 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)5041 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5042 {
5043     WIN32_FILE_ATTRIBUTE_DATA info;
5044     WIN32_FIND_DATAW find_data;
5045     HANDLE find_data_handle;
5046     int is_directory = 0;
5047     int is_link = 0;
5048 
5049     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5050         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5051 
5052         /* Get WIN32_FIND_DATA structure for the path to determine if
5053            it is a symlink */
5054         if(is_directory &&
5055            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5056             find_data_handle = FindFirstFileW(lpFileName, &find_data);
5057 
5058             if(find_data_handle != INVALID_HANDLE_VALUE) {
5059                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5060                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5061                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5062                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5063                 FindClose(find_data_handle);
5064             }
5065         }
5066     }
5067 
5068     if (is_directory && is_link)
5069         return RemoveDirectoryW(lpFileName);
5070 
5071     return DeleteFileW(lpFileName);
5072 }
5073 #endif /* MS_WINDOWS */
5074 
5075 
5076 /*[clinic input]
5077 os.unlink
5078 
5079     path: path_t
5080     *
5081     dir_fd: dir_fd(requires='unlinkat')=None
5082 
5083 Remove a file (same as remove()).
5084 
5085 If dir_fd is not None, it should be a file descriptor open to a directory,
5086   and path should be relative; path will then be relative to that directory.
5087 dir_fd may not be implemented on your platform.
5088   If it is unavailable, using it will raise a NotImplementedError.
5089 
5090 [clinic start generated code]*/
5091 
5092 static PyObject *
os_unlink_impl(PyObject *module, path_t *path, int dir_fd)5093 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5094 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5095 {
5096     int result;
5097 #ifdef HAVE_UNLINKAT
5098     int unlinkat_unavailable = 0;
5099 #endif
5100 
5101     if (PySys_Audit("os.remove", "Oi", path->object,
5102                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5103         return NULL;
5104     }
5105 
5106     Py_BEGIN_ALLOW_THREADS
5107     _Py_BEGIN_SUPPRESS_IPH
5108 #ifdef MS_WINDOWS
5109     /* Windows, success=1, UNIX, success=0 */
5110     result = !Py_DeleteFileW(path->wide);
5111 #else
5112 #ifdef HAVE_UNLINKAT
5113     if (dir_fd != DEFAULT_DIR_FD) {
5114       if (HAVE_UNLINKAT_RUNTIME) {
5115 
5116         result = unlinkat(dir_fd, path->narrow, 0);
5117       } else {
5118         unlinkat_unavailable = 1;
5119       }
5120     } else
5121 #endif /* HAVE_UNLINKAT */
5122         result = unlink(path->narrow);
5123 #endif
5124     _Py_END_SUPPRESS_IPH
5125     Py_END_ALLOW_THREADS
5126 
5127 #ifdef HAVE_UNLINKAT
5128     if (unlinkat_unavailable) {
5129         argument_unavailable_error(NULL, "dir_fd");
5130         return NULL;
5131     }
5132 #endif
5133 
5134     if (result)
5135         return path_error(path);
5136 
5137     Py_RETURN_NONE;
5138 }
5139 
5140 
5141 /*[clinic input]
5142 os.remove = os.unlink
5143 
5144 Remove a file (same as unlink()).
5145 
5146 If dir_fd is not None, it should be a file descriptor open to a directory,
5147   and path should be relative; path will then be relative to that directory.
5148 dir_fd may not be implemented on your platform.
5149   If it is unavailable, using it will raise a NotImplementedError.
5150 [clinic start generated code]*/
5151 
5152 static PyObject *
os_remove_impl(PyObject *module, path_t *path, int dir_fd)5153 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5154 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5155 {
5156     return os_unlink_impl(module, path, dir_fd);
5157 }
5158 
5159 
5160 static PyStructSequence_Field uname_result_fields[] = {
5161     {"sysname",    "operating system name"},
5162     {"nodename",   "name of machine on network (implementation-defined)"},
5163     {"release",    "operating system release"},
5164     {"version",    "operating system version"},
5165     {"machine",    "hardware identifier"},
5166     {NULL}
5167 };
5168 
5169 PyDoc_STRVAR(uname_result__doc__,
5170 "uname_result: Result from os.uname().\n\n\
5171 This object may be accessed either as a tuple of\n\
5172   (sysname, nodename, release, version, machine),\n\
5173 or via the attributes sysname, nodename, release, version, and machine.\n\
5174 \n\
5175 See os.uname for more information.");
5176 
5177 static PyStructSequence_Desc uname_result_desc = {
5178     MODNAME ".uname_result", /* name */
5179     uname_result__doc__, /* doc */
5180     uname_result_fields,
5181     5
5182 };
5183 
5184 #ifdef HAVE_UNAME
5185 /*[clinic input]
5186 os.uname
5187 
5188 Return an object identifying the current operating system.
5189 
5190 The object behaves like a named tuple with the following fields:
5191   (sysname, nodename, release, version, machine)
5192 
5193 [clinic start generated code]*/
5194 
5195 static PyObject *
os_uname_impl(PyObject *module)5196 os_uname_impl(PyObject *module)
5197 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5198 {
5199     struct utsname u;
5200     int res;
5201     PyObject *value;
5202 
5203     Py_BEGIN_ALLOW_THREADS
5204     res = uname(&u);
5205     Py_END_ALLOW_THREADS
5206     if (res < 0)
5207         return posix_error();
5208 
5209     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5210     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5211     if (value == NULL)
5212         return NULL;
5213 
5214 #define SET(i, field) \
5215     { \
5216     PyObject *o = PyUnicode_DecodeFSDefault(field); \
5217     if (!o) { \
5218         Py_DECREF(value); \
5219         return NULL; \
5220     } \
5221     PyStructSequence_SET_ITEM(value, i, o); \
5222     } \
5223 
5224     SET(0, u.sysname);
5225     SET(1, u.nodename);
5226     SET(2, u.release);
5227     SET(3, u.version);
5228     SET(4, u.machine);
5229 
5230 #undef SET
5231 
5232     return value;
5233 }
5234 #endif /* HAVE_UNAME */
5235 
5236 
5237 
5238 typedef struct {
5239     int    now;
5240     time_t atime_s;
5241     long   atime_ns;
5242     time_t mtime_s;
5243     long   mtime_ns;
5244 } utime_t;
5245 
5246 /*
5247  * these macros assume that "ut" is a pointer to a utime_t
5248  * they also intentionally leak the declaration of a pointer named "time"
5249  */
5250 #define UTIME_TO_TIMESPEC \
5251     struct timespec ts[2]; \
5252     struct timespec *time; \
5253     if (ut->now) \
5254         time = NULL; \
5255     else { \
5256         ts[0].tv_sec = ut->atime_s; \
5257         ts[0].tv_nsec = ut->atime_ns; \
5258         ts[1].tv_sec = ut->mtime_s; \
5259         ts[1].tv_nsec = ut->mtime_ns; \
5260         time = ts; \
5261     } \
5262 
5263 #define UTIME_TO_TIMEVAL \
5264     struct timeval tv[2]; \
5265     struct timeval *time; \
5266     if (ut->now) \
5267         time = NULL; \
5268     else { \
5269         tv[0].tv_sec = ut->atime_s; \
5270         tv[0].tv_usec = ut->atime_ns / 1000; \
5271         tv[1].tv_sec = ut->mtime_s; \
5272         tv[1].tv_usec = ut->mtime_ns / 1000; \
5273         time = tv; \
5274     } \
5275 
5276 #define UTIME_TO_UTIMBUF \
5277     struct utimbuf u; \
5278     struct utimbuf *time; \
5279     if (ut->now) \
5280         time = NULL; \
5281     else { \
5282         u.actime = ut->atime_s; \
5283         u.modtime = ut->mtime_s; \
5284         time = &u; \
5285     }
5286 
5287 #define UTIME_TO_TIME_T \
5288     time_t timet[2]; \
5289     time_t *time; \
5290     if (ut->now) \
5291         time = NULL; \
5292     else { \
5293         timet[0] = ut->atime_s; \
5294         timet[1] = ut->mtime_s; \
5295         time = timet; \
5296     } \
5297 
5298 
5299 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5300 
5301 static int
utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)5302 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5303 {
5304 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5305     if (HAVE_UTIMENSAT_RUNTIME) {
5306         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5307         UTIME_TO_TIMESPEC;
5308         return utimensat(dir_fd, path, time, flags);
5309     }  else {
5310         errno = ENOSYS;
5311         return -1;
5312     }
5313 #elif defined(HAVE_UTIMENSAT)
5314     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5315     UTIME_TO_TIMESPEC;
5316     return utimensat(dir_fd, path, time, flags);
5317 #elif defined(HAVE_FUTIMESAT)
5318     UTIME_TO_TIMEVAL;
5319     /*
5320      * follow_symlinks will never be false here;
5321      * we only allow !follow_symlinks and dir_fd together
5322      * if we have utimensat()
5323      */
5324     assert(follow_symlinks);
5325     return futimesat(dir_fd, path, time);
5326 #endif
5327 }
5328 
5329     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5330 #else
5331     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5332 #endif
5333 
5334 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5335 
5336 static int
utime_fd(utime_t *ut, int fd)5337 utime_fd(utime_t *ut, int fd)
5338 {
5339 #ifdef HAVE_FUTIMENS
5340 
5341     if (HAVE_FUTIMENS_RUNTIME) {
5342 
5343     UTIME_TO_TIMESPEC;
5344     return futimens(fd, time);
5345 
5346     } else
5347 #ifndef HAVE_FUTIMES
5348     {
5349         /* Not sure if this can happen */
5350         PyErr_SetString(
5351             PyExc_RuntimeError,
5352             "neither futimens nor futimes are supported"
5353             " on this system");
5354         return -1;
5355     }
5356 #endif
5357 
5358 #endif
5359 #ifdef HAVE_FUTIMES
5360     {
5361     UTIME_TO_TIMEVAL;
5362     return futimes(fd, time);
5363     }
5364 #endif
5365 }
5366 
5367     #define PATH_UTIME_HAVE_FD 1
5368 #else
5369     #define PATH_UTIME_HAVE_FD 0
5370 #endif
5371 
5372 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5373 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5374 #endif
5375 
5376 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5377 
5378 static int
utime_nofollow_symlinks(utime_t *ut, const char *path)5379 utime_nofollow_symlinks(utime_t *ut, const char *path)
5380 {
5381 #ifdef HAVE_UTIMENSAT
5382     if (HAVE_UTIMENSAT_RUNTIME) {
5383         UTIME_TO_TIMESPEC;
5384         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5385     } else
5386 #ifndef HAVE_LUTIMES
5387     {
5388         /* Not sure if this can happen */
5389         PyErr_SetString(
5390             PyExc_RuntimeError,
5391             "neither utimensat nor lutimes are supported"
5392             " on this system");
5393         return -1;
5394     }
5395 #endif
5396 #endif
5397 
5398 #ifdef HAVE_LUTIMES
5399     {
5400     UTIME_TO_TIMEVAL;
5401     return lutimes(path, time);
5402     }
5403 #endif
5404 }
5405 
5406 #endif
5407 
5408 #ifndef MS_WINDOWS
5409 
5410 static int
utime_default(utime_t *ut, const char *path)5411 utime_default(utime_t *ut, const char *path)
5412 {
5413 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5414     if (HAVE_UTIMENSAT_RUNTIME) {
5415         UTIME_TO_TIMESPEC;
5416         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5417     } else {
5418         UTIME_TO_TIMEVAL;
5419         return utimes(path, time);
5420     }
5421 #elif defined(HAVE_UTIMENSAT)
5422     UTIME_TO_TIMESPEC;
5423     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5424 #elif defined(HAVE_UTIMES)
5425     UTIME_TO_TIMEVAL;
5426     return utimes(path, time);
5427 #elif defined(HAVE_UTIME_H)
5428     UTIME_TO_UTIMBUF;
5429     return utime(path, time);
5430 #else
5431     UTIME_TO_TIME_T;
5432     return utime(path, time);
5433 #endif
5434 }
5435 
5436 #endif
5437 
5438 static int
split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)5439 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5440 {
5441     int result = 0;
5442     PyObject *divmod;
5443     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5444     if (!divmod)
5445         goto exit;
5446     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5447         PyErr_Format(PyExc_TypeError,
5448                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5449                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5450         goto exit;
5451     }
5452     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5453     if ((*s == -1) && PyErr_Occurred())
5454         goto exit;
5455     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5456     if ((*ns == -1) && PyErr_Occurred())
5457         goto exit;
5458 
5459     result = 1;
5460 exit:
5461     Py_XDECREF(divmod);
5462     return result;
5463 }
5464 
5465 
5466 /*[clinic input]
5467 os.utime
5468 
5469     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5470     times: object = None
5471     *
5472     ns: object = NULL
5473     dir_fd: dir_fd(requires='futimensat') = None
5474     follow_symlinks: bool=True
5475 
5476 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5477 
5478 Set the access and modified time of path.
5479 
5480 path may always be specified as a string.
5481 On some platforms, path may also be specified as an open file descriptor.
5482   If this functionality is unavailable, using it raises an exception.
5483 
5484 If times is not None, it must be a tuple (atime, mtime);
5485     atime and mtime should be expressed as float seconds since the epoch.
5486 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5487     atime_ns and mtime_ns should be expressed as integer nanoseconds
5488     since the epoch.
5489 If times is None and ns is unspecified, utime uses the current time.
5490 Specifying tuples for both times and ns is an error.
5491 
5492 If dir_fd is not None, it should be a file descriptor open to a directory,
5493   and path should be relative; path will then be relative to that directory.
5494 If follow_symlinks is False, and the last element of the path is a symbolic
5495   link, utime will modify the symbolic link itself instead of the file the
5496   link points to.
5497 It is an error to use dir_fd or follow_symlinks when specifying path
5498   as an open file descriptor.
5499 dir_fd and follow_symlinks may not be available on your platform.
5500   If they are unavailable, using them will raise a NotImplementedError.
5501 
5502 [clinic start generated code]*/
5503 
5504 static PyObject *
os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks)5505 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5506               int dir_fd, int follow_symlinks)
5507 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5508 {
5509 #ifdef MS_WINDOWS
5510     HANDLE hFile;
5511     FILETIME atime, mtime;
5512 #else
5513     int result;
5514 #endif
5515 
5516     utime_t utime;
5517 
5518     memset(&utime, 0, sizeof(utime_t));
5519 
5520     if (times != Py_None && ns) {
5521         PyErr_SetString(PyExc_ValueError,
5522                      "utime: you may specify either 'times'"
5523                      " or 'ns' but not both");
5524         return NULL;
5525     }
5526 
5527     if (times != Py_None) {
5528         time_t a_sec, m_sec;
5529         long a_nsec, m_nsec;
5530         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5531             PyErr_SetString(PyExc_TypeError,
5532                          "utime: 'times' must be either"
5533                          " a tuple of two ints or None");
5534             return NULL;
5535         }
5536         utime.now = 0;
5537         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5538                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5539             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5540                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5541             return NULL;
5542         }
5543         utime.atime_s = a_sec;
5544         utime.atime_ns = a_nsec;
5545         utime.mtime_s = m_sec;
5546         utime.mtime_ns = m_nsec;
5547     }
5548     else if (ns) {
5549         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5550             PyErr_SetString(PyExc_TypeError,
5551                          "utime: 'ns' must be a tuple of two ints");
5552             return NULL;
5553         }
5554         utime.now = 0;
5555         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5556                                       &utime.atime_s, &utime.atime_ns) ||
5557             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5558                                        &utime.mtime_s, &utime.mtime_ns)) {
5559             return NULL;
5560         }
5561     }
5562     else {
5563         /* times and ns are both None/unspecified. use "now". */
5564         utime.now = 1;
5565     }
5566 
5567 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5568     if (follow_symlinks_specified("utime", follow_symlinks))
5569         return NULL;
5570 #endif
5571 
5572     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5573         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5574         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5575         return NULL;
5576 
5577 #if !defined(HAVE_UTIMENSAT)
5578     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5579         PyErr_SetString(PyExc_ValueError,
5580                      "utime: cannot use dir_fd and follow_symlinks "
5581                      "together on this platform");
5582         return NULL;
5583     }
5584 #endif
5585 
5586     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5587                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5588         return NULL;
5589     }
5590 
5591 #ifdef MS_WINDOWS
5592     Py_BEGIN_ALLOW_THREADS
5593     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5594                         NULL, OPEN_EXISTING,
5595                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5596     Py_END_ALLOW_THREADS
5597     if (hFile == INVALID_HANDLE_VALUE) {
5598         path_error(path);
5599         return NULL;
5600     }
5601 
5602     if (utime.now) {
5603         GetSystemTimeAsFileTime(&mtime);
5604         atime = mtime;
5605     }
5606     else {
5607         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5608         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5609     }
5610     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5611         /* Avoid putting the file name into the error here,
5612            as that may confuse the user into believing that
5613            something is wrong with the file, when it also
5614            could be the time stamp that gives a problem. */
5615         PyErr_SetFromWindowsErr(0);
5616         CloseHandle(hFile);
5617         return NULL;
5618     }
5619     CloseHandle(hFile);
5620 #else /* MS_WINDOWS */
5621     Py_BEGIN_ALLOW_THREADS
5622 
5623 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5624     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5625         result = utime_nofollow_symlinks(&utime, path->narrow);
5626     else
5627 #endif
5628 
5629 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5630     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5631         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5632 
5633     } else
5634 #endif
5635 
5636 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5637     if (path->fd != -1)
5638         result = utime_fd(&utime, path->fd);
5639     else
5640 #endif
5641 
5642     result = utime_default(&utime, path->narrow);
5643 
5644     Py_END_ALLOW_THREADS
5645 
5646 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5647     /* See utime_dir_fd implementation */
5648     if (result == -1 && errno == ENOSYS) {
5649         argument_unavailable_error(NULL, "dir_fd");
5650         return NULL;
5651     }
5652 #endif
5653 
5654     if (result < 0) {
5655         /* see previous comment about not putting filename in error here */
5656         posix_error();
5657         return NULL;
5658     }
5659 
5660 #endif /* MS_WINDOWS */
5661 
5662     Py_RETURN_NONE;
5663 }
5664 
5665 /* Process operations */
5666 
5667 
5668 /*[clinic input]
5669 os._exit
5670 
5671     status: int
5672 
5673 Exit to the system with specified status, without normal exit processing.
5674 [clinic start generated code]*/
5675 
5676 static PyObject *
os__exit_impl(PyObject *module, int status)5677 os__exit_impl(PyObject *module, int status)
5678 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5679 {
5680     _exit(status);
5681     return NULL; /* Make gcc -Wall happy */
5682 }
5683 
5684 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5685 #define EXECV_CHAR wchar_t
5686 #else
5687 #define EXECV_CHAR char
5688 #endif
5689 
5690 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5691 static void
free_string_array(EXECV_CHAR **array, Py_ssize_t count)5692 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5693 {
5694     Py_ssize_t i;
5695     for (i = 0; i < count; i++)
5696         PyMem_Free(array[i]);
5697     PyMem_Free(array);
5698 }
5699 
5700 static int
fsconvert_strdup(PyObject *o, EXECV_CHAR **out)5701 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5702 {
5703     Py_ssize_t size;
5704     PyObject *ub;
5705     int result = 0;
5706 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5707     if (!PyUnicode_FSDecoder(o, &ub))
5708         return 0;
5709     *out = PyUnicode_AsWideCharString(ub, &size);
5710     if (*out)
5711         result = 1;
5712 #else
5713     if (!PyUnicode_FSConverter(o, &ub))
5714         return 0;
5715     size = PyBytes_GET_SIZE(ub);
5716     *out = PyMem_Malloc(size + 1);
5717     if (*out) {
5718         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5719         result = 1;
5720     } else
5721         PyErr_NoMemory();
5722 #endif
5723     Py_DECREF(ub);
5724     return result;
5725 }
5726 #endif
5727 
5728 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5729 static EXECV_CHAR**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)5730 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5731 {
5732     Py_ssize_t i, pos, envc;
5733     PyObject *keys=NULL, *vals=NULL;
5734     PyObject *key, *val, *key2, *val2, *keyval;
5735     EXECV_CHAR **envlist;
5736 
5737     i = PyMapping_Size(env);
5738     if (i < 0)
5739         return NULL;
5740     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5741     if (envlist == NULL) {
5742         PyErr_NoMemory();
5743         return NULL;
5744     }
5745     envc = 0;
5746     keys = PyMapping_Keys(env);
5747     if (!keys)
5748         goto error;
5749     vals = PyMapping_Values(env);
5750     if (!vals)
5751         goto error;
5752     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5753         PyErr_Format(PyExc_TypeError,
5754                      "env.keys() or env.values() is not a list");
5755         goto error;
5756     }
5757 
5758     for (pos = 0; pos < i; pos++) {
5759         key = PyList_GetItem(keys, pos);
5760         val = PyList_GetItem(vals, pos);
5761         if (!key || !val)
5762             goto error;
5763 
5764 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5765         if (!PyUnicode_FSDecoder(key, &key2))
5766             goto error;
5767         if (!PyUnicode_FSDecoder(val, &val2)) {
5768             Py_DECREF(key2);
5769             goto error;
5770         }
5771         /* Search from index 1 because on Windows starting '=' is allowed for
5772            defining hidden environment variables. */
5773         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5774             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5775         {
5776             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5777             Py_DECREF(key2);
5778             Py_DECREF(val2);
5779             goto error;
5780         }
5781         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5782 #else
5783         if (!PyUnicode_FSConverter(key, &key2))
5784             goto error;
5785         if (!PyUnicode_FSConverter(val, &val2)) {
5786             Py_DECREF(key2);
5787             goto error;
5788         }
5789         if (PyBytes_GET_SIZE(key2) == 0 ||
5790             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5791         {
5792             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5793             Py_DECREF(key2);
5794             Py_DECREF(val2);
5795             goto error;
5796         }
5797         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5798                                              PyBytes_AS_STRING(val2));
5799 #endif
5800         Py_DECREF(key2);
5801         Py_DECREF(val2);
5802         if (!keyval)
5803             goto error;
5804 
5805         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5806             Py_DECREF(keyval);
5807             goto error;
5808         }
5809 
5810         Py_DECREF(keyval);
5811     }
5812     Py_DECREF(vals);
5813     Py_DECREF(keys);
5814 
5815     envlist[envc] = 0;
5816     *envc_ptr = envc;
5817     return envlist;
5818 
5819 error:
5820     Py_XDECREF(keys);
5821     Py_XDECREF(vals);
5822     free_string_array(envlist, envc);
5823     return NULL;
5824 }
5825 
5826 static EXECV_CHAR**
parse_arglist(PyObject* argv, Py_ssize_t *argc)5827 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5828 {
5829     int i;
5830     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5831     if (argvlist == NULL) {
5832         PyErr_NoMemory();
5833         return NULL;
5834     }
5835     for (i = 0; i < *argc; i++) {
5836         PyObject* item = PySequence_ITEM(argv, i);
5837         if (item == NULL)
5838             goto fail;
5839         if (!fsconvert_strdup(item, &argvlist[i])) {
5840             Py_DECREF(item);
5841             goto fail;
5842         }
5843         Py_DECREF(item);
5844     }
5845     argvlist[*argc] = NULL;
5846     return argvlist;
5847 fail:
5848     *argc = i;
5849     free_string_array(argvlist, *argc);
5850     return NULL;
5851 }
5852 
5853 #endif
5854 
5855 
5856 #ifdef HAVE_EXECV
5857 /*[clinic input]
5858 os.execv
5859 
5860     path: path_t
5861         Path of executable file.
5862     argv: object
5863         Tuple or list of strings.
5864     /
5865 
5866 Execute an executable path with arguments, replacing current process.
5867 [clinic start generated code]*/
5868 
5869 static PyObject *
os_execv_impl(PyObject *module, path_t *path, PyObject *argv)5870 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5871 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5872 {
5873     EXECV_CHAR **argvlist;
5874     Py_ssize_t argc;
5875 
5876     /* execv has two arguments: (path, argv), where
5877        argv is a list or tuple of strings. */
5878 
5879     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5880         PyErr_SetString(PyExc_TypeError,
5881                         "execv() arg 2 must be a tuple or list");
5882         return NULL;
5883     }
5884     argc = PySequence_Size(argv);
5885     if (argc < 1) {
5886         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5887         return NULL;
5888     }
5889 
5890     argvlist = parse_arglist(argv, &argc);
5891     if (argvlist == NULL) {
5892         return NULL;
5893     }
5894     if (!argvlist[0][0]) {
5895         PyErr_SetString(PyExc_ValueError,
5896             "execv() arg 2 first element cannot be empty");
5897         free_string_array(argvlist, argc);
5898         return NULL;
5899     }
5900 
5901     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5902         free_string_array(argvlist, argc);
5903         return NULL;
5904     }
5905 
5906     _Py_BEGIN_SUPPRESS_IPH
5907 #ifdef HAVE_WEXECV
5908     _wexecv(path->wide, argvlist);
5909 #else
5910     execv(path->narrow, argvlist);
5911 #endif
5912     _Py_END_SUPPRESS_IPH
5913 
5914     /* If we get here it's definitely an error */
5915 
5916     free_string_array(argvlist, argc);
5917     return posix_error();
5918 }
5919 
5920 
5921 /*[clinic input]
5922 os.execve
5923 
5924     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5925         Path of executable file.
5926     argv: object
5927         Tuple or list of strings.
5928     env: object
5929         Dictionary of strings mapping to strings.
5930 
5931 Execute an executable path with arguments, replacing current process.
5932 [clinic start generated code]*/
5933 
5934 static PyObject *
os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)5935 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5936 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5937 {
5938     EXECV_CHAR **argvlist = NULL;
5939     EXECV_CHAR **envlist;
5940     Py_ssize_t argc, envc;
5941 
5942     /* execve has three arguments: (path, argv, env), where
5943        argv is a list or tuple of strings and env is a dictionary
5944        like posix.environ. */
5945 
5946     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5947         PyErr_SetString(PyExc_TypeError,
5948                         "execve: argv must be a tuple or list");
5949         goto fail_0;
5950     }
5951     argc = PySequence_Size(argv);
5952     if (argc < 1) {
5953         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5954         return NULL;
5955     }
5956 
5957     if (!PyMapping_Check(env)) {
5958         PyErr_SetString(PyExc_TypeError,
5959                         "execve: environment must be a mapping object");
5960         goto fail_0;
5961     }
5962 
5963     argvlist = parse_arglist(argv, &argc);
5964     if (argvlist == NULL) {
5965         goto fail_0;
5966     }
5967     if (!argvlist[0][0]) {
5968         PyErr_SetString(PyExc_ValueError,
5969             "execve: argv first element cannot be empty");
5970         goto fail_0;
5971     }
5972 
5973     envlist = parse_envlist(env, &envc);
5974     if (envlist == NULL)
5975         goto fail_0;
5976 
5977     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5978         goto fail_1;
5979     }
5980 
5981     _Py_BEGIN_SUPPRESS_IPH
5982 #ifdef HAVE_FEXECVE
5983     if (path->fd > -1)
5984         fexecve(path->fd, argvlist, envlist);
5985     else
5986 #endif
5987 #ifdef HAVE_WEXECV
5988         _wexecve(path->wide, argvlist, envlist);
5989 #else
5990         execve(path->narrow, argvlist, envlist);
5991 #endif
5992     _Py_END_SUPPRESS_IPH
5993 
5994     /* If we get here it's definitely an error */
5995 
5996     posix_path_error(path);
5997   fail_1:
5998     free_string_array(envlist, envc);
5999   fail_0:
6000     if (argvlist)
6001         free_string_array(argvlist, argc);
6002     return NULL;
6003 }
6004 
6005 #endif /* HAVE_EXECV */
6006 
6007 #ifdef HAVE_POSIX_SPAWN
6008 
6009 enum posix_spawn_file_actions_identifier {
6010     POSIX_SPAWN_OPEN,
6011     POSIX_SPAWN_CLOSE,
6012     POSIX_SPAWN_DUP2
6013 };
6014 
6015 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6016 static int
6017 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
6018 #endif
6019 
6020 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)6021 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
6022                         int resetids, int setsid, PyObject *setsigmask,
6023                         PyObject *setsigdef, PyObject *scheduler,
6024                         posix_spawnattr_t *attrp)
6025 {
6026     long all_flags = 0;
6027 
6028     errno = posix_spawnattr_init(attrp);
6029     if (errno) {
6030         posix_error();
6031         return -1;
6032     }
6033 
6034     if (setpgroup) {
6035         pid_t pgid = PyLong_AsPid(setpgroup);
6036         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
6037             goto fail;
6038         }
6039         errno = posix_spawnattr_setpgroup(attrp, pgid);
6040         if (errno) {
6041             posix_error();
6042             goto fail;
6043         }
6044         all_flags |= POSIX_SPAWN_SETPGROUP;
6045     }
6046 
6047     if (resetids) {
6048         all_flags |= POSIX_SPAWN_RESETIDS;
6049     }
6050 
6051     if (setsid) {
6052 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6053         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6054 #endif
6055 #ifdef POSIX_SPAWN_SETSID
6056         all_flags |= POSIX_SPAWN_SETSID;
6057 #elif defined(POSIX_SPAWN_SETSID_NP)
6058         all_flags |= POSIX_SPAWN_SETSID_NP;
6059 #else
6060         argument_unavailable_error(func_name, "setsid");
6061         return -1;
6062 #endif
6063 
6064 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6065         } else {
6066             argument_unavailable_error(func_name, "setsid");
6067             return -1;
6068         }
6069 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6070 
6071     }
6072 
6073 #ifdef HAVE_SIGSET_T
6074    if (setsigmask) {
6075         sigset_t set;
6076         if (!_Py_Sigset_Converter(setsigmask, &set)) {
6077             goto fail;
6078         }
6079         errno = posix_spawnattr_setsigmask(attrp, &set);
6080         if (errno) {
6081             posix_error();
6082             goto fail;
6083         }
6084         all_flags |= POSIX_SPAWN_SETSIGMASK;
6085     }
6086 
6087     if (setsigdef) {
6088         sigset_t set;
6089         if (!_Py_Sigset_Converter(setsigdef, &set)) {
6090             goto fail;
6091         }
6092         errno = posix_spawnattr_setsigdefault(attrp, &set);
6093         if (errno) {
6094             posix_error();
6095             goto fail;
6096         }
6097         all_flags |= POSIX_SPAWN_SETSIGDEF;
6098     }
6099 #else
6100     if (setsigmask || setsigdef) {
6101         PyErr_SetString(PyExc_NotImplementedError,
6102                         "sigset is not supported on this platform");
6103         goto fail;
6104     }
6105 #endif
6106 
6107     if (scheduler) {
6108 #ifdef POSIX_SPAWN_SETSCHEDULER
6109         PyObject *py_schedpolicy;
6110         PyObject *schedparam_obj;
6111         struct sched_param schedparam;
6112 
6113         if (!PyArg_ParseTuple(scheduler, "OO"
6114                         ";A scheduler tuple must have two elements",
6115                         &py_schedpolicy, &schedparam_obj)) {
6116             goto fail;
6117         }
6118         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6119             goto fail;
6120         }
6121         if (py_schedpolicy != Py_None) {
6122             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6123 
6124             if (schedpolicy == -1 && PyErr_Occurred()) {
6125                 goto fail;
6126             }
6127             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6128             if (errno) {
6129                 posix_error();
6130                 goto fail;
6131             }
6132             all_flags |= POSIX_SPAWN_SETSCHEDULER;
6133         }
6134         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6135         if (errno) {
6136             posix_error();
6137             goto fail;
6138         }
6139         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6140 #else
6141         PyErr_SetString(PyExc_NotImplementedError,
6142                 "The scheduler option is not supported in this system.");
6143         goto fail;
6144 #endif
6145     }
6146 
6147     errno = posix_spawnattr_setflags(attrp, all_flags);
6148     if (errno) {
6149         posix_error();
6150         goto fail;
6151     }
6152 
6153     return 0;
6154 
6155 fail:
6156     (void)posix_spawnattr_destroy(attrp);
6157     return -1;
6158 }
6159 
6160 static int
parse_file_actions(PyObject *file_actions, posix_spawn_file_actions_t *file_actionsp, PyObject *temp_buffer)6161 parse_file_actions(PyObject *file_actions,
6162                    posix_spawn_file_actions_t *file_actionsp,
6163                    PyObject *temp_buffer)
6164 {
6165     PyObject *seq;
6166     PyObject *file_action = NULL;
6167     PyObject *tag_obj;
6168 
6169     seq = PySequence_Fast(file_actions,
6170                           "file_actions must be a sequence or None");
6171     if (seq == NULL) {
6172         return -1;
6173     }
6174 
6175     errno = posix_spawn_file_actions_init(file_actionsp);
6176     if (errno) {
6177         posix_error();
6178         Py_DECREF(seq);
6179         return -1;
6180     }
6181 
6182     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6183         file_action = PySequence_Fast_GET_ITEM(seq, i);
6184         Py_INCREF(file_action);
6185         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6186             PyErr_SetString(PyExc_TypeError,
6187                 "Each file_actions element must be a non-empty tuple");
6188             goto fail;
6189         }
6190         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6191         if (tag == -1 && PyErr_Occurred()) {
6192             goto fail;
6193         }
6194 
6195         /* Populate the file_actions object */
6196         switch (tag) {
6197             case POSIX_SPAWN_OPEN: {
6198                 int fd, oflag;
6199                 PyObject *path;
6200                 unsigned long mode;
6201                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6202                         ";A open file_action tuple must have 5 elements",
6203                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
6204                         &oflag, &mode))
6205                 {
6206                     goto fail;
6207                 }
6208                 if (PyList_Append(temp_buffer, path)) {
6209                     Py_DECREF(path);
6210                     goto fail;
6211                 }
6212                 errno = posix_spawn_file_actions_addopen(file_actionsp,
6213                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6214                 Py_DECREF(path);
6215                 if (errno) {
6216                     posix_error();
6217                     goto fail;
6218                 }
6219                 break;
6220             }
6221             case POSIX_SPAWN_CLOSE: {
6222                 int fd;
6223                 if (!PyArg_ParseTuple(file_action, "Oi"
6224                         ";A close file_action tuple must have 2 elements",
6225                         &tag_obj, &fd))
6226                 {
6227                     goto fail;
6228                 }
6229                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6230                 if (errno) {
6231                     posix_error();
6232                     goto fail;
6233                 }
6234                 break;
6235             }
6236             case POSIX_SPAWN_DUP2: {
6237                 int fd1, fd2;
6238                 if (!PyArg_ParseTuple(file_action, "Oii"
6239                         ";A dup2 file_action tuple must have 3 elements",
6240                         &tag_obj, &fd1, &fd2))
6241                 {
6242                     goto fail;
6243                 }
6244                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6245                                                          fd1, fd2);
6246                 if (errno) {
6247                     posix_error();
6248                     goto fail;
6249                 }
6250                 break;
6251             }
6252             default: {
6253                 PyErr_SetString(PyExc_TypeError,
6254                                 "Unknown file_actions identifier");
6255                 goto fail;
6256             }
6257         }
6258         Py_DECREF(file_action);
6259     }
6260 
6261     Py_DECREF(seq);
6262     return 0;
6263 
6264 fail:
6265     Py_DECREF(seq);
6266     Py_DECREF(file_action);
6267     (void)posix_spawn_file_actions_destroy(file_actionsp);
6268     return -1;
6269 }
6270 
6271 
6272 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)6273 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6274                PyObject *env, PyObject *file_actions,
6275                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6276                PyObject *setsigdef, PyObject *scheduler)
6277 {
6278     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6279     EXECV_CHAR **argvlist = NULL;
6280     EXECV_CHAR **envlist = NULL;
6281     posix_spawn_file_actions_t file_actions_buf;
6282     posix_spawn_file_actions_t *file_actionsp = NULL;
6283     posix_spawnattr_t attr;
6284     posix_spawnattr_t *attrp = NULL;
6285     Py_ssize_t argc, envc;
6286     PyObject *result = NULL;
6287     PyObject *temp_buffer = NULL;
6288     pid_t pid;
6289     int err_code;
6290 
6291     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6292        argv is a list or tuple of strings and env is a dictionary
6293        like posix.environ. */
6294 
6295     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6296         PyErr_Format(PyExc_TypeError,
6297                      "%s: argv must be a tuple or list", func_name);
6298         goto exit;
6299     }
6300     argc = PySequence_Size(argv);
6301     if (argc < 1) {
6302         PyErr_Format(PyExc_ValueError,
6303                      "%s: argv must not be empty", func_name);
6304         return NULL;
6305     }
6306 
6307     if (!PyMapping_Check(env)) {
6308         PyErr_Format(PyExc_TypeError,
6309                      "%s: environment must be a mapping object", func_name);
6310         goto exit;
6311     }
6312 
6313     argvlist = parse_arglist(argv, &argc);
6314     if (argvlist == NULL) {
6315         goto exit;
6316     }
6317     if (!argvlist[0][0]) {
6318         PyErr_Format(PyExc_ValueError,
6319                      "%s: argv first element cannot be empty", func_name);
6320         goto exit;
6321     }
6322 
6323     envlist = parse_envlist(env, &envc);
6324     if (envlist == NULL) {
6325         goto exit;
6326     }
6327 
6328     if (file_actions != NULL && file_actions != Py_None) {
6329         /* There is a bug in old versions of glibc that makes some of the
6330          * helper functions for manipulating file actions not copy the provided
6331          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6332          * copy the value of path for some old versions of glibc (<2.20).
6333          * The use of temp_buffer here is a workaround that keeps the
6334          * python objects that own the buffers alive until posix_spawn gets called.
6335          * Check https://bugs.python.org/issue33630 and
6336          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6337         temp_buffer = PyList_New(0);
6338         if (!temp_buffer) {
6339             goto exit;
6340         }
6341         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6342             goto exit;
6343         }
6344         file_actionsp = &file_actions_buf;
6345     }
6346 
6347     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6348                                 setsigmask, setsigdef, scheduler, &attr)) {
6349         goto exit;
6350     }
6351     attrp = &attr;
6352 
6353     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6354         goto exit;
6355     }
6356 
6357     _Py_BEGIN_SUPPRESS_IPH
6358 #ifdef HAVE_POSIX_SPAWNP
6359     if (use_posix_spawnp) {
6360         err_code = posix_spawnp(&pid, path->narrow,
6361                                 file_actionsp, attrp, argvlist, envlist);
6362     }
6363     else
6364 #endif /* HAVE_POSIX_SPAWNP */
6365     {
6366         err_code = posix_spawn(&pid, path->narrow,
6367                                file_actionsp, attrp, argvlist, envlist);
6368     }
6369     _Py_END_SUPPRESS_IPH
6370 
6371     if (err_code) {
6372         errno = err_code;
6373         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6374         goto exit;
6375     }
6376 #ifdef _Py_MEMORY_SANITIZER
6377     __msan_unpoison(&pid, sizeof(pid));
6378 #endif
6379     result = PyLong_FromPid(pid);
6380 
6381 exit:
6382     if (file_actionsp) {
6383         (void)posix_spawn_file_actions_destroy(file_actionsp);
6384     }
6385     if (attrp) {
6386         (void)posix_spawnattr_destroy(attrp);
6387     }
6388     if (envlist) {
6389         free_string_array(envlist, envc);
6390     }
6391     if (argvlist) {
6392         free_string_array(argvlist, argc);
6393     }
6394     Py_XDECREF(temp_buffer);
6395     return result;
6396 }
6397 
6398 
6399 /*[clinic input]
6400 
6401 os.posix_spawn
6402     path: path_t
6403         Path of executable file.
6404     argv: object
6405         Tuple or list of strings.
6406     env: object
6407         Dictionary of strings mapping to strings.
6408     /
6409     *
6410     file_actions: object(c_default='NULL') = ()
6411         A sequence of file action tuples.
6412     setpgroup: object = NULL
6413         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6414     resetids: bool(accept={int}) = False
6415         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6416     setsid: bool(accept={int}) = False
6417         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6418     setsigmask: object(c_default='NULL') = ()
6419         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6420     setsigdef: object(c_default='NULL') = ()
6421         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6422     scheduler: object = NULL
6423         A tuple with the scheduler policy (optional) and parameters.
6424 
6425 Execute the program specified by path in a new process.
6426 [clinic start generated code]*/
6427 
6428 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)6429 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6430                     PyObject *env, PyObject *file_actions,
6431                     PyObject *setpgroup, int resetids, int setsid,
6432                     PyObject *setsigmask, PyObject *setsigdef,
6433                     PyObject *scheduler)
6434 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6435 {
6436     return py_posix_spawn(0, module, path, argv, env, file_actions,
6437                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6438                           scheduler);
6439 }
6440  #endif /* HAVE_POSIX_SPAWN */
6441 
6442 
6443 
6444 #ifdef HAVE_POSIX_SPAWNP
6445 /*[clinic input]
6446 
6447 os.posix_spawnp
6448     path: path_t
6449         Path of executable file.
6450     argv: object
6451         Tuple or list of strings.
6452     env: object
6453         Dictionary of strings mapping to strings.
6454     /
6455     *
6456     file_actions: object(c_default='NULL') = ()
6457         A sequence of file action tuples.
6458     setpgroup: object = NULL
6459         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6460     resetids: bool(accept={int}) = False
6461         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6462     setsid: bool(accept={int}) = False
6463         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6464     setsigmask: object(c_default='NULL') = ()
6465         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6466     setsigdef: object(c_default='NULL') = ()
6467         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6468     scheduler: object = NULL
6469         A tuple with the scheduler policy (optional) and parameters.
6470 
6471 Execute the program specified by path in a new process.
6472 [clinic start generated code]*/
6473 
6474 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)6475 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6476                      PyObject *env, PyObject *file_actions,
6477                      PyObject *setpgroup, int resetids, int setsid,
6478                      PyObject *setsigmask, PyObject *setsigdef,
6479                      PyObject *scheduler)
6480 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6481 {
6482     return py_posix_spawn(1, module, path, argv, env, file_actions,
6483                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6484                           scheduler);
6485 }
6486 #endif /* HAVE_POSIX_SPAWNP */
6487 
6488 #ifdef HAVE_RTPSPAWN
6489 static intptr_t
_rtp_spawn(int mode, const char *rtpFileName, const char *argv[], const char *envp[])6490 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6491                const char  *envp[])
6492 {
6493      RTP_ID rtpid;
6494      int status;
6495      pid_t res;
6496      int async_err = 0;
6497 
6498      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6499         uStackSize=0 cannot be used, the default stack size is too small for
6500         Python. */
6501      if (envp) {
6502          rtpid = rtpSpawn(rtpFileName, argv, envp,
6503                           100, 0x1000000, 0, VX_FP_TASK);
6504      }
6505      else {
6506          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6507                           100, 0x1000000, 0, VX_FP_TASK);
6508      }
6509      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6510          do {
6511              res = waitpid((pid_t)rtpid, &status, 0);
6512          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6513 
6514          if (res < 0)
6515              return RTP_ID_ERROR;
6516          return ((intptr_t)status);
6517      }
6518      return ((intptr_t)rtpid);
6519 }
6520 #endif
6521 
6522 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6523 /*[clinic input]
6524 os.spawnv
6525 
6526     mode: int
6527         Mode of process creation.
6528     path: path_t
6529         Path of executable file.
6530     argv: object
6531         Tuple or list of strings.
6532     /
6533 
6534 Execute the program specified by path in a new process.
6535 [clinic start generated code]*/
6536 
6537 static PyObject *
os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)6538 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6539 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6540 {
6541     EXECV_CHAR **argvlist;
6542     int i;
6543     Py_ssize_t argc;
6544     intptr_t spawnval;
6545     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6546 
6547     /* spawnv has three arguments: (mode, path, argv), where
6548        argv is a list or tuple of strings. */
6549 
6550     if (PyList_Check(argv)) {
6551         argc = PyList_Size(argv);
6552         getitem = PyList_GetItem;
6553     }
6554     else if (PyTuple_Check(argv)) {
6555         argc = PyTuple_Size(argv);
6556         getitem = PyTuple_GetItem;
6557     }
6558     else {
6559         PyErr_SetString(PyExc_TypeError,
6560                         "spawnv() arg 2 must be a tuple or list");
6561         return NULL;
6562     }
6563     if (argc == 0) {
6564         PyErr_SetString(PyExc_ValueError,
6565             "spawnv() arg 2 cannot be empty");
6566         return NULL;
6567     }
6568 
6569     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6570     if (argvlist == NULL) {
6571         return PyErr_NoMemory();
6572     }
6573     for (i = 0; i < argc; i++) {
6574         if (!fsconvert_strdup((*getitem)(argv, i),
6575                               &argvlist[i])) {
6576             free_string_array(argvlist, i);
6577             PyErr_SetString(
6578                 PyExc_TypeError,
6579                 "spawnv() arg 2 must contain only strings");
6580             return NULL;
6581         }
6582         if (i == 0 && !argvlist[0][0]) {
6583             free_string_array(argvlist, i + 1);
6584             PyErr_SetString(
6585                 PyExc_ValueError,
6586                 "spawnv() arg 2 first element cannot be empty");
6587             return NULL;
6588         }
6589     }
6590     argvlist[argc] = NULL;
6591 
6592 #if !defined(HAVE_RTPSPAWN)
6593     if (mode == _OLD_P_OVERLAY)
6594         mode = _P_OVERLAY;
6595 #endif
6596 
6597     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6598                     Py_None) < 0) {
6599         free_string_array(argvlist, argc);
6600         return NULL;
6601     }
6602 
6603     Py_BEGIN_ALLOW_THREADS
6604     _Py_BEGIN_SUPPRESS_IPH
6605 #ifdef HAVE_WSPAWNV
6606     spawnval = _wspawnv(mode, path->wide, argvlist);
6607 #elif defined(HAVE_RTPSPAWN)
6608     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6609 #else
6610     spawnval = _spawnv(mode, path->narrow, argvlist);
6611 #endif
6612     _Py_END_SUPPRESS_IPH
6613     Py_END_ALLOW_THREADS
6614 
6615     free_string_array(argvlist, argc);
6616 
6617     if (spawnval == -1)
6618         return posix_error();
6619     else
6620         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6621 }
6622 
6623 /*[clinic input]
6624 os.spawnve
6625 
6626     mode: int
6627         Mode of process creation.
6628     path: path_t
6629         Path of executable file.
6630     argv: object
6631         Tuple or list of strings.
6632     env: object
6633         Dictionary of strings mapping to strings.
6634     /
6635 
6636 Execute the program specified by path in a new process.
6637 [clinic start generated code]*/
6638 
6639 static PyObject *
os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, PyObject *env)6640 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6641                 PyObject *env)
6642 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6643 {
6644     EXECV_CHAR **argvlist;
6645     EXECV_CHAR **envlist;
6646     PyObject *res = NULL;
6647     Py_ssize_t argc, i, envc;
6648     intptr_t spawnval;
6649     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6650     Py_ssize_t lastarg = 0;
6651 
6652     /* spawnve has four arguments: (mode, path, argv, env), where
6653        argv is a list or tuple of strings and env is a dictionary
6654        like posix.environ. */
6655 
6656     if (PyList_Check(argv)) {
6657         argc = PyList_Size(argv);
6658         getitem = PyList_GetItem;
6659     }
6660     else if (PyTuple_Check(argv)) {
6661         argc = PyTuple_Size(argv);
6662         getitem = PyTuple_GetItem;
6663     }
6664     else {
6665         PyErr_SetString(PyExc_TypeError,
6666                         "spawnve() arg 2 must be a tuple or list");
6667         goto fail_0;
6668     }
6669     if (argc == 0) {
6670         PyErr_SetString(PyExc_ValueError,
6671             "spawnve() arg 2 cannot be empty");
6672         goto fail_0;
6673     }
6674     if (!PyMapping_Check(env)) {
6675         PyErr_SetString(PyExc_TypeError,
6676                         "spawnve() arg 3 must be a mapping object");
6677         goto fail_0;
6678     }
6679 
6680     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6681     if (argvlist == NULL) {
6682         PyErr_NoMemory();
6683         goto fail_0;
6684     }
6685     for (i = 0; i < argc; i++) {
6686         if (!fsconvert_strdup((*getitem)(argv, i),
6687                               &argvlist[i]))
6688         {
6689             lastarg = i;
6690             goto fail_1;
6691         }
6692         if (i == 0 && !argvlist[0][0]) {
6693             lastarg = i + 1;
6694             PyErr_SetString(
6695                 PyExc_ValueError,
6696                 "spawnv() arg 2 first element cannot be empty");
6697             goto fail_1;
6698         }
6699     }
6700     lastarg = argc;
6701     argvlist[argc] = NULL;
6702 
6703     envlist = parse_envlist(env, &envc);
6704     if (envlist == NULL)
6705         goto fail_1;
6706 
6707 #if !defined(HAVE_RTPSPAWN)
6708     if (mode == _OLD_P_OVERLAY)
6709         mode = _P_OVERLAY;
6710 #endif
6711 
6712     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6713         goto fail_2;
6714     }
6715 
6716     Py_BEGIN_ALLOW_THREADS
6717     _Py_BEGIN_SUPPRESS_IPH
6718 #ifdef HAVE_WSPAWNV
6719     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6720 #elif defined(HAVE_RTPSPAWN)
6721     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6722                            (const char **)envlist);
6723 #else
6724     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6725 #endif
6726     _Py_END_SUPPRESS_IPH
6727     Py_END_ALLOW_THREADS
6728 
6729     if (spawnval == -1)
6730         (void) posix_error();
6731     else
6732         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6733 
6734   fail_2:
6735     while (--envc >= 0) {
6736         PyMem_Free(envlist[envc]);
6737     }
6738     PyMem_Free(envlist);
6739   fail_1:
6740     free_string_array(argvlist, lastarg);
6741   fail_0:
6742     return res;
6743 }
6744 
6745 #endif /* HAVE_SPAWNV */
6746 
6747 #ifdef HAVE_FORK
6748 
6749 /* Helper function to validate arguments.
6750    Returns 0 on success.  non-zero on failure with a TypeError raised.
6751    If obj is non-NULL it must be callable.  */
6752 static int
check_null_or_callable(PyObject *obj, const char* obj_name)6753 check_null_or_callable(PyObject *obj, const char* obj_name)
6754 {
6755     if (obj && !PyCallable_Check(obj)) {
6756         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6757                      obj_name, _PyType_Name(Py_TYPE(obj)));
6758         return -1;
6759     }
6760     return 0;
6761 }
6762 
6763 /*[clinic input]
6764 os.register_at_fork
6765 
6766     *
6767     before: object=NULL
6768         A callable to be called in the parent before the fork() syscall.
6769     after_in_child: object=NULL
6770         A callable to be called in the child after fork().
6771     after_in_parent: object=NULL
6772         A callable to be called in the parent after fork().
6773 
6774 Register callables to be called when forking a new process.
6775 
6776 'before' callbacks are called in reverse order.
6777 'after_in_child' and 'after_in_parent' callbacks are called in order.
6778 
6779 [clinic start generated code]*/
6780 
6781 static PyObject *
os_register_at_fork_impl(PyObject *module, PyObject *before, PyObject *after_in_child, PyObject *after_in_parent)6782 os_register_at_fork_impl(PyObject *module, PyObject *before,
6783                          PyObject *after_in_child, PyObject *after_in_parent)
6784 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6785 {
6786     PyInterpreterState *interp;
6787 
6788     if (!before && !after_in_child && !after_in_parent) {
6789         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6790         return NULL;
6791     }
6792     if (check_null_or_callable(before, "before") ||
6793         check_null_or_callable(after_in_child, "after_in_child") ||
6794         check_null_or_callable(after_in_parent, "after_in_parent")) {
6795         return NULL;
6796     }
6797     interp = _PyInterpreterState_GET();
6798 
6799     if (register_at_forker(&interp->before_forkers, before)) {
6800         return NULL;
6801     }
6802     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6803         return NULL;
6804     }
6805     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6806         return NULL;
6807     }
6808     Py_RETURN_NONE;
6809 }
6810 #endif /* HAVE_FORK */
6811 
6812 
6813 #ifdef HAVE_FORK1
6814 /*[clinic input]
6815 os.fork1
6816 
6817 Fork a child process with a single multiplexed (i.e., not bound) thread.
6818 
6819 Return 0 to child process and PID of child to parent process.
6820 [clinic start generated code]*/
6821 
6822 static PyObject *
os_fork1_impl(PyObject *module)6823 os_fork1_impl(PyObject *module)
6824 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6825 {
6826     pid_t pid;
6827 
6828     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6829         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6830         return NULL;
6831     }
6832     PyOS_BeforeFork();
6833     pid = fork1();
6834     if (pid == 0) {
6835         /* child: this clobbers and resets the import lock. */
6836         PyOS_AfterFork_Child();
6837     } else {
6838         /* parent: release the import lock. */
6839         PyOS_AfterFork_Parent();
6840     }
6841     if (pid == -1)
6842         return posix_error();
6843     return PyLong_FromPid(pid);
6844 }
6845 #endif /* HAVE_FORK1 */
6846 
6847 
6848 #ifdef HAVE_FORK
6849 /*[clinic input]
6850 os.fork
6851 
6852 Fork a child process.
6853 
6854 Return 0 to child process and PID of child to parent process.
6855 [clinic start generated code]*/
6856 
6857 static PyObject *
os_fork_impl(PyObject *module)6858 os_fork_impl(PyObject *module)
6859 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6860 {
6861     pid_t pid;
6862     PyInterpreterState *interp = _PyInterpreterState_GET();
6863     if (interp->config._isolated_interpreter) {
6864         PyErr_SetString(PyExc_RuntimeError,
6865                         "fork not supported for isolated subinterpreters");
6866         return NULL;
6867     }
6868     if (PySys_Audit("os.fork", NULL) < 0) {
6869         return NULL;
6870     }
6871     PyOS_BeforeFork();
6872     pid = fork();
6873     if (pid == 0) {
6874         /* child: this clobbers and resets the import lock. */
6875         PyOS_AfterFork_Child();
6876     } else {
6877         /* parent: release the import lock. */
6878         PyOS_AfterFork_Parent();
6879     }
6880     if (pid == -1)
6881         return posix_error();
6882     return PyLong_FromPid(pid);
6883 }
6884 #endif /* HAVE_FORK */
6885 
6886 
6887 #ifdef HAVE_SCHED_H
6888 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6889 /*[clinic input]
6890 os.sched_get_priority_max
6891 
6892     policy: int
6893 
6894 Get the maximum scheduling priority for policy.
6895 [clinic start generated code]*/
6896 
6897 static PyObject *
os_sched_get_priority_max_impl(PyObject *module, int policy)6898 os_sched_get_priority_max_impl(PyObject *module, int policy)
6899 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6900 {
6901     int max;
6902 
6903     max = sched_get_priority_max(policy);
6904     if (max < 0)
6905         return posix_error();
6906     return PyLong_FromLong(max);
6907 }
6908 
6909 
6910 /*[clinic input]
6911 os.sched_get_priority_min
6912 
6913     policy: int
6914 
6915 Get the minimum scheduling priority for policy.
6916 [clinic start generated code]*/
6917 
6918 static PyObject *
os_sched_get_priority_min_impl(PyObject *module, int policy)6919 os_sched_get_priority_min_impl(PyObject *module, int policy)
6920 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6921 {
6922     int min = sched_get_priority_min(policy);
6923     if (min < 0)
6924         return posix_error();
6925     return PyLong_FromLong(min);
6926 }
6927 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6928 
6929 
6930 #ifdef HAVE_SCHED_SETSCHEDULER
6931 /*[clinic input]
6932 os.sched_getscheduler
6933     pid: pid_t
6934     /
6935 
6936 Get the scheduling policy for the process identified by pid.
6937 
6938 Passing 0 for pid returns the scheduling policy for the calling process.
6939 [clinic start generated code]*/
6940 
6941 static PyObject *
os_sched_getscheduler_impl(PyObject *module, pid_t pid)6942 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6943 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6944 {
6945     int policy;
6946 
6947     policy = sched_getscheduler(pid);
6948     if (policy < 0)
6949         return posix_error();
6950     return PyLong_FromLong(policy);
6951 }
6952 #endif /* HAVE_SCHED_SETSCHEDULER */
6953 
6954 
6955 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6956 /*[clinic input]
6957 class os.sched_param "PyObject *" "SchedParamType"
6958 
6959 @classmethod
6960 os.sched_param.__new__
6961 
6962     sched_priority: object
6963         A scheduling parameter.
6964 
6965 Currently has only one field: sched_priority
6966 [clinic start generated code]*/
6967 
6968 static PyObject *
os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)6969 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6970 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6971 {
6972     PyObject *res;
6973 
6974     res = PyStructSequence_New(type);
6975     if (!res)
6976         return NULL;
6977     Py_INCREF(sched_priority);
6978     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6979     return res;
6980 }
6981 
6982 PyDoc_VAR(os_sched_param__doc__);
6983 
6984 static PyStructSequence_Field sched_param_fields[] = {
6985     {"sched_priority", "the scheduling priority"},
6986     {0}
6987 };
6988 
6989 static PyStructSequence_Desc sched_param_desc = {
6990     "sched_param", /* name */
6991     os_sched_param__doc__, /* doc */
6992     sched_param_fields,
6993     1
6994 };
6995 
6996 static int
convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)6997 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6998 {
6999     long priority;
7000 
7001     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
7002         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
7003         return 0;
7004     }
7005     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
7006     if (priority == -1 && PyErr_Occurred())
7007         return 0;
7008     if (priority > INT_MAX || priority < INT_MIN) {
7009         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
7010         return 0;
7011     }
7012     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
7013     return 1;
7014 }
7015 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
7016 
7017 
7018 #ifdef HAVE_SCHED_SETSCHEDULER
7019 /*[clinic input]
7020 os.sched_setscheduler
7021 
7022     pid: pid_t
7023     policy: int
7024     param as param_obj: object
7025     /
7026 
7027 Set the scheduling policy for the process identified by pid.
7028 
7029 If pid is 0, the calling process is changed.
7030 param is an instance of sched_param.
7031 [clinic start generated code]*/
7032 
7033 static PyObject *
os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy, PyObject *param_obj)7034 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
7035                            PyObject *param_obj)
7036 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
7037 {
7038     struct sched_param param;
7039     if (!convert_sched_param(module, param_obj, &param)) {
7040         return NULL;
7041     }
7042 
7043     /*
7044     ** sched_setscheduler() returns 0 in Linux, but the previous
7045     ** scheduling policy under Solaris/Illumos, and others.
7046     ** On error, -1 is returned in all Operating Systems.
7047     */
7048     if (sched_setscheduler(pid, policy, &param) == -1)
7049         return posix_error();
7050     Py_RETURN_NONE;
7051 }
7052 #endif  /* HAVE_SCHED_SETSCHEDULER*/
7053 
7054 
7055 #ifdef HAVE_SCHED_SETPARAM
7056 /*[clinic input]
7057 os.sched_getparam
7058     pid: pid_t
7059     /
7060 
7061 Returns scheduling parameters for the process identified by pid.
7062 
7063 If pid is 0, returns parameters for the calling process.
7064 Return value is an instance of sched_param.
7065 [clinic start generated code]*/
7066 
7067 static PyObject *
os_sched_getparam_impl(PyObject *module, pid_t pid)7068 os_sched_getparam_impl(PyObject *module, pid_t pid)
7069 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7070 {
7071     struct sched_param param;
7072     PyObject *result;
7073     PyObject *priority;
7074 
7075     if (sched_getparam(pid, &param))
7076         return posix_error();
7077     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7078     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7079     if (!result)
7080         return NULL;
7081     priority = PyLong_FromLong(param.sched_priority);
7082     if (!priority) {
7083         Py_DECREF(result);
7084         return NULL;
7085     }
7086     PyStructSequence_SET_ITEM(result, 0, priority);
7087     return result;
7088 }
7089 
7090 
7091 /*[clinic input]
7092 os.sched_setparam
7093     pid: pid_t
7094     param as param_obj: object
7095     /
7096 
7097 Set scheduling parameters for the process identified by pid.
7098 
7099 If pid is 0, sets parameters for the calling process.
7100 param should be an instance of sched_param.
7101 [clinic start generated code]*/
7102 
7103 static PyObject *
os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)7104 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7105 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7106 {
7107     struct sched_param param;
7108     if (!convert_sched_param(module, param_obj, &param)) {
7109         return NULL;
7110     }
7111 
7112     if (sched_setparam(pid, &param))
7113         return posix_error();
7114     Py_RETURN_NONE;
7115 }
7116 #endif /* HAVE_SCHED_SETPARAM */
7117 
7118 
7119 #ifdef HAVE_SCHED_RR_GET_INTERVAL
7120 /*[clinic input]
7121 os.sched_rr_get_interval -> double
7122     pid: pid_t
7123     /
7124 
7125 Return the round-robin quantum for the process identified by pid, in seconds.
7126 
7127 Value returned is a float.
7128 [clinic start generated code]*/
7129 
7130 static double
os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)7131 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7132 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7133 {
7134     struct timespec interval;
7135     if (sched_rr_get_interval(pid, &interval)) {
7136         posix_error();
7137         return -1.0;
7138     }
7139 #ifdef _Py_MEMORY_SANITIZER
7140     __msan_unpoison(&interval, sizeof(interval));
7141 #endif
7142     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7143 }
7144 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7145 
7146 
7147 /*[clinic input]
7148 os.sched_yield
7149 
7150 Voluntarily relinquish the CPU.
7151 [clinic start generated code]*/
7152 
7153 static PyObject *
os_sched_yield_impl(PyObject *module)7154 os_sched_yield_impl(PyObject *module)
7155 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7156 {
7157     int result;
7158     Py_BEGIN_ALLOW_THREADS
7159     result = sched_yield();
7160     Py_END_ALLOW_THREADS
7161     if (result < 0) {
7162         return posix_error();
7163     }
7164     Py_RETURN_NONE;
7165 }
7166 
7167 #ifdef HAVE_SCHED_SETAFFINITY
7168 /* The minimum number of CPUs allocated in a cpu_set_t */
7169 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7170 
7171 /*[clinic input]
7172 os.sched_setaffinity
7173     pid: pid_t
7174     mask : object
7175     /
7176 
7177 Set the CPU affinity of the process identified by pid to mask.
7178 
7179 mask should be an iterable of integers identifying CPUs.
7180 [clinic start generated code]*/
7181 
7182 static PyObject *
os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)7183 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7184 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7185 {
7186     int ncpus;
7187     size_t setsize;
7188     cpu_set_t *cpu_set = NULL;
7189     PyObject *iterator = NULL, *item;
7190 
7191     iterator = PyObject_GetIter(mask);
7192     if (iterator == NULL)
7193         return NULL;
7194 
7195     ncpus = NCPUS_START;
7196     setsize = CPU_ALLOC_SIZE(ncpus);
7197     cpu_set = CPU_ALLOC(ncpus);
7198     if (cpu_set == NULL) {
7199         PyErr_NoMemory();
7200         goto error;
7201     }
7202     CPU_ZERO_S(setsize, cpu_set);
7203 
7204     while ((item = PyIter_Next(iterator))) {
7205         long cpu;
7206         if (!PyLong_Check(item)) {
7207             PyErr_Format(PyExc_TypeError,
7208                         "expected an iterator of ints, "
7209                         "but iterator yielded %R",
7210                         Py_TYPE(item));
7211             Py_DECREF(item);
7212             goto error;
7213         }
7214         cpu = PyLong_AsLong(item);
7215         Py_DECREF(item);
7216         if (cpu < 0) {
7217             if (!PyErr_Occurred())
7218                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7219             goto error;
7220         }
7221         if (cpu > INT_MAX - 1) {
7222             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7223             goto error;
7224         }
7225         if (cpu >= ncpus) {
7226             /* Grow CPU mask to fit the CPU number */
7227             int newncpus = ncpus;
7228             cpu_set_t *newmask;
7229             size_t newsetsize;
7230             while (newncpus <= cpu) {
7231                 if (newncpus > INT_MAX / 2)
7232                     newncpus = cpu + 1;
7233                 else
7234                     newncpus = newncpus * 2;
7235             }
7236             newmask = CPU_ALLOC(newncpus);
7237             if (newmask == NULL) {
7238                 PyErr_NoMemory();
7239                 goto error;
7240             }
7241             newsetsize = CPU_ALLOC_SIZE(newncpus);
7242             CPU_ZERO_S(newsetsize, newmask);
7243             memcpy(newmask, cpu_set, setsize);
7244             CPU_FREE(cpu_set);
7245             setsize = newsetsize;
7246             cpu_set = newmask;
7247             ncpus = newncpus;
7248         }
7249         CPU_SET_S(cpu, setsize, cpu_set);
7250     }
7251     if (PyErr_Occurred()) {
7252         goto error;
7253     }
7254     Py_CLEAR(iterator);
7255 
7256     if (sched_setaffinity(pid, setsize, cpu_set)) {
7257         posix_error();
7258         goto error;
7259     }
7260     CPU_FREE(cpu_set);
7261     Py_RETURN_NONE;
7262 
7263 error:
7264     if (cpu_set)
7265         CPU_FREE(cpu_set);
7266     Py_XDECREF(iterator);
7267     return NULL;
7268 }
7269 
7270 
7271 /*[clinic input]
7272 os.sched_getaffinity
7273     pid: pid_t
7274     /
7275 
7276 Return the affinity of the process identified by pid (or the current process if zero).
7277 
7278 The affinity is returned as a set of CPU identifiers.
7279 [clinic start generated code]*/
7280 
7281 static PyObject *
os_sched_getaffinity_impl(PyObject *module, pid_t pid)7282 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7283 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7284 {
7285     int cpu, ncpus, count;
7286     size_t setsize;
7287     cpu_set_t *mask = NULL;
7288     PyObject *res = NULL;
7289 
7290     ncpus = NCPUS_START;
7291     while (1) {
7292         setsize = CPU_ALLOC_SIZE(ncpus);
7293         mask = CPU_ALLOC(ncpus);
7294         if (mask == NULL)
7295             return PyErr_NoMemory();
7296         if (sched_getaffinity(pid, setsize, mask) == 0)
7297             break;
7298         CPU_FREE(mask);
7299         if (errno != EINVAL)
7300             return posix_error();
7301         if (ncpus > INT_MAX / 2) {
7302             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7303                             "a large enough CPU set");
7304             return NULL;
7305         }
7306         ncpus = ncpus * 2;
7307     }
7308 
7309     res = PySet_New(NULL);
7310     if (res == NULL)
7311         goto error;
7312     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7313         if (CPU_ISSET_S(cpu, setsize, mask)) {
7314             PyObject *cpu_num = PyLong_FromLong(cpu);
7315             --count;
7316             if (cpu_num == NULL)
7317                 goto error;
7318             if (PySet_Add(res, cpu_num)) {
7319                 Py_DECREF(cpu_num);
7320                 goto error;
7321             }
7322             Py_DECREF(cpu_num);
7323         }
7324     }
7325     CPU_FREE(mask);
7326     return res;
7327 
7328 error:
7329     if (mask)
7330         CPU_FREE(mask);
7331     Py_XDECREF(res);
7332     return NULL;
7333 }
7334 
7335 #endif /* HAVE_SCHED_SETAFFINITY */
7336 
7337 #endif /* HAVE_SCHED_H */
7338 
7339 
7340 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7341 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7342 #  define DEV_PTY_FILE "/dev/ptc"
7343 #  define HAVE_DEV_PTMX
7344 #else
7345 #  define DEV_PTY_FILE "/dev/ptmx"
7346 #endif
7347 
7348 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7349 #ifdef HAVE_PTY_H
7350 #include <pty.h>
7351 #ifdef HAVE_UTMP_H
7352 #include <utmp.h>
7353 #endif /* HAVE_UTMP_H */
7354 #elif defined(HAVE_LIBUTIL_H)
7355 #include <libutil.h>
7356 #elif defined(HAVE_UTIL_H)
7357 #include <util.h>
7358 #endif /* HAVE_PTY_H */
7359 #ifdef HAVE_STROPTS_H
7360 #include <stropts.h>
7361 #endif
7362 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7363 
7364 
7365 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7366 /*[clinic input]
7367 os.openpty
7368 
7369 Open a pseudo-terminal.
7370 
7371 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7372 for both the master and slave ends.
7373 [clinic start generated code]*/
7374 
7375 static PyObject *
os_openpty_impl(PyObject *module)7376 os_openpty_impl(PyObject *module)
7377 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7378 {
7379     int master_fd = -1, slave_fd = -1;
7380 #ifndef HAVE_OPENPTY
7381     char * slave_name;
7382 #endif
7383 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7384     PyOS_sighandler_t sig_saved;
7385 #if defined(__sun) && defined(__SVR4)
7386     extern char *ptsname(int fildes);
7387 #endif
7388 #endif
7389 
7390 #ifdef HAVE_OPENPTY
7391     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7392         goto posix_error;
7393 
7394     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7395         goto error;
7396     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7397         goto error;
7398 
7399 #elif defined(HAVE__GETPTY)
7400     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7401     if (slave_name == NULL)
7402         goto posix_error;
7403     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7404         goto error;
7405 
7406     slave_fd = _Py_open(slave_name, O_RDWR);
7407     if (slave_fd < 0)
7408         goto error;
7409 
7410 #else
7411     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7412     if (master_fd < 0)
7413         goto posix_error;
7414 
7415     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7416 
7417     /* change permission of slave */
7418     if (grantpt(master_fd) < 0) {
7419         PyOS_setsig(SIGCHLD, sig_saved);
7420         goto posix_error;
7421     }
7422 
7423     /* unlock slave */
7424     if (unlockpt(master_fd) < 0) {
7425         PyOS_setsig(SIGCHLD, sig_saved);
7426         goto posix_error;
7427     }
7428 
7429     PyOS_setsig(SIGCHLD, sig_saved);
7430 
7431     slave_name = ptsname(master_fd); /* get name of slave */
7432     if (slave_name == NULL)
7433         goto posix_error;
7434 
7435     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7436     if (slave_fd == -1)
7437         goto error;
7438 
7439     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7440         goto posix_error;
7441 
7442 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7443     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7444     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7445 #ifndef __hpux
7446     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7447 #endif /* __hpux */
7448 #endif /* HAVE_CYGWIN */
7449 #endif /* HAVE_OPENPTY */
7450 
7451     return Py_BuildValue("(ii)", master_fd, slave_fd);
7452 
7453 posix_error:
7454     posix_error();
7455 error:
7456     if (master_fd != -1)
7457         close(master_fd);
7458     if (slave_fd != -1)
7459         close(slave_fd);
7460     return NULL;
7461 }
7462 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7463 
7464 
7465 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7466 #define HAVE_FALLBACK_LOGIN_TTY 1
7467 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7468 
7469 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7470 /*[clinic input]
7471 os.login_tty
7472 
7473     fd: fildes
7474     /
7475 
7476 Prepare the tty of which fd is a file descriptor for a new login session.
7477 
7478 Make the calling process a session leader; make the tty the
7479 controlling tty, the stdin, the stdout, and the stderr of the
7480 calling process; close fd.
7481 [clinic start generated code]*/
7482 
7483 static PyObject *
os_login_tty_impl(PyObject *module, int fd)7484 os_login_tty_impl(PyObject *module, int fd)
7485 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7486 {
7487 #ifdef HAVE_LOGIN_TTY
7488     if (login_tty(fd) == -1) {
7489         return posix_error();
7490     }
7491 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7492     /* Establish a new session. */
7493     if (setsid() == -1) {
7494         return posix_error();
7495     }
7496 
7497     /* The tty becomes the controlling terminal. */
7498     if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7499         return posix_error();
7500     }
7501 
7502     /* The tty becomes stdin/stdout/stderr */
7503     if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7504         return posix_error();
7505     }
7506     if (fd > 2) {
7507         close(fd);
7508     }
7509 #endif /* HAVE_LOGIN_TTY */
7510     Py_RETURN_NONE;
7511 }
7512 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7513 
7514 
7515 #ifdef HAVE_FORKPTY
7516 /*[clinic input]
7517 os.forkpty
7518 
7519 Fork a new process with a new pseudo-terminal as controlling tty.
7520 
7521 Returns a tuple of (pid, master_fd).
7522 Like fork(), return pid of 0 to the child process,
7523 and pid of child to the parent process.
7524 To both, return fd of newly opened pseudo-terminal.
7525 [clinic start generated code]*/
7526 
7527 static PyObject *
os_forkpty_impl(PyObject *module)7528 os_forkpty_impl(PyObject *module)
7529 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7530 {
7531     int master_fd = -1;
7532     pid_t pid;
7533 
7534     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7535         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7536         return NULL;
7537     }
7538     if (PySys_Audit("os.forkpty", NULL) < 0) {
7539         return NULL;
7540     }
7541     PyOS_BeforeFork();
7542     pid = forkpty(&master_fd, NULL, NULL, NULL);
7543     if (pid == 0) {
7544         /* child: this clobbers and resets the import lock. */
7545         PyOS_AfterFork_Child();
7546     } else {
7547         /* parent: release the import lock. */
7548         PyOS_AfterFork_Parent();
7549     }
7550     if (pid == -1) {
7551         return posix_error();
7552     }
7553     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7554 }
7555 #endif /* HAVE_FORKPTY */
7556 
7557 
7558 #ifdef HAVE_GETEGID
7559 /*[clinic input]
7560 os.getegid
7561 
7562 Return the current process's effective group id.
7563 [clinic start generated code]*/
7564 
7565 static PyObject *
os_getegid_impl(PyObject *module)7566 os_getegid_impl(PyObject *module)
7567 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7568 {
7569     return _PyLong_FromGid(getegid());
7570 }
7571 #endif /* HAVE_GETEGID */
7572 
7573 
7574 #ifdef HAVE_GETEUID
7575 /*[clinic input]
7576 os.geteuid
7577 
7578 Return the current process's effective user id.
7579 [clinic start generated code]*/
7580 
7581 static PyObject *
os_geteuid_impl(PyObject *module)7582 os_geteuid_impl(PyObject *module)
7583 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7584 {
7585     return _PyLong_FromUid(geteuid());
7586 }
7587 #endif /* HAVE_GETEUID */
7588 
7589 
7590 #ifdef HAVE_GETGID
7591 /*[clinic input]
7592 os.getgid
7593 
7594 Return the current process's group id.
7595 [clinic start generated code]*/
7596 
7597 static PyObject *
os_getgid_impl(PyObject *module)7598 os_getgid_impl(PyObject *module)
7599 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7600 {
7601     return _PyLong_FromGid(getgid());
7602 }
7603 #endif /* HAVE_GETGID */
7604 
7605 
7606 #ifdef HAVE_GETPID
7607 /*[clinic input]
7608 os.getpid
7609 
7610 Return the current process id.
7611 [clinic start generated code]*/
7612 
7613 static PyObject *
os_getpid_impl(PyObject *module)7614 os_getpid_impl(PyObject *module)
7615 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7616 {
7617     return PyLong_FromPid(getpid());
7618 }
7619 #endif /* HAVE_GETPID */
7620 
7621 #ifdef NGROUPS_MAX
7622 #define MAX_GROUPS NGROUPS_MAX
7623 #else
7624     /* defined to be 16 on Solaris7, so this should be a small number */
7625 #define MAX_GROUPS 64
7626 #endif
7627 
7628 #ifdef HAVE_GETGROUPLIST
7629 
7630 #ifdef __APPLE__
7631 /*[clinic input]
7632 os.getgrouplist
7633 
7634     user: str
7635         username to lookup
7636     group as basegid: int
7637         base group id of the user
7638     /
7639 
7640 Returns a list of groups to which a user belongs.
7641 [clinic start generated code]*/
7642 
7643 static PyObject *
os_getgrouplist_impl(PyObject *module, const char *user, int basegid)7644 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7645 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7646 #else
7647 /*[clinic input]
7648 os.getgrouplist
7649 
7650     user: str
7651         username to lookup
7652     group as basegid: gid_t
7653         base group id of the user
7654     /
7655 
7656 Returns a list of groups to which a user belongs.
7657 [clinic start generated code]*/
7658 
7659 static PyObject *
7660 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7661 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7662 #endif
7663 {
7664     int i, ngroups;
7665     PyObject *list;
7666 #ifdef __APPLE__
7667     int *groups;
7668 #else
7669     gid_t *groups;
7670 #endif
7671 
7672     /*
7673      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7674      * number of supplimental groups a users can belong to.
7675      * We have to increment it by one because
7676      * getgrouplist() returns both the supplemental groups
7677      * and the primary group, i.e. all of the groups the
7678      * user belongs to.
7679      */
7680     ngroups = 1 + MAX_GROUPS;
7681 
7682     while (1) {
7683 #ifdef __APPLE__
7684         groups = PyMem_New(int, ngroups);
7685 #else
7686         groups = PyMem_New(gid_t, ngroups);
7687 #endif
7688         if (groups == NULL) {
7689             return PyErr_NoMemory();
7690         }
7691 
7692         int old_ngroups = ngroups;
7693         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7694             /* Success */
7695             break;
7696         }
7697 
7698         /* getgrouplist() fails if the group list is too small */
7699         PyMem_Free(groups);
7700 
7701         if (ngroups > old_ngroups) {
7702             /* If the group list is too small, the glibc implementation of
7703                getgrouplist() sets ngroups to the total number of groups and
7704                returns -1. */
7705         }
7706         else {
7707             /* Double the group list size */
7708             if (ngroups > INT_MAX / 2) {
7709                 return PyErr_NoMemory();
7710             }
7711             ngroups *= 2;
7712         }
7713 
7714         /* Retry getgrouplist() with a larger group list */
7715     }
7716 
7717 #ifdef _Py_MEMORY_SANITIZER
7718     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7719     __msan_unpoison(&ngroups, sizeof(ngroups));
7720     __msan_unpoison(groups, ngroups*sizeof(*groups));
7721 #endif
7722 
7723     list = PyList_New(ngroups);
7724     if (list == NULL) {
7725         PyMem_Free(groups);
7726         return NULL;
7727     }
7728 
7729     for (i = 0; i < ngroups; i++) {
7730 #ifdef __APPLE__
7731         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7732 #else
7733         PyObject *o = _PyLong_FromGid(groups[i]);
7734 #endif
7735         if (o == NULL) {
7736             Py_DECREF(list);
7737             PyMem_Free(groups);
7738             return NULL;
7739         }
7740         PyList_SET_ITEM(list, i, o);
7741     }
7742 
7743     PyMem_Free(groups);
7744 
7745     return list;
7746 }
7747 #endif /* HAVE_GETGROUPLIST */
7748 
7749 
7750 #ifdef HAVE_GETGROUPS
7751 /*[clinic input]
7752 os.getgroups
7753 
7754 Return list of supplemental group IDs for the process.
7755 [clinic start generated code]*/
7756 
7757 static PyObject *
os_getgroups_impl(PyObject *module)7758 os_getgroups_impl(PyObject *module)
7759 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7760 {
7761     // Call getgroups with length 0 to get the actual number of groups
7762     int n = getgroups(0, NULL);
7763     if (n < 0) {
7764         return posix_error();
7765     }
7766 
7767     if (n == 0) {
7768         return PyList_New(0);
7769     }
7770 
7771     gid_t *grouplist = PyMem_New(gid_t, n);
7772     if (grouplist == NULL) {
7773         return PyErr_NoMemory();
7774     }
7775 
7776     n = getgroups(n, grouplist);
7777     if (n == -1) {
7778         PyMem_Free(grouplist);
7779         return posix_error();
7780     }
7781 
7782     PyObject *result = PyList_New(n);
7783     if (result == NULL) {
7784         goto error;
7785     }
7786 
7787     for (int i = 0; i < n; ++i) {
7788         PyObject *group = _PyLong_FromGid(grouplist[i]);
7789         if (group == NULL) {
7790             goto error;
7791         }
7792         PyList_SET_ITEM(result, i, group);
7793     }
7794     PyMem_Free(grouplist);
7795 
7796     return result;
7797 
7798 error:
7799     PyMem_Free(grouplist);
7800     Py_XDECREF(result);
7801     return NULL;
7802 }
7803 #endif /* HAVE_GETGROUPS */
7804 
7805 #ifdef HAVE_INITGROUPS
7806 #ifdef __APPLE__
7807 /*[clinic input]
7808 os.initgroups
7809 
7810     username as oname: FSConverter
7811     gid: int
7812     /
7813 
7814 Initialize the group access list.
7815 
7816 Call the system initgroups() to initialize the group access list with all of
7817 the groups of which the specified username is a member, plus the specified
7818 group id.
7819 [clinic start generated code]*/
7820 
7821 static PyObject *
os_initgroups_impl(PyObject *module, PyObject *oname, int gid)7822 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7823 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7824 #else
7825 /*[clinic input]
7826 os.initgroups
7827 
7828     username as oname: FSConverter
7829     gid: gid_t
7830     /
7831 
7832 Initialize the group access list.
7833 
7834 Call the system initgroups() to initialize the group access list with all of
7835 the groups of which the specified username is a member, plus the specified
7836 group id.
7837 [clinic start generated code]*/
7838 
7839 static PyObject *
7840 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7841 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7842 #endif
7843 {
7844     const char *username = PyBytes_AS_STRING(oname);
7845 
7846     if (initgroups(username, gid) == -1)
7847         return PyErr_SetFromErrno(PyExc_OSError);
7848 
7849     Py_RETURN_NONE;
7850 }
7851 #endif /* HAVE_INITGROUPS */
7852 
7853 
7854 #ifdef HAVE_GETPGID
7855 /*[clinic input]
7856 os.getpgid
7857 
7858     pid: pid_t
7859 
7860 Call the system call getpgid(), and return the result.
7861 [clinic start generated code]*/
7862 
7863 static PyObject *
os_getpgid_impl(PyObject *module, pid_t pid)7864 os_getpgid_impl(PyObject *module, pid_t pid)
7865 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7866 {
7867     pid_t pgid = getpgid(pid);
7868     if (pgid < 0)
7869         return posix_error();
7870     return PyLong_FromPid(pgid);
7871 }
7872 #endif /* HAVE_GETPGID */
7873 
7874 
7875 #ifdef HAVE_GETPGRP
7876 /*[clinic input]
7877 os.getpgrp
7878 
7879 Return the current process group id.
7880 [clinic start generated code]*/
7881 
7882 static PyObject *
os_getpgrp_impl(PyObject *module)7883 os_getpgrp_impl(PyObject *module)
7884 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7885 {
7886 #ifdef GETPGRP_HAVE_ARG
7887     return PyLong_FromPid(getpgrp(0));
7888 #else /* GETPGRP_HAVE_ARG */
7889     return PyLong_FromPid(getpgrp());
7890 #endif /* GETPGRP_HAVE_ARG */
7891 }
7892 #endif /* HAVE_GETPGRP */
7893 
7894 
7895 #ifdef HAVE_SETPGRP
7896 /*[clinic input]
7897 os.setpgrp
7898 
7899 Make the current process the leader of its process group.
7900 [clinic start generated code]*/
7901 
7902 static PyObject *
os_setpgrp_impl(PyObject *module)7903 os_setpgrp_impl(PyObject *module)
7904 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7905 {
7906 #ifdef SETPGRP_HAVE_ARG
7907     if (setpgrp(0, 0) < 0)
7908 #else /* SETPGRP_HAVE_ARG */
7909     if (setpgrp() < 0)
7910 #endif /* SETPGRP_HAVE_ARG */
7911         return posix_error();
7912     Py_RETURN_NONE;
7913 }
7914 #endif /* HAVE_SETPGRP */
7915 
7916 #ifdef HAVE_GETPPID
7917 
7918 #ifdef MS_WINDOWS
7919 #include <tlhelp32.h>
7920 
7921 static PyObject*
win32_getppidnull7922 win32_getppid()
7923 {
7924     HANDLE snapshot;
7925     pid_t mypid;
7926     PyObject* result = NULL;
7927     BOOL have_record;
7928     PROCESSENTRY32 pe;
7929 
7930     mypid = getpid(); /* This function never fails */
7931 
7932     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7933     if (snapshot == INVALID_HANDLE_VALUE)
7934         return PyErr_SetFromWindowsErr(GetLastError());
7935 
7936     pe.dwSize = sizeof(pe);
7937     have_record = Process32First(snapshot, &pe);
7938     while (have_record) {
7939         if (mypid == (pid_t)pe.th32ProcessID) {
7940             /* We could cache the ulong value in a static variable. */
7941             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7942             break;
7943         }
7944 
7945         have_record = Process32Next(snapshot, &pe);
7946     }
7947 
7948     /* If our loop exits and our pid was not found (result will be NULL)
7949      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7950      * error anyway, so let's raise it. */
7951     if (!result)
7952         result = PyErr_SetFromWindowsErr(GetLastError());
7953 
7954     CloseHandle(snapshot);
7955 
7956     return result;
7957 }
7958 #endif /*MS_WINDOWS*/
7959 
7960 
7961 /*[clinic input]
7962 os.getppid
7963 
7964 Return the parent's process id.
7965 
7966 If the parent process has already exited, Windows machines will still
7967 return its id; others systems will return the id of the 'init' process (1).
7968 [clinic start generated code]*/
7969 
7970 static PyObject *
os_getppid_impl(PyObject *module)7971 os_getppid_impl(PyObject *module)
7972 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7973 {
7974 #ifdef MS_WINDOWS
7975     return win32_getppid();
7976 #else
7977     return PyLong_FromPid(getppid());
7978 #endif
7979 }
7980 #endif /* HAVE_GETPPID */
7981 
7982 
7983 #ifdef HAVE_GETLOGIN
7984 /*[clinic input]
7985 os.getlogin
7986 
7987 Return the actual login name.
7988 [clinic start generated code]*/
7989 
7990 static PyObject *
os_getlogin_impl(PyObject *module)7991 os_getlogin_impl(PyObject *module)
7992 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7993 {
7994     PyObject *result = NULL;
7995 #ifdef MS_WINDOWS
7996     wchar_t user_name[UNLEN + 1];
7997     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7998 
7999     if (GetUserNameW(user_name, &num_chars)) {
8000         /* num_chars is the number of unicode chars plus null terminator */
8001         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
8002     }
8003     else
8004         result = PyErr_SetFromWindowsErr(GetLastError());
8005 #else
8006     char *name;
8007     int old_errno = errno;
8008 
8009     errno = 0;
8010     name = getlogin();
8011     if (name == NULL) {
8012         if (errno)
8013             posix_error();
8014         else
8015             PyErr_SetString(PyExc_OSError, "unable to determine login name");
8016     }
8017     else
8018         result = PyUnicode_DecodeFSDefault(name);
8019     errno = old_errno;
8020 #endif
8021     return result;
8022 }
8023 #endif /* HAVE_GETLOGIN */
8024 
8025 
8026 #ifdef HAVE_GETUID
8027 /*[clinic input]
8028 os.getuid
8029 
8030 Return the current process's user id.
8031 [clinic start generated code]*/
8032 
8033 static PyObject *
os_getuid_impl(PyObject *module)8034 os_getuid_impl(PyObject *module)
8035 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
8036 {
8037     return _PyLong_FromUid(getuid());
8038 }
8039 #endif /* HAVE_GETUID */
8040 
8041 
8042 #ifdef MS_WINDOWS
8043 #define HAVE_KILL
8044 #endif /* MS_WINDOWS */
8045 
8046 #ifdef HAVE_KILL
8047 /*[clinic input]
8048 os.kill
8049 
8050     pid: pid_t
8051     signal: Py_ssize_t
8052     /
8053 
8054 Kill a process with a signal.
8055 [clinic start generated code]*/
8056 
8057 static PyObject *
os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)8058 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8059 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8060 {
8061     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8062         return NULL;
8063     }
8064 #ifndef MS_WINDOWS
8065     if (kill(pid, (int)signal) == -1) {
8066         return posix_error();
8067     }
8068 
8069     // Check immediately if the signal was sent to the current process.
8070     // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8071     // is cheap.
8072     if (PyErr_CheckSignals()) {
8073         return NULL;
8074     }
8075 
8076     Py_RETURN_NONE;
8077 #else /* !MS_WINDOWS */
8078     PyObject *result;
8079     DWORD sig = (DWORD)signal;
8080     DWORD err;
8081     HANDLE handle;
8082 
8083     /* Console processes which share a common console can be sent CTRL+C or
8084        CTRL+BREAK events, provided they handle said events. */
8085     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8086         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8087             err = GetLastError();
8088             PyErr_SetFromWindowsErr(err);
8089         }
8090         else
8091             Py_RETURN_NONE;
8092     }
8093 
8094     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8095        attempt to open and terminate the process. */
8096     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8097     if (handle == NULL) {
8098         err = GetLastError();
8099         return PyErr_SetFromWindowsErr(err);
8100     }
8101 
8102     if (TerminateProcess(handle, sig) == 0) {
8103         err = GetLastError();
8104         result = PyErr_SetFromWindowsErr(err);
8105     } else {
8106         Py_INCREF(Py_None);
8107         result = Py_None;
8108     }
8109 
8110     CloseHandle(handle);
8111     return result;
8112 #endif /* !MS_WINDOWS */
8113 }
8114 #endif /* HAVE_KILL */
8115 
8116 
8117 #ifdef HAVE_KILLPG
8118 /*[clinic input]
8119 os.killpg
8120 
8121     pgid: pid_t
8122     signal: int
8123     /
8124 
8125 Kill a process group with a signal.
8126 [clinic start generated code]*/
8127 
8128 static PyObject *
os_killpg_impl(PyObject *module, pid_t pgid, int signal)8129 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8130 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8131 {
8132     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8133         return NULL;
8134     }
8135     /* XXX some man pages make the `pgid` parameter an int, others
8136        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8137        take the same type. Moreover, pid_t is always at least as wide as
8138        int (else compilation of this module fails), which is safe. */
8139     if (killpg(pgid, signal) == -1)
8140         return posix_error();
8141     Py_RETURN_NONE;
8142 }
8143 #endif /* HAVE_KILLPG */
8144 
8145 
8146 #ifdef HAVE_PLOCK
8147 #ifdef HAVE_SYS_LOCK_H
8148 #include <sys/lock.h>
8149 #endif
8150 
8151 /*[clinic input]
8152 os.plock
8153     op: int
8154     /
8155 
8156 Lock program segments into memory.");
8157 [clinic start generated code]*/
8158 
8159 static PyObject *
os_plock_impl(PyObject *module, int op)8160 os_plock_impl(PyObject *module, int op)
8161 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8162 {
8163     if (plock(op) == -1)
8164         return posix_error();
8165     Py_RETURN_NONE;
8166 }
8167 #endif /* HAVE_PLOCK */
8168 
8169 
8170 #ifdef HAVE_SETUID
8171 /*[clinic input]
8172 os.setuid
8173 
8174     uid: uid_t
8175     /
8176 
8177 Set the current process's user id.
8178 [clinic start generated code]*/
8179 
8180 static PyObject *
os_setuid_impl(PyObject *module, uid_t uid)8181 os_setuid_impl(PyObject *module, uid_t uid)
8182 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8183 {
8184     if (setuid(uid) < 0)
8185         return posix_error();
8186     Py_RETURN_NONE;
8187 }
8188 #endif /* HAVE_SETUID */
8189 
8190 
8191 #ifdef HAVE_SETEUID
8192 /*[clinic input]
8193 os.seteuid
8194 
8195     euid: uid_t
8196     /
8197 
8198 Set the current process's effective user id.
8199 [clinic start generated code]*/
8200 
8201 static PyObject *
os_seteuid_impl(PyObject *module, uid_t euid)8202 os_seteuid_impl(PyObject *module, uid_t euid)
8203 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8204 {
8205     if (seteuid(euid) < 0)
8206         return posix_error();
8207     Py_RETURN_NONE;
8208 }
8209 #endif /* HAVE_SETEUID */
8210 
8211 
8212 #ifdef HAVE_SETEGID
8213 /*[clinic input]
8214 os.setegid
8215 
8216     egid: gid_t
8217     /
8218 
8219 Set the current process's effective group id.
8220 [clinic start generated code]*/
8221 
8222 static PyObject *
os_setegid_impl(PyObject *module, gid_t egid)8223 os_setegid_impl(PyObject *module, gid_t egid)
8224 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8225 {
8226     if (setegid(egid) < 0)
8227         return posix_error();
8228     Py_RETURN_NONE;
8229 }
8230 #endif /* HAVE_SETEGID */
8231 
8232 
8233 #ifdef HAVE_SETREUID
8234 /*[clinic input]
8235 os.setreuid
8236 
8237     ruid: uid_t
8238     euid: uid_t
8239     /
8240 
8241 Set the current process's real and effective user ids.
8242 [clinic start generated code]*/
8243 
8244 static PyObject *
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)8245 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8246 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8247 {
8248     if (setreuid(ruid, euid) < 0) {
8249         return posix_error();
8250     } else {
8251         Py_RETURN_NONE;
8252     }
8253 }
8254 #endif /* HAVE_SETREUID */
8255 
8256 
8257 #ifdef HAVE_SETREGID
8258 /*[clinic input]
8259 os.setregid
8260 
8261     rgid: gid_t
8262     egid: gid_t
8263     /
8264 
8265 Set the current process's real and effective group ids.
8266 [clinic start generated code]*/
8267 
8268 static PyObject *
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)8269 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8270 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8271 {
8272     if (setregid(rgid, egid) < 0)
8273         return posix_error();
8274     Py_RETURN_NONE;
8275 }
8276 #endif /* HAVE_SETREGID */
8277 
8278 
8279 #ifdef HAVE_SETGID
8280 /*[clinic input]
8281 os.setgid
8282     gid: gid_t
8283     /
8284 
8285 Set the current process's group id.
8286 [clinic start generated code]*/
8287 
8288 static PyObject *
os_setgid_impl(PyObject *module, gid_t gid)8289 os_setgid_impl(PyObject *module, gid_t gid)
8290 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8291 {
8292     if (setgid(gid) < 0)
8293         return posix_error();
8294     Py_RETURN_NONE;
8295 }
8296 #endif /* HAVE_SETGID */
8297 
8298 
8299 #ifdef HAVE_SETGROUPS
8300 /*[clinic input]
8301 os.setgroups
8302 
8303     groups: object
8304     /
8305 
8306 Set the groups of the current process to list.
8307 [clinic start generated code]*/
8308 
8309 static PyObject *
os_setgroups(PyObject *module, PyObject *groups)8310 os_setgroups(PyObject *module, PyObject *groups)
8311 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8312 {
8313     if (!PySequence_Check(groups)) {
8314         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8315         return NULL;
8316     }
8317     Py_ssize_t len = PySequence_Size(groups);
8318     if (len < 0) {
8319         return NULL;
8320     }
8321     if (len > MAX_GROUPS) {
8322         PyErr_SetString(PyExc_ValueError, "too many groups");
8323         return NULL;
8324     }
8325 
8326     gid_t *grouplist = PyMem_New(gid_t, len);
8327     for (Py_ssize_t i = 0; i < len; i++) {
8328         PyObject *elem;
8329         elem = PySequence_GetItem(groups, i);
8330         if (!elem) {
8331             PyMem_Free(grouplist);
8332             return NULL;
8333         }
8334         if (!PyLong_Check(elem)) {
8335             PyErr_SetString(PyExc_TypeError,
8336                             "groups must be integers");
8337             Py_DECREF(elem);
8338             PyMem_Free(grouplist);
8339             return NULL;
8340         } else {
8341             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8342                 Py_DECREF(elem);
8343                 PyMem_Free(grouplist);
8344                 return NULL;
8345             }
8346         }
8347         Py_DECREF(elem);
8348     }
8349 
8350     if (setgroups(len, grouplist) < 0) {
8351         PyMem_Free(grouplist);
8352         return posix_error();
8353     }
8354     PyMem_Free(grouplist);
8355     Py_RETURN_NONE;
8356 }
8357 #endif /* HAVE_SETGROUPS */
8358 
8359 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8360 static PyObject *
wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)8361 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8362 {
8363     PyObject *result;
8364     PyObject *struct_rusage;
8365 
8366     if (pid == -1)
8367         return posix_error();
8368 
8369     // If wait succeeded but no child was ready to report status, ru will not
8370     // have been populated.
8371     if (pid == 0) {
8372         memset(ru, 0, sizeof(*ru));
8373     }
8374 
8375     PyObject *m = PyImport_ImportModule("resource");
8376     if (m == NULL)
8377         return NULL;
8378     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8379     Py_DECREF(m);
8380     if (struct_rusage == NULL)
8381         return NULL;
8382 
8383     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8384     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8385     Py_DECREF(struct_rusage);
8386     if (!result)
8387         return NULL;
8388 
8389 #ifndef doubletime
8390 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8391 #endif
8392 
8393     PyStructSequence_SET_ITEM(result, 0,
8394                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8395     PyStructSequence_SET_ITEM(result, 1,
8396                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8397 #define SET_INT(result, index, value)\
8398         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8399     SET_INT(result, 2, ru->ru_maxrss);
8400     SET_INT(result, 3, ru->ru_ixrss);
8401     SET_INT(result, 4, ru->ru_idrss);
8402     SET_INT(result, 5, ru->ru_isrss);
8403     SET_INT(result, 6, ru->ru_minflt);
8404     SET_INT(result, 7, ru->ru_majflt);
8405     SET_INT(result, 8, ru->ru_nswap);
8406     SET_INT(result, 9, ru->ru_inblock);
8407     SET_INT(result, 10, ru->ru_oublock);
8408     SET_INT(result, 11, ru->ru_msgsnd);
8409     SET_INT(result, 12, ru->ru_msgrcv);
8410     SET_INT(result, 13, ru->ru_nsignals);
8411     SET_INT(result, 14, ru->ru_nvcsw);
8412     SET_INT(result, 15, ru->ru_nivcsw);
8413 #undef SET_INT
8414 
8415     if (PyErr_Occurred()) {
8416         Py_DECREF(result);
8417         return NULL;
8418     }
8419 
8420     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8421 }
8422 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8423 
8424 
8425 #ifdef HAVE_WAIT3
8426 /*[clinic input]
8427 os.wait3
8428 
8429     options: int
8430 Wait for completion of a child process.
8431 
8432 Returns a tuple of information about the child process:
8433   (pid, status, rusage)
8434 [clinic start generated code]*/
8435 
8436 static PyObject *
os_wait3_impl(PyObject *module, int options)8437 os_wait3_impl(PyObject *module, int options)
8438 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8439 {
8440     pid_t pid;
8441     struct rusage ru;
8442     int async_err = 0;
8443     WAIT_TYPE status;
8444     WAIT_STATUS_INT(status) = 0;
8445 
8446     do {
8447         Py_BEGIN_ALLOW_THREADS
8448         pid = wait3(&status, options, &ru);
8449         Py_END_ALLOW_THREADS
8450     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8451     if (pid < 0)
8452         return (!async_err) ? posix_error() : NULL;
8453 
8454     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8455 }
8456 #endif /* HAVE_WAIT3 */
8457 
8458 
8459 #ifdef HAVE_WAIT4
8460 /*[clinic input]
8461 
8462 os.wait4
8463 
8464     pid: pid_t
8465     options: int
8466 
8467 Wait for completion of a specific child process.
8468 
8469 Returns a tuple of information about the child process:
8470   (pid, status, rusage)
8471 [clinic start generated code]*/
8472 
8473 static PyObject *
os_wait4_impl(PyObject *module, pid_t pid, int options)8474 os_wait4_impl(PyObject *module, pid_t pid, int options)
8475 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8476 {
8477     pid_t res;
8478     struct rusage ru;
8479     int async_err = 0;
8480     WAIT_TYPE status;
8481     WAIT_STATUS_INT(status) = 0;
8482 
8483     do {
8484         Py_BEGIN_ALLOW_THREADS
8485         res = wait4(pid, &status, options, &ru);
8486         Py_END_ALLOW_THREADS
8487     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8488     if (res < 0)
8489         return (!async_err) ? posix_error() : NULL;
8490 
8491     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8492 }
8493 #endif /* HAVE_WAIT4 */
8494 
8495 
8496 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8497 /*[clinic input]
8498 os.waitid
8499 
8500     idtype: idtype_t
8501         Must be one of be P_PID, P_PGID or P_ALL.
8502     id: id_t
8503         The id to wait on.
8504     options: int
8505         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8506         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8507     /
8508 
8509 Returns the result of waiting for a process or processes.
8510 
8511 Returns either waitid_result or None if WNOHANG is specified and there are
8512 no children in a waitable state.
8513 [clinic start generated code]*/
8514 
8515 static PyObject *
os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)8516 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8517 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8518 {
8519     PyObject *result;
8520     int res;
8521     int async_err = 0;
8522     siginfo_t si;
8523     si.si_pid = 0;
8524 
8525     do {
8526         Py_BEGIN_ALLOW_THREADS
8527         res = waitid(idtype, id, &si, options);
8528         Py_END_ALLOW_THREADS
8529     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8530     if (res < 0)
8531         return (!async_err) ? posix_error() : NULL;
8532 
8533     if (si.si_pid == 0)
8534         Py_RETURN_NONE;
8535 
8536     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8537     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8538     if (!result)
8539         return NULL;
8540 
8541     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8542     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8543     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8544     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8545     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8546     if (PyErr_Occurred()) {
8547         Py_DECREF(result);
8548         return NULL;
8549     }
8550 
8551     return result;
8552 }
8553 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8554 
8555 
8556 #if defined(HAVE_WAITPID)
8557 /*[clinic input]
8558 os.waitpid
8559     pid: pid_t
8560     options: int
8561     /
8562 
8563 Wait for completion of a given child process.
8564 
8565 Returns a tuple of information regarding the child process:
8566     (pid, status)
8567 
8568 The options argument is ignored on Windows.
8569 [clinic start generated code]*/
8570 
8571 static PyObject *
os_waitpid_impl(PyObject *module, pid_t pid, int options)8572 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8573 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8574 {
8575     pid_t res;
8576     int async_err = 0;
8577     WAIT_TYPE status;
8578     WAIT_STATUS_INT(status) = 0;
8579 
8580     do {
8581         Py_BEGIN_ALLOW_THREADS
8582         res = waitpid(pid, &status, options);
8583         Py_END_ALLOW_THREADS
8584     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8585     if (res < 0)
8586         return (!async_err) ? posix_error() : NULL;
8587 
8588     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8589 }
8590 #elif defined(HAVE_CWAIT)
8591 /* MS C has a variant of waitpid() that's usable for most purposes. */
8592 /*[clinic input]
8593 os.waitpid
8594     pid: intptr_t
8595     options: int
8596     /
8597 
8598 Wait for completion of a given process.
8599 
8600 Returns a tuple of information regarding the process:
8601     (pid, status << 8)
8602 
8603 The options argument is ignored on Windows.
8604 [clinic start generated code]*/
8605 
8606 static PyObject *
os_waitpid_impl(PyObject *module, intptr_t pid, int options)8607 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8608 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8609 {
8610     int status;
8611     intptr_t res;
8612     int async_err = 0;
8613 
8614     do {
8615         Py_BEGIN_ALLOW_THREADS
8616         _Py_BEGIN_SUPPRESS_IPH
8617         res = _cwait(&status, pid, options);
8618         _Py_END_SUPPRESS_IPH
8619         Py_END_ALLOW_THREADS
8620     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8621     if (res < 0)
8622         return (!async_err) ? posix_error() : NULL;
8623 
8624     unsigned long long ustatus = (unsigned int)status;
8625 
8626     /* shift the status left a byte so this is more like the POSIX waitpid */
8627     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8628 }
8629 #endif
8630 
8631 
8632 #ifdef HAVE_WAIT
8633 /*[clinic input]
8634 os.wait
8635 
8636 Wait for completion of a child process.
8637 
8638 Returns a tuple of information about the child process:
8639     (pid, status)
8640 [clinic start generated code]*/
8641 
8642 static PyObject *
os_wait_impl(PyObject *module)8643 os_wait_impl(PyObject *module)
8644 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8645 {
8646     pid_t pid;
8647     int async_err = 0;
8648     WAIT_TYPE status;
8649     WAIT_STATUS_INT(status) = 0;
8650 
8651     do {
8652         Py_BEGIN_ALLOW_THREADS
8653         pid = wait(&status);
8654         Py_END_ALLOW_THREADS
8655     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8656     if (pid < 0)
8657         return (!async_err) ? posix_error() : NULL;
8658 
8659     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8660 }
8661 #endif /* HAVE_WAIT */
8662 
8663 #if defined(__linux__) && defined(__NR_pidfd_open)
8664 /*[clinic input]
8665 os.pidfd_open
8666   pid: pid_t
8667   flags: unsigned_int = 0
8668 
8669 Return a file descriptor referring to the process *pid*.
8670 
8671 The descriptor can be used to perform process management without races and
8672 signals.
8673 [clinic start generated code]*/
8674 
8675 static PyObject *
os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)8676 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8677 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8678 {
8679     int fd = syscall(__NR_pidfd_open, pid, flags);
8680     if (fd < 0) {
8681         return posix_error();
8682     }
8683     return PyLong_FromLong(fd);
8684 }
8685 #endif
8686 
8687 
8688 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8689 /*[clinic input]
8690 os.readlink
8691 
8692     path: path_t
8693     *
8694     dir_fd: dir_fd(requires='readlinkat') = None
8695 
8696 Return a string representing the path to which the symbolic link points.
8697 
8698 If dir_fd is not None, it should be a file descriptor open to a directory,
8699 and path should be relative; path will then be relative to that directory.
8700 
8701 dir_fd may not be implemented on your platform.  If it is unavailable,
8702 using it will raise a NotImplementedError.
8703 [clinic start generated code]*/
8704 
8705 static PyObject *
os_readlink_impl(PyObject *module, path_t *path, int dir_fd)8706 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8707 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8708 {
8709 #if defined(HAVE_READLINK)
8710     char buffer[MAXPATHLEN+1];
8711     ssize_t length;
8712 #ifdef HAVE_READLINKAT
8713     int readlinkat_unavailable = 0;
8714 #endif
8715 
8716     Py_BEGIN_ALLOW_THREADS
8717 #ifdef HAVE_READLINKAT
8718     if (dir_fd != DEFAULT_DIR_FD) {
8719         if (HAVE_READLINKAT_RUNTIME) {
8720             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8721         } else {
8722             readlinkat_unavailable = 1;
8723         }
8724     } else
8725 #endif
8726         length = readlink(path->narrow, buffer, MAXPATHLEN);
8727     Py_END_ALLOW_THREADS
8728 
8729 #ifdef HAVE_READLINKAT
8730     if (readlinkat_unavailable) {
8731         argument_unavailable_error(NULL, "dir_fd");
8732         return NULL;
8733     }
8734 #endif
8735 
8736     if (length < 0) {
8737         return path_error(path);
8738     }
8739     buffer[length] = '\0';
8740 
8741     if (PyUnicode_Check(path->object))
8742         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8743     else
8744         return PyBytes_FromStringAndSize(buffer, length);
8745 #elif defined(MS_WINDOWS)
8746     DWORD n_bytes_returned;
8747     DWORD io_result = 0;
8748     HANDLE reparse_point_handle;
8749     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8750     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8751     PyObject *result = NULL;
8752 
8753     /* First get a handle to the reparse point */
8754     Py_BEGIN_ALLOW_THREADS
8755     reparse_point_handle = CreateFileW(
8756         path->wide,
8757         0,
8758         0,
8759         0,
8760         OPEN_EXISTING,
8761         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8762         0);
8763     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8764         /* New call DeviceIoControl to read the reparse point */
8765         io_result = DeviceIoControl(
8766             reparse_point_handle,
8767             FSCTL_GET_REPARSE_POINT,
8768             0, 0, /* in buffer */
8769             target_buffer, sizeof(target_buffer),
8770             &n_bytes_returned,
8771             0 /* we're not using OVERLAPPED_IO */
8772             );
8773         CloseHandle(reparse_point_handle);
8774     }
8775     Py_END_ALLOW_THREADS
8776 
8777     if (io_result == 0) {
8778         return path_error(path);
8779     }
8780 
8781     wchar_t *name = NULL;
8782     Py_ssize_t nameLen = 0;
8783     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8784     {
8785         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8786                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8787         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8788     }
8789     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8790     {
8791         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8792                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8793         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8794     }
8795     else
8796     {
8797         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8798     }
8799     if (name) {
8800         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8801             /* Our buffer is mutable, so this is okay */
8802             name[1] = L'\\';
8803         }
8804         result = PyUnicode_FromWideChar(name, nameLen);
8805         if (result && path->narrow) {
8806             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8807         }
8808     }
8809     return result;
8810 #endif
8811 }
8812 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8813 
8814 #if defined(MS_WINDOWS)
8815 
8816 /* Remove the last portion of the path - return 0 on success */
8817 static int
_dirnameW(WCHAR *path)8818 _dirnameW(WCHAR *path)
8819 {
8820     WCHAR *ptr;
8821     size_t length = wcsnlen_s(path, MAX_PATH);
8822     if (length == MAX_PATH) {
8823         return -1;
8824     }
8825 
8826     /* walk the path from the end until a backslash is encountered */
8827     for(ptr = path + length; ptr != path; ptr--) {
8828         if (*ptr == L'\\' || *ptr == L'/') {
8829             break;
8830         }
8831     }
8832     *ptr = 0;
8833     return 0;
8834 }
8835 
8836 #endif
8837 
8838 #ifdef HAVE_SYMLINK
8839 
8840 #if defined(MS_WINDOWS)
8841 
8842 /* Is this path absolute? */
8843 static int
_is_absW(const WCHAR *path)8844 _is_absW(const WCHAR *path)
8845 {
8846     return path[0] == L'\\' || path[0] == L'/' ||
8847         (path[0] && path[1] == L':');
8848 }
8849 
8850 /* join root and rest with a backslash - return 0 on success */
8851 static int
_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)8852 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8853 {
8854     if (_is_absW(rest)) {
8855         return wcscpy_s(dest_path, MAX_PATH, rest);
8856     }
8857 
8858     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8859         return -1;
8860     }
8861 
8862     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8863         return -1;
8864     }
8865 
8866     return wcscat_s(dest_path, MAX_PATH, rest);
8867 }
8868 
8869 /* Return True if the path at src relative to dest is a directory */
8870 static int
_check_dirW(LPCWSTR src, LPCWSTR dest)8871 _check_dirW(LPCWSTR src, LPCWSTR dest)
8872 {
8873     WIN32_FILE_ATTRIBUTE_DATA src_info;
8874     WCHAR dest_parent[MAX_PATH];
8875     WCHAR src_resolved[MAX_PATH] = L"";
8876 
8877     /* dest_parent = os.path.dirname(dest) */
8878     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8879         _dirnameW(dest_parent)) {
8880         return 0;
8881     }
8882     /* src_resolved = os.path.join(dest_parent, src) */
8883     if (_joinW(src_resolved, dest_parent, src)) {
8884         return 0;
8885     }
8886     return (
8887         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8888         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8889     );
8890 }
8891 #endif
8892 
8893 
8894 /*[clinic input]
8895 os.symlink
8896     src: path_t
8897     dst: path_t
8898     target_is_directory: bool = False
8899     *
8900     dir_fd: dir_fd(requires='symlinkat')=None
8901 
8902 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8903 
8904 Create a symbolic link pointing to src named dst.
8905 
8906 target_is_directory is required on Windows if the target is to be
8907   interpreted as a directory.  (On Windows, symlink requires
8908   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8909   target_is_directory is ignored on non-Windows platforms.
8910 
8911 If dir_fd is not None, it should be a file descriptor open to a directory,
8912   and path should be relative; path will then be relative to that directory.
8913 dir_fd may not be implemented on your platform.
8914   If it is unavailable, using it will raise a NotImplementedError.
8915 
8916 [clinic start generated code]*/
8917 
8918 static PyObject *
os_symlink_impl(PyObject *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd)8919 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8920                 int target_is_directory, int dir_fd)
8921 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8922 {
8923 #ifdef MS_WINDOWS
8924     DWORD result;
8925     DWORD flags = 0;
8926 
8927     /* Assumed true, set to false if detected to not be available. */
8928     static int windows_has_symlink_unprivileged_flag = TRUE;
8929 #else
8930     int result;
8931 #ifdef HAVE_SYMLINKAT
8932     int symlinkat_unavailable = 0;
8933 #endif
8934 #endif
8935 
8936     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8937                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8938         return NULL;
8939     }
8940 
8941 #ifdef MS_WINDOWS
8942 
8943     if (windows_has_symlink_unprivileged_flag) {
8944         /* Allow non-admin symlinks if system allows it. */
8945         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8946     }
8947 
8948     Py_BEGIN_ALLOW_THREADS
8949     _Py_BEGIN_SUPPRESS_IPH
8950     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8951     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8952         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8953     }
8954 
8955     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8956     _Py_END_SUPPRESS_IPH
8957     Py_END_ALLOW_THREADS
8958 
8959     if (windows_has_symlink_unprivileged_flag && !result &&
8960         ERROR_INVALID_PARAMETER == GetLastError()) {
8961 
8962         Py_BEGIN_ALLOW_THREADS
8963         _Py_BEGIN_SUPPRESS_IPH
8964         /* This error might be caused by
8965         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8966         Try again, and update windows_has_symlink_unprivileged_flag if we
8967         are successful this time.
8968 
8969         NOTE: There is a risk of a race condition here if there are other
8970         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8971         another process (or thread) changes that condition in between our
8972         calls to CreateSymbolicLink.
8973         */
8974         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8975         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8976         _Py_END_SUPPRESS_IPH
8977         Py_END_ALLOW_THREADS
8978 
8979         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8980             windows_has_symlink_unprivileged_flag = FALSE;
8981         }
8982     }
8983 
8984     if (!result)
8985         return path_error2(src, dst);
8986 
8987 #else
8988 
8989     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8990         PyErr_SetString(PyExc_ValueError,
8991             "symlink: src and dst must be the same type");
8992         return NULL;
8993     }
8994 
8995     Py_BEGIN_ALLOW_THREADS
8996 #ifdef HAVE_SYMLINKAT
8997     if (dir_fd != DEFAULT_DIR_FD) {
8998         if (HAVE_SYMLINKAT_RUNTIME) {
8999             result = symlinkat(src->narrow, dir_fd, dst->narrow);
9000         } else {
9001             symlinkat_unavailable = 1;
9002         }
9003     } else
9004 #endif
9005         result = symlink(src->narrow, dst->narrow);
9006     Py_END_ALLOW_THREADS
9007 
9008 #ifdef HAVE_SYMLINKAT
9009     if (symlinkat_unavailable) {
9010           argument_unavailable_error(NULL, "dir_fd");
9011           return NULL;
9012     }
9013 #endif
9014 
9015     if (result)
9016         return path_error2(src, dst);
9017 #endif
9018 
9019     Py_RETURN_NONE;
9020 }
9021 #endif /* HAVE_SYMLINK */
9022 
9023 
9024 
9025 
9026 static PyStructSequence_Field times_result_fields[] = {
9027     {"user",    "user time"},
9028     {"system",   "system time"},
9029     {"children_user",    "user time of children"},
9030     {"children_system",    "system time of children"},
9031     {"elapsed",    "elapsed time since an arbitrary point in the past"},
9032     {NULL}
9033 };
9034 
9035 PyDoc_STRVAR(times_result__doc__,
9036 "times_result: Result from os.times().\n\n\
9037 This object may be accessed either as a tuple of\n\
9038   (user, system, children_user, children_system, elapsed),\n\
9039 or via the attributes user, system, children_user, children_system,\n\
9040 and elapsed.\n\
9041 \n\
9042 See os.times for more information.");
9043 
9044 static PyStructSequence_Desc times_result_desc = {
9045     "times_result", /* name */
9046     times_result__doc__, /* doc */
9047     times_result_fields,
9048     5
9049 };
9050 
9051 #ifdef MS_WINDOWS
9052 #define HAVE_TIMES  /* mandatory, for the method table */
9053 #endif
9054 
9055 #ifdef HAVE_TIMES
9056 
9057 static PyObject *
build_times_result(PyObject *module, double user, double system, double children_user, double children_system, double elapsed)9058 build_times_result(PyObject *module, double user, double system,
9059     double children_user, double children_system,
9060     double elapsed)
9061 {
9062     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9063     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9064     if (value == NULL)
9065         return NULL;
9066 
9067 #define SET(i, field) \
9068     { \
9069     PyObject *o = PyFloat_FromDouble(field); \
9070     if (!o) { \
9071         Py_DECREF(value); \
9072         return NULL; \
9073     } \
9074     PyStructSequence_SET_ITEM(value, i, o); \
9075     } \
9076 
9077     SET(0, user);
9078     SET(1, system);
9079     SET(2, children_user);
9080     SET(3, children_system);
9081     SET(4, elapsed);
9082 
9083 #undef SET
9084 
9085     return value;
9086 }
9087 
9088 
9089 #ifndef MS_WINDOWS
9090 #define NEED_TICKS_PER_SECOND
9091 static long ticks_per_second = -1;
9092 #endif /* MS_WINDOWS */
9093 
9094 /*[clinic input]
9095 os.times
9096 
9097 Return a collection containing process timing information.
9098 
9099 The object returned behaves like a named tuple with these fields:
9100   (utime, stime, cutime, cstime, elapsed_time)
9101 All fields are floating point numbers.
9102 [clinic start generated code]*/
9103 
9104 static PyObject *
os_times_impl(PyObject *module)9105 os_times_impl(PyObject *module)
9106 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9107 #ifdef MS_WINDOWS
9108 {
9109     FILETIME create, exit, kernel, user;
9110     HANDLE hProc;
9111     hProc = GetCurrentProcess();
9112     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9113     /* The fields of a FILETIME structure are the hi and lo part
9114        of a 64-bit value expressed in 100 nanosecond units.
9115        1e7 is one second in such units; 1e-7 the inverse.
9116        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9117     */
9118     return build_times_result(module,
9119         (double)(user.dwHighDateTime*429.4967296 +
9120                  user.dwLowDateTime*1e-7),
9121         (double)(kernel.dwHighDateTime*429.4967296 +
9122                  kernel.dwLowDateTime*1e-7),
9123         (double)0,
9124         (double)0,
9125         (double)0);
9126 }
9127 #else /* MS_WINDOWS */
9128 {
9129 
9130 
9131     struct tms t;
9132     clock_t c;
9133     errno = 0;
9134     c = times(&t);
9135     if (c == (clock_t) -1)
9136         return posix_error();
9137     return build_times_result(module,
9138                          (double)t.tms_utime / ticks_per_second,
9139                          (double)t.tms_stime / ticks_per_second,
9140                          (double)t.tms_cutime / ticks_per_second,
9141                          (double)t.tms_cstime / ticks_per_second,
9142                          (double)c / ticks_per_second);
9143 }
9144 #endif /* MS_WINDOWS */
9145 #endif /* HAVE_TIMES */
9146 
9147 
9148 #ifdef HAVE_GETSID
9149 /*[clinic input]
9150 os.getsid
9151 
9152     pid: pid_t
9153     /
9154 
9155 Call the system call getsid(pid) and return the result.
9156 [clinic start generated code]*/
9157 
9158 static PyObject *
os_getsid_impl(PyObject *module, pid_t pid)9159 os_getsid_impl(PyObject *module, pid_t pid)
9160 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9161 {
9162     int sid;
9163     sid = getsid(pid);
9164     if (sid < 0)
9165         return posix_error();
9166     return PyLong_FromLong((long)sid);
9167 }
9168 #endif /* HAVE_GETSID */
9169 
9170 
9171 #ifdef HAVE_SETSID
9172 /*[clinic input]
9173 os.setsid
9174 
9175 Call the system call setsid().
9176 [clinic start generated code]*/
9177 
9178 static PyObject *
os_setsid_impl(PyObject *module)9179 os_setsid_impl(PyObject *module)
9180 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9181 {
9182     if (setsid() < 0)
9183         return posix_error();
9184     Py_RETURN_NONE;
9185 }
9186 #endif /* HAVE_SETSID */
9187 
9188 
9189 #ifdef HAVE_SETPGID
9190 /*[clinic input]
9191 os.setpgid
9192 
9193     pid: pid_t
9194     pgrp: pid_t
9195     /
9196 
9197 Call the system call setpgid(pid, pgrp).
9198 [clinic start generated code]*/
9199 
9200 static PyObject *
os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)9201 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9202 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9203 {
9204     if (setpgid(pid, pgrp) < 0)
9205         return posix_error();
9206     Py_RETURN_NONE;
9207 }
9208 #endif /* HAVE_SETPGID */
9209 
9210 
9211 #ifdef HAVE_TCGETPGRP
9212 /*[clinic input]
9213 os.tcgetpgrp
9214 
9215     fd: int
9216     /
9217 
9218 Return the process group associated with the terminal specified by fd.
9219 [clinic start generated code]*/
9220 
9221 static PyObject *
os_tcgetpgrp_impl(PyObject *module, int fd)9222 os_tcgetpgrp_impl(PyObject *module, int fd)
9223 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9224 {
9225     pid_t pgid = tcgetpgrp(fd);
9226     if (pgid < 0)
9227         return posix_error();
9228     return PyLong_FromPid(pgid);
9229 }
9230 #endif /* HAVE_TCGETPGRP */
9231 
9232 
9233 #ifdef HAVE_TCSETPGRP
9234 /*[clinic input]
9235 os.tcsetpgrp
9236 
9237     fd: int
9238     pgid: pid_t
9239     /
9240 
9241 Set the process group associated with the terminal specified by fd.
9242 [clinic start generated code]*/
9243 
9244 static PyObject *
os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)9245 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9246 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9247 {
9248     if (tcsetpgrp(fd, pgid) < 0)
9249         return posix_error();
9250     Py_RETURN_NONE;
9251 }
9252 #endif /* HAVE_TCSETPGRP */
9253 
9254 /* Functions acting on file descriptors */
9255 
9256 #ifdef O_CLOEXEC
9257 extern int _Py_open_cloexec_works;
9258 #endif
9259 
9260 
9261 /*[clinic input]
9262 os.open -> int
9263     path: path_t
9264     flags: int
9265     mode: int = 0o777
9266     *
9267     dir_fd: dir_fd(requires='openat') = None
9268 
9269 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9270 
9271 Open a file for low level IO.  Returns a file descriptor (integer).
9272 
9273 If dir_fd is not None, it should be a file descriptor open to a directory,
9274   and path should be relative; path will then be relative to that directory.
9275 dir_fd may not be implemented on your platform.
9276   If it is unavailable, using it will raise a NotImplementedError.
9277 [clinic start generated code]*/
9278 
9279 static int
os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)9280 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9281 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9282 {
9283     int fd;
9284     int async_err = 0;
9285 #ifdef HAVE_OPENAT
9286     int openat_unavailable = 0;
9287 #endif
9288 
9289 #ifdef O_CLOEXEC
9290     int *atomic_flag_works = &_Py_open_cloexec_works;
9291 #elif !defined(MS_WINDOWS)
9292     int *atomic_flag_works = NULL;
9293 #endif
9294 
9295 #ifdef MS_WINDOWS
9296     flags |= O_NOINHERIT;
9297 #elif defined(O_CLOEXEC)
9298     flags |= O_CLOEXEC;
9299 #endif
9300 
9301     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9302         return -1;
9303     }
9304 
9305     _Py_BEGIN_SUPPRESS_IPH
9306     do {
9307         Py_BEGIN_ALLOW_THREADS
9308 #ifdef MS_WINDOWS
9309         fd = _wopen(path->wide, flags, mode);
9310 #else
9311 #ifdef HAVE_OPENAT
9312         if (dir_fd != DEFAULT_DIR_FD) {
9313             if (HAVE_OPENAT_RUNTIME) {
9314                 fd = openat(dir_fd, path->narrow, flags, mode);
9315 
9316             } else {
9317                 openat_unavailable = 1;
9318                 fd = -1;
9319             }
9320         } else
9321 #endif /* HAVE_OPENAT */
9322             fd = open(path->narrow, flags, mode);
9323 #endif /* !MS_WINDOWS */
9324         Py_END_ALLOW_THREADS
9325     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9326     _Py_END_SUPPRESS_IPH
9327 
9328 #ifdef HAVE_OPENAT
9329     if (openat_unavailable) {
9330         argument_unavailable_error(NULL, "dir_fd");
9331         return -1;
9332     }
9333 #endif
9334 
9335     if (fd < 0) {
9336         if (!async_err)
9337             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9338         return -1;
9339     }
9340 
9341 #ifndef MS_WINDOWS
9342     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9343         close(fd);
9344         return -1;
9345     }
9346 #endif
9347 
9348     return fd;
9349 }
9350 
9351 
9352 /*[clinic input]
9353 os.close
9354 
9355     fd: int
9356 
9357 Close a file descriptor.
9358 [clinic start generated code]*/
9359 
9360 static PyObject *
os_close_impl(PyObject *module, int fd)9361 os_close_impl(PyObject *module, int fd)
9362 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9363 {
9364     int res;
9365     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9366      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9367      * for more details.
9368      */
9369     Py_BEGIN_ALLOW_THREADS
9370     _Py_BEGIN_SUPPRESS_IPH
9371     res = close(fd);
9372     _Py_END_SUPPRESS_IPH
9373     Py_END_ALLOW_THREADS
9374     if (res < 0)
9375         return posix_error();
9376     Py_RETURN_NONE;
9377 }
9378 
9379 /*[clinic input]
9380 os.closerange
9381 
9382     fd_low: int
9383     fd_high: int
9384     /
9385 
9386 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9387 [clinic start generated code]*/
9388 
9389 static PyObject *
os_closerange_impl(PyObject *module, int fd_low, int fd_high)9390 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9391 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9392 {
9393     Py_BEGIN_ALLOW_THREADS
9394     _Py_closerange(fd_low, fd_high - 1);
9395     Py_END_ALLOW_THREADS
9396     Py_RETURN_NONE;
9397 }
9398 
9399 
9400 /*[clinic input]
9401 os.dup -> int
9402 
9403     fd: int
9404     /
9405 
9406 Return a duplicate of a file descriptor.
9407 [clinic start generated code]*/
9408 
9409 static int
os_dup_impl(PyObject *module, int fd)9410 os_dup_impl(PyObject *module, int fd)
9411 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9412 {
9413     return _Py_dup(fd);
9414 }
9415 
9416 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
9417 // dup2.c provides working dup2() if and only if F_DUPFD is available.
9418 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
9419 /*[clinic input]
9420 os.dup2 -> int
9421     fd: int
9422     fd2: int
9423     inheritable: bool=True
9424 
9425 Duplicate file descriptor.
9426 [clinic start generated code]*/
9427 
9428 static int
os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)9429 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9430 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9431 {
9432     int res = 0;
9433 #if defined(HAVE_DUP3) && \
9434     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9435     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9436     static int dup3_works = -1;
9437 #endif
9438 
9439     /* dup2() can fail with EINTR if the target FD is already open, because it
9440      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9441      * upon close(), and therefore below.
9442      */
9443 #ifdef MS_WINDOWS
9444     Py_BEGIN_ALLOW_THREADS
9445     _Py_BEGIN_SUPPRESS_IPH
9446     res = dup2(fd, fd2);
9447     _Py_END_SUPPRESS_IPH
9448     Py_END_ALLOW_THREADS
9449     if (res < 0) {
9450         posix_error();
9451         return -1;
9452     }
9453     res = fd2; // msvcrt dup2 returns 0 on success.
9454 
9455     /* Character files like console cannot be make non-inheritable */
9456     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9457         close(fd2);
9458         return -1;
9459     }
9460 
9461 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9462     Py_BEGIN_ALLOW_THREADS
9463     if (!inheritable)
9464         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9465     else
9466         res = dup2(fd, fd2);
9467     Py_END_ALLOW_THREADS
9468     if (res < 0) {
9469         posix_error();
9470         return -1;
9471     }
9472 
9473 #else
9474 
9475 #ifdef HAVE_DUP3
9476     if (!inheritable && dup3_works != 0) {
9477         Py_BEGIN_ALLOW_THREADS
9478         res = dup3(fd, fd2, O_CLOEXEC);
9479         Py_END_ALLOW_THREADS
9480         if (res < 0) {
9481             if (dup3_works == -1)
9482                 dup3_works = (errno != ENOSYS);
9483             if (dup3_works) {
9484                 posix_error();
9485                 return -1;
9486             }
9487         }
9488     }
9489 
9490     if (inheritable || dup3_works == 0)
9491     {
9492 #endif
9493         Py_BEGIN_ALLOW_THREADS
9494         res = dup2(fd, fd2);
9495         Py_END_ALLOW_THREADS
9496         if (res < 0) {
9497             posix_error();
9498             return -1;
9499         }
9500 
9501         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9502             close(fd2);
9503             return -1;
9504         }
9505 #ifdef HAVE_DUP3
9506     }
9507 #endif
9508 
9509 #endif
9510 
9511     return res;
9512 }
9513 #endif
9514 
9515 
9516 #ifdef HAVE_LOCKF
9517 /*[clinic input]
9518 os.lockf
9519 
9520     fd: int
9521         An open file descriptor.
9522     command: int
9523         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9524     length: Py_off_t
9525         The number of bytes to lock, starting at the current position.
9526     /
9527 
9528 Apply, test or remove a POSIX lock on an open file descriptor.
9529 
9530 [clinic start generated code]*/
9531 
9532 static PyObject *
os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)9533 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9534 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9535 {
9536     int res;
9537 
9538     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9539         return NULL;
9540     }
9541 
9542     Py_BEGIN_ALLOW_THREADS
9543     res = lockf(fd, command, length);
9544     Py_END_ALLOW_THREADS
9545 
9546     if (res < 0)
9547         return posix_error();
9548 
9549     Py_RETURN_NONE;
9550 }
9551 #endif /* HAVE_LOCKF */
9552 
9553 
9554 /*[clinic input]
9555 os.lseek -> Py_off_t
9556 
9557     fd: int
9558     position: Py_off_t
9559     how: int
9560     /
9561 
9562 Set the position of a file descriptor.  Return the new position.
9563 
9564 Return the new cursor position in number of bytes
9565 relative to the beginning of the file.
9566 [clinic start generated code]*/
9567 
9568 static Py_off_t
os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)9569 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9570 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9571 {
9572     Py_off_t result;
9573 
9574 #ifdef SEEK_SET
9575     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9576     switch (how) {
9577         case 0: how = SEEK_SET; break;
9578         case 1: how = SEEK_CUR; break;
9579         case 2: how = SEEK_END; break;
9580     }
9581 #endif /* SEEK_END */
9582 
9583     Py_BEGIN_ALLOW_THREADS
9584     _Py_BEGIN_SUPPRESS_IPH
9585 #ifdef MS_WINDOWS
9586     result = _lseeki64(fd, position, how);
9587 #else
9588     result = lseek(fd, position, how);
9589 #endif
9590     _Py_END_SUPPRESS_IPH
9591     Py_END_ALLOW_THREADS
9592     if (result < 0)
9593         posix_error();
9594 
9595     return result;
9596 }
9597 
9598 
9599 /*[clinic input]
9600 os.read
9601     fd: int
9602     length: Py_ssize_t
9603     /
9604 
9605 Read from a file descriptor.  Returns a bytes object.
9606 [clinic start generated code]*/
9607 
9608 static PyObject *
os_read_impl(PyObject *module, int fd, Py_ssize_t length)9609 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9610 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9611 {
9612     Py_ssize_t n;
9613     PyObject *buffer;
9614 
9615     if (length < 0) {
9616         errno = EINVAL;
9617         return posix_error();
9618     }
9619 
9620     length = Py_MIN(length, _PY_READ_MAX);
9621 
9622     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9623     if (buffer == NULL)
9624         return NULL;
9625 
9626     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9627     if (n == -1) {
9628         Py_DECREF(buffer);
9629         return NULL;
9630     }
9631 
9632     if (n != length)
9633         _PyBytes_Resize(&buffer, n);
9634 
9635     return buffer;
9636 }
9637 
9638 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9639                                 || defined(__APPLE__))) \
9640     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9641     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9642 static int
iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)9643 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9644 {
9645     Py_ssize_t i, j;
9646 
9647     *iov = PyMem_New(struct iovec, cnt);
9648     if (*iov == NULL) {
9649         PyErr_NoMemory();
9650         return -1;
9651     }
9652 
9653     *buf = PyMem_New(Py_buffer, cnt);
9654     if (*buf == NULL) {
9655         PyMem_Free(*iov);
9656         PyErr_NoMemory();
9657         return -1;
9658     }
9659 
9660     for (i = 0; i < cnt; i++) {
9661         PyObject *item = PySequence_GetItem(seq, i);
9662         if (item == NULL)
9663             goto fail;
9664         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9665             Py_DECREF(item);
9666             goto fail;
9667         }
9668         Py_DECREF(item);
9669         (*iov)[i].iov_base = (*buf)[i].buf;
9670         (*iov)[i].iov_len = (*buf)[i].len;
9671     }
9672     return 0;
9673 
9674 fail:
9675     PyMem_Free(*iov);
9676     for (j = 0; j < i; j++) {
9677         PyBuffer_Release(&(*buf)[j]);
9678     }
9679     PyMem_Free(*buf);
9680     return -1;
9681 }
9682 
9683 static void
iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)9684 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9685 {
9686     int i;
9687     PyMem_Free(iov);
9688     for (i = 0; i < cnt; i++) {
9689         PyBuffer_Release(&buf[i]);
9690     }
9691     PyMem_Free(buf);
9692 }
9693 #endif
9694 
9695 
9696 #ifdef HAVE_READV
9697 /*[clinic input]
9698 os.readv -> Py_ssize_t
9699 
9700     fd: int
9701     buffers: object
9702     /
9703 
9704 Read from a file descriptor fd into an iterable of buffers.
9705 
9706 The buffers should be mutable buffers accepting bytes.
9707 readv will transfer data into each buffer until it is full
9708 and then move on to the next buffer in the sequence to hold
9709 the rest of the data.
9710 
9711 readv returns the total number of bytes read,
9712 which may be less than the total capacity of all the buffers.
9713 [clinic start generated code]*/
9714 
9715 static Py_ssize_t
os_readv_impl(PyObject *module, int fd, PyObject *buffers)9716 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9717 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9718 {
9719     Py_ssize_t cnt, n;
9720     int async_err = 0;
9721     struct iovec *iov;
9722     Py_buffer *buf;
9723 
9724     if (!PySequence_Check(buffers)) {
9725         PyErr_SetString(PyExc_TypeError,
9726             "readv() arg 2 must be a sequence");
9727         return -1;
9728     }
9729 
9730     cnt = PySequence_Size(buffers);
9731     if (cnt < 0)
9732         return -1;
9733 
9734     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9735         return -1;
9736 
9737     do {
9738         Py_BEGIN_ALLOW_THREADS
9739         n = readv(fd, iov, cnt);
9740         Py_END_ALLOW_THREADS
9741     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9742 
9743     iov_cleanup(iov, buf, cnt);
9744     if (n < 0) {
9745         if (!async_err)
9746             posix_error();
9747         return -1;
9748     }
9749 
9750     return n;
9751 }
9752 #endif /* HAVE_READV */
9753 
9754 
9755 #ifdef HAVE_PREAD
9756 /*[clinic input]
9757 os.pread
9758 
9759     fd: int
9760     length: Py_ssize_t
9761     offset: Py_off_t
9762     /
9763 
9764 Read a number of bytes from a file descriptor starting at a particular offset.
9765 
9766 Read length bytes from file descriptor fd, starting at offset bytes from
9767 the beginning of the file.  The file offset remains unchanged.
9768 [clinic start generated code]*/
9769 
9770 static PyObject *
os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)9771 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9772 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9773 {
9774     Py_ssize_t n;
9775     int async_err = 0;
9776     PyObject *buffer;
9777 
9778     if (length < 0) {
9779         errno = EINVAL;
9780         return posix_error();
9781     }
9782     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9783     if (buffer == NULL)
9784         return NULL;
9785 
9786     do {
9787         Py_BEGIN_ALLOW_THREADS
9788         _Py_BEGIN_SUPPRESS_IPH
9789         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9790         _Py_END_SUPPRESS_IPH
9791         Py_END_ALLOW_THREADS
9792     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9793 
9794     if (n < 0) {
9795         Py_DECREF(buffer);
9796         return (!async_err) ? posix_error() : NULL;
9797     }
9798     if (n != length)
9799         _PyBytes_Resize(&buffer, n);
9800     return buffer;
9801 }
9802 #endif /* HAVE_PREAD */
9803 
9804 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9805 /*[clinic input]
9806 os.preadv -> Py_ssize_t
9807 
9808     fd: int
9809     buffers: object
9810     offset: Py_off_t
9811     flags: int = 0
9812     /
9813 
9814 Reads from a file descriptor into a number of mutable bytes-like objects.
9815 
9816 Combines the functionality of readv() and pread(). As readv(), it will
9817 transfer data into each buffer until it is full and then move on to the next
9818 buffer in the sequence to hold the rest of the data. Its fourth argument,
9819 specifies the file offset at which the input operation is to be performed. It
9820 will return the total number of bytes read (which can be less than the total
9821 capacity of all the objects).
9822 
9823 The flags argument contains a bitwise OR of zero or more of the following flags:
9824 
9825 - RWF_HIPRI
9826 - RWF_NOWAIT
9827 
9828 Using non-zero flags requires Linux 4.6 or newer.
9829 [clinic start generated code]*/
9830 
9831 static Py_ssize_t
os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags)9832 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9833                int flags)
9834 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9835 {
9836     Py_ssize_t cnt, n;
9837     int async_err = 0;
9838     struct iovec *iov;
9839     Py_buffer *buf;
9840 
9841     if (!PySequence_Check(buffers)) {
9842         PyErr_SetString(PyExc_TypeError,
9843             "preadv2() arg 2 must be a sequence");
9844         return -1;
9845     }
9846 
9847     cnt = PySequence_Size(buffers);
9848     if (cnt < 0) {
9849         return -1;
9850     }
9851 
9852 #ifndef HAVE_PREADV2
9853     if(flags != 0) {
9854         argument_unavailable_error("preadv2", "flags");
9855         return -1;
9856     }
9857 #endif
9858 
9859     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9860         return -1;
9861     }
9862 #ifdef HAVE_PREADV2
9863     do {
9864         Py_BEGIN_ALLOW_THREADS
9865         _Py_BEGIN_SUPPRESS_IPH
9866         n = preadv2(fd, iov, cnt, offset, flags);
9867         _Py_END_SUPPRESS_IPH
9868         Py_END_ALLOW_THREADS
9869     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9870 #else
9871     do {
9872 #if defined(__APPLE__) && defined(__clang__)
9873 /* This entire function will be removed from the module dict when the API
9874  * is not available.
9875  */
9876 #pragma clang diagnostic push
9877 #pragma clang diagnostic ignored "-Wunguarded-availability"
9878 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9879 #endif
9880         Py_BEGIN_ALLOW_THREADS
9881         _Py_BEGIN_SUPPRESS_IPH
9882         n = preadv(fd, iov, cnt, offset);
9883         _Py_END_SUPPRESS_IPH
9884         Py_END_ALLOW_THREADS
9885     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9886 
9887 #if defined(__APPLE__) && defined(__clang__)
9888 #pragma clang diagnostic pop
9889 #endif
9890 
9891 #endif
9892 
9893     iov_cleanup(iov, buf, cnt);
9894     if (n < 0) {
9895         if (!async_err) {
9896             posix_error();
9897         }
9898         return -1;
9899     }
9900 
9901     return n;
9902 }
9903 #endif /* HAVE_PREADV */
9904 
9905 
9906 /*[clinic input]
9907 os.write -> Py_ssize_t
9908 
9909     fd: int
9910     data: Py_buffer
9911     /
9912 
9913 Write a bytes object to a file descriptor.
9914 [clinic start generated code]*/
9915 
9916 static Py_ssize_t
os_write_impl(PyObject *module, int fd, Py_buffer *data)9917 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9918 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9919 {
9920     return _Py_write(fd, data->buf, data->len);
9921 }
9922 
9923 #ifdef HAVE_SENDFILE
9924 #ifdef __APPLE__
9925 /*[clinic input]
9926 os.sendfile
9927 
9928     out_fd: int
9929     in_fd: int
9930     offset: Py_off_t
9931     count as sbytes: Py_off_t
9932     headers: object(c_default="NULL") = ()
9933     trailers: object(c_default="NULL") = ()
9934     flags: int = 0
9935 
9936 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9937 [clinic start generated code]*/
9938 
9939 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)9940 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9941                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9942                  int flags)
9943 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9944 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9945 /*[clinic input]
9946 os.sendfile
9947 
9948     out_fd: int
9949     in_fd: int
9950     offset: Py_off_t
9951     count: Py_ssize_t
9952     headers: object(c_default="NULL") = ()
9953     trailers: object(c_default="NULL") = ()
9954     flags: int = 0
9955 
9956 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9957 [clinic start generated code]*/
9958 
9959 static PyObject *
9960 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9961                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9962                  int flags)
9963 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9964 #else
9965 /*[clinic input]
9966 os.sendfile
9967 
9968     out_fd: int
9969     in_fd: int
9970     offset as offobj: object
9971     count: Py_ssize_t
9972 
9973 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9974 [clinic start generated code]*/
9975 
9976 static PyObject *
9977 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9978                  Py_ssize_t count)
9979 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9980 #endif
9981 {
9982     Py_ssize_t ret;
9983     int async_err = 0;
9984 
9985 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9986 #ifndef __APPLE__
9987     off_t sbytes;
9988 #endif
9989     Py_buffer *hbuf, *tbuf;
9990     struct sf_hdtr sf;
9991 
9992     sf.headers = NULL;
9993     sf.trailers = NULL;
9994 
9995     if (headers != NULL) {
9996         if (!PySequence_Check(headers)) {
9997             PyErr_SetString(PyExc_TypeError,
9998                 "sendfile() headers must be a sequence");
9999             return NULL;
10000         } else {
10001             Py_ssize_t i = PySequence_Size(headers);
10002             if (i < 0)
10003                 return NULL;
10004             if (i > INT_MAX) {
10005                 PyErr_SetString(PyExc_OverflowError,
10006                     "sendfile() header is too large");
10007                 return NULL;
10008             }
10009             if (i > 0) {
10010                 sf.hdr_cnt = (int)i;
10011                 if (iov_setup(&(sf.headers), &hbuf,
10012                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
10013                     return NULL;
10014 #ifdef __APPLE__
10015                 for (i = 0; i < sf.hdr_cnt; i++) {
10016                     Py_ssize_t blen = sf.headers[i].iov_len;
10017 # define OFF_T_MAX 0x7fffffffffffffff
10018                     if (sbytes >= OFF_T_MAX - blen) {
10019                         PyErr_SetString(PyExc_OverflowError,
10020                             "sendfile() header is too large");
10021                         return NULL;
10022                     }
10023                     sbytes += blen;
10024                 }
10025 #endif
10026             }
10027         }
10028     }
10029     if (trailers != NULL) {
10030         if (!PySequence_Check(trailers)) {
10031             PyErr_SetString(PyExc_TypeError,
10032                 "sendfile() trailers must be a sequence");
10033             return NULL;
10034         } else {
10035             Py_ssize_t i = PySequence_Size(trailers);
10036             if (i < 0)
10037                 return NULL;
10038             if (i > INT_MAX) {
10039                 PyErr_SetString(PyExc_OverflowError,
10040                     "sendfile() trailer is too large");
10041                 return NULL;
10042             }
10043             if (i > 0) {
10044                 sf.trl_cnt = (int)i;
10045                 if (iov_setup(&(sf.trailers), &tbuf,
10046                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10047                     return NULL;
10048             }
10049         }
10050     }
10051 
10052     _Py_BEGIN_SUPPRESS_IPH
10053     do {
10054         Py_BEGIN_ALLOW_THREADS
10055 #ifdef __APPLE__
10056         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10057 #else
10058         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10059 #endif
10060         Py_END_ALLOW_THREADS
10061     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10062     _Py_END_SUPPRESS_IPH
10063 
10064     if (sf.headers != NULL)
10065         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10066     if (sf.trailers != NULL)
10067         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10068 
10069     if (ret < 0) {
10070         if ((errno == EAGAIN) || (errno == EBUSY)) {
10071             if (sbytes != 0) {
10072                 // some data has been sent
10073                 goto done;
10074             }
10075             else {
10076                 // no data has been sent; upper application is supposed
10077                 // to retry on EAGAIN or EBUSY
10078                 return posix_error();
10079             }
10080         }
10081         return (!async_err) ? posix_error() : NULL;
10082     }
10083     goto done;
10084 
10085 done:
10086     #if !defined(HAVE_LARGEFILE_SUPPORT)
10087         return Py_BuildValue("l", sbytes);
10088     #else
10089         return Py_BuildValue("L", sbytes);
10090     #endif
10091 
10092 #else
10093 #ifdef __linux__
10094     if (offobj == Py_None) {
10095         do {
10096             Py_BEGIN_ALLOW_THREADS
10097             ret = sendfile(out_fd, in_fd, NULL, count);
10098             Py_END_ALLOW_THREADS
10099         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10100         if (ret < 0)
10101             return (!async_err) ? posix_error() : NULL;
10102         return Py_BuildValue("n", ret);
10103     }
10104 #endif
10105     off_t offset;
10106     if (!Py_off_t_converter(offobj, &offset))
10107         return NULL;
10108 
10109 #if defined(__sun) && defined(__SVR4)
10110     // On Solaris, sendfile raises EINVAL rather than returning 0
10111     // when the offset is equal or bigger than the in_fd size.
10112     struct stat st;
10113 
10114     do {
10115         Py_BEGIN_ALLOW_THREADS
10116         ret = fstat(in_fd, &st);
10117         Py_END_ALLOW_THREADS
10118     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10119     if (ret < 0)
10120         return (!async_err) ? posix_error() : NULL;
10121 
10122     if (offset >= st.st_size) {
10123         return Py_BuildValue("i", 0);
10124     }
10125 
10126     // On illumos specifically sendfile() may perform a partial write but
10127     // return -1/an error (in one confirmed case the destination socket
10128     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10129     // code to check if the offset parameter was modified by sendfile().
10130     //
10131     // We need this variable to track said change.
10132     off_t original_offset = offset;
10133 #endif
10134 
10135     do {
10136         Py_BEGIN_ALLOW_THREADS
10137         ret = sendfile(out_fd, in_fd, &offset, count);
10138 #if defined(__sun) && defined(__SVR4)
10139         // This handles illumos-specific sendfile() partial write behavior,
10140         // see a comment above for more details.
10141         if (ret < 0 && offset != original_offset) {
10142             ret = offset - original_offset;
10143         }
10144 #endif
10145         Py_END_ALLOW_THREADS
10146     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10147     if (ret < 0)
10148         return (!async_err) ? posix_error() : NULL;
10149     return Py_BuildValue("n", ret);
10150 #endif
10151 }
10152 #endif /* HAVE_SENDFILE */
10153 
10154 
10155 #if defined(__APPLE__)
10156 /*[clinic input]
10157 os._fcopyfile
10158 
10159     in_fd: int
10160     out_fd: int
10161     flags: int
10162     /
10163 
10164 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10165 [clinic start generated code]*/
10166 
10167 static PyObject *
os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)10168 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10169 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10170 {
10171     int ret;
10172 
10173     Py_BEGIN_ALLOW_THREADS
10174     ret = fcopyfile(in_fd, out_fd, NULL, flags);
10175     Py_END_ALLOW_THREADS
10176     if (ret < 0)
10177         return posix_error();
10178     Py_RETURN_NONE;
10179 }
10180 #endif
10181 
10182 
10183 /*[clinic input]
10184 os.fstat
10185 
10186     fd : int
10187 
10188 Perform a stat system call on the given file descriptor.
10189 
10190 Like stat(), but for an open file descriptor.
10191 Equivalent to os.stat(fd).
10192 [clinic start generated code]*/
10193 
10194 static PyObject *
os_fstat_impl(PyObject *module, int fd)10195 os_fstat_impl(PyObject *module, int fd)
10196 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10197 {
10198     STRUCT_STAT st;
10199     int res;
10200     int async_err = 0;
10201 
10202     do {
10203         Py_BEGIN_ALLOW_THREADS
10204         res = FSTAT(fd, &st);
10205         Py_END_ALLOW_THREADS
10206     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10207     if (res != 0) {
10208 #ifdef MS_WINDOWS
10209         return PyErr_SetFromWindowsErr(0);
10210 #else
10211         return (!async_err) ? posix_error() : NULL;
10212 #endif
10213     }
10214 
10215     return _pystat_fromstructstat(module, &st);
10216 }
10217 
10218 
10219 /*[clinic input]
10220 os.isatty -> bool
10221     fd: int
10222     /
10223 
10224 Return True if the fd is connected to a terminal.
10225 
10226 Return True if the file descriptor is an open file descriptor
10227 connected to the slave end of a terminal.
10228 [clinic start generated code]*/
10229 
10230 static int
os_isatty_impl(PyObject *module, int fd)10231 os_isatty_impl(PyObject *module, int fd)
10232 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10233 {
10234     int return_value;
10235     Py_BEGIN_ALLOW_THREADS
10236     _Py_BEGIN_SUPPRESS_IPH
10237     return_value = isatty(fd);
10238     _Py_END_SUPPRESS_IPH
10239     Py_END_ALLOW_THREADS
10240     return return_value;
10241 }
10242 
10243 
10244 #ifdef HAVE_PIPE
10245 /*[clinic input]
10246 os.pipe
10247 
10248 Create a pipe.
10249 
10250 Returns a tuple of two file descriptors:
10251   (read_fd, write_fd)
10252 [clinic start generated code]*/
10253 
10254 static PyObject *
os_pipe_impl(PyObject *module)10255 os_pipe_impl(PyObject *module)
10256 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10257 {
10258     int fds[2];
10259 #ifdef MS_WINDOWS
10260     HANDLE read, write;
10261     SECURITY_ATTRIBUTES attr;
10262     BOOL ok;
10263 #else
10264     int res;
10265 #endif
10266 
10267 #ifdef MS_WINDOWS
10268     attr.nLength = sizeof(attr);
10269     attr.lpSecurityDescriptor = NULL;
10270     attr.bInheritHandle = FALSE;
10271 
10272     Py_BEGIN_ALLOW_THREADS
10273     ok = CreatePipe(&read, &write, &attr, 0);
10274     if (ok) {
10275         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10276         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10277         if (fds[0] == -1 || fds[1] == -1) {
10278             CloseHandle(read);
10279             CloseHandle(write);
10280             ok = 0;
10281         }
10282     }
10283     Py_END_ALLOW_THREADS
10284 
10285     if (!ok)
10286         return PyErr_SetFromWindowsErr(0);
10287 #else
10288 
10289 #ifdef HAVE_PIPE2
10290     Py_BEGIN_ALLOW_THREADS
10291     res = pipe2(fds, O_CLOEXEC);
10292     Py_END_ALLOW_THREADS
10293 
10294     if (res != 0 && errno == ENOSYS)
10295     {
10296 #endif
10297         Py_BEGIN_ALLOW_THREADS
10298         res = pipe(fds);
10299         Py_END_ALLOW_THREADS
10300 
10301         if (res == 0) {
10302             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10303                 close(fds[0]);
10304                 close(fds[1]);
10305                 return NULL;
10306             }
10307             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10308                 close(fds[0]);
10309                 close(fds[1]);
10310                 return NULL;
10311             }
10312         }
10313 #ifdef HAVE_PIPE2
10314     }
10315 #endif
10316 
10317     if (res != 0)
10318         return PyErr_SetFromErrno(PyExc_OSError);
10319 #endif /* !MS_WINDOWS */
10320     return Py_BuildValue("(ii)", fds[0], fds[1]);
10321 }
10322 #endif  /* HAVE_PIPE */
10323 
10324 
10325 #ifdef HAVE_PIPE2
10326 /*[clinic input]
10327 os.pipe2
10328 
10329     flags: int
10330     /
10331 
10332 Create a pipe with flags set atomically.
10333 
10334 Returns a tuple of two file descriptors:
10335   (read_fd, write_fd)
10336 
10337 flags can be constructed by ORing together one or more of these values:
10338 O_NONBLOCK, O_CLOEXEC.
10339 [clinic start generated code]*/
10340 
10341 static PyObject *
os_pipe2_impl(PyObject *module, int flags)10342 os_pipe2_impl(PyObject *module, int flags)
10343 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10344 {
10345     int fds[2];
10346     int res;
10347 
10348     res = pipe2(fds, flags);
10349     if (res != 0)
10350         return posix_error();
10351     return Py_BuildValue("(ii)", fds[0], fds[1]);
10352 }
10353 #endif /* HAVE_PIPE2 */
10354 
10355 
10356 #ifdef HAVE_WRITEV
10357 /*[clinic input]
10358 os.writev -> Py_ssize_t
10359     fd: int
10360     buffers: object
10361     /
10362 
10363 Iterate over buffers, and write the contents of each to a file descriptor.
10364 
10365 Returns the total number of bytes written.
10366 buffers must be a sequence of bytes-like objects.
10367 [clinic start generated code]*/
10368 
10369 static Py_ssize_t
os_writev_impl(PyObject *module, int fd, PyObject *buffers)10370 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10371 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10372 {
10373     Py_ssize_t cnt;
10374     Py_ssize_t result;
10375     int async_err = 0;
10376     struct iovec *iov;
10377     Py_buffer *buf;
10378 
10379     if (!PySequence_Check(buffers)) {
10380         PyErr_SetString(PyExc_TypeError,
10381             "writev() arg 2 must be a sequence");
10382         return -1;
10383     }
10384     cnt = PySequence_Size(buffers);
10385     if (cnt < 0)
10386         return -1;
10387 
10388     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10389         return -1;
10390     }
10391 
10392     do {
10393         Py_BEGIN_ALLOW_THREADS
10394         result = writev(fd, iov, cnt);
10395         Py_END_ALLOW_THREADS
10396     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10397 
10398     iov_cleanup(iov, buf, cnt);
10399     if (result < 0 && !async_err)
10400         posix_error();
10401 
10402     return result;
10403 }
10404 #endif /* HAVE_WRITEV */
10405 
10406 
10407 #ifdef HAVE_PWRITE
10408 /*[clinic input]
10409 os.pwrite -> Py_ssize_t
10410 
10411     fd: int
10412     buffer: Py_buffer
10413     offset: Py_off_t
10414     /
10415 
10416 Write bytes to a file descriptor starting at a particular offset.
10417 
10418 Write buffer to fd, starting at offset bytes from the beginning of
10419 the file.  Returns the number of bytes writte.  Does not change the
10420 current file offset.
10421 [clinic start generated code]*/
10422 
10423 static Py_ssize_t
os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)10424 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10425 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10426 {
10427     Py_ssize_t size;
10428     int async_err = 0;
10429 
10430     do {
10431         Py_BEGIN_ALLOW_THREADS
10432         _Py_BEGIN_SUPPRESS_IPH
10433         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10434         _Py_END_SUPPRESS_IPH
10435         Py_END_ALLOW_THREADS
10436     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10437 
10438     if (size < 0 && !async_err)
10439         posix_error();
10440     return size;
10441 }
10442 #endif /* HAVE_PWRITE */
10443 
10444 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10445 /*[clinic input]
10446 os.pwritev -> Py_ssize_t
10447 
10448     fd: int
10449     buffers: object
10450     offset: Py_off_t
10451     flags: int = 0
10452     /
10453 
10454 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10455 
10456 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10457 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10458 buffer is written before proceeding to second, and so on. The operating system may
10459 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10460 This function writes the contents of each object to the file descriptor and returns
10461 the total number of bytes written.
10462 
10463 The flags argument contains a bitwise OR of zero or more of the following flags:
10464 
10465 - RWF_DSYNC
10466 - RWF_SYNC
10467 - RWF_APPEND
10468 
10469 Using non-zero flags requires Linux 4.7 or newer.
10470 [clinic start generated code]*/
10471 
10472 static Py_ssize_t
os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset, int flags)10473 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10474                 int flags)
10475 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10476 {
10477     Py_ssize_t cnt;
10478     Py_ssize_t result;
10479     int async_err = 0;
10480     struct iovec *iov;
10481     Py_buffer *buf;
10482 
10483     if (!PySequence_Check(buffers)) {
10484         PyErr_SetString(PyExc_TypeError,
10485             "pwritev() arg 2 must be a sequence");
10486         return -1;
10487     }
10488 
10489     cnt = PySequence_Size(buffers);
10490     if (cnt < 0) {
10491         return -1;
10492     }
10493 
10494 #ifndef HAVE_PWRITEV2
10495     if(flags != 0) {
10496         argument_unavailable_error("pwritev2", "flags");
10497         return -1;
10498     }
10499 #endif
10500 
10501     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10502         return -1;
10503     }
10504 #ifdef HAVE_PWRITEV2
10505     do {
10506         Py_BEGIN_ALLOW_THREADS
10507         _Py_BEGIN_SUPPRESS_IPH
10508         result = pwritev2(fd, iov, cnt, offset, flags);
10509         _Py_END_SUPPRESS_IPH
10510         Py_END_ALLOW_THREADS
10511     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10512 #else
10513 
10514 #if defined(__APPLE__) && defined(__clang__)
10515 /* This entire function will be removed from the module dict when the API
10516  * is not available.
10517  */
10518 #pragma clang diagnostic push
10519 #pragma clang diagnostic ignored "-Wunguarded-availability"
10520 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10521 #endif
10522     do {
10523         Py_BEGIN_ALLOW_THREADS
10524         _Py_BEGIN_SUPPRESS_IPH
10525         result = pwritev(fd, iov, cnt, offset);
10526         _Py_END_SUPPRESS_IPH
10527         Py_END_ALLOW_THREADS
10528     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10529 
10530 #if defined(__APPLE__) && defined(__clang__)
10531 #pragma clang diagnostic pop
10532 #endif
10533 
10534 #endif
10535 
10536     iov_cleanup(iov, buf, cnt);
10537     if (result < 0) {
10538         if (!async_err) {
10539             posix_error();
10540         }
10541         return -1;
10542     }
10543 
10544     return result;
10545 }
10546 #endif /* HAVE_PWRITEV */
10547 
10548 #ifdef HAVE_COPY_FILE_RANGE
10549 /*[clinic input]
10550 
10551 os.copy_file_range
10552     src: int
10553         Source file descriptor.
10554     dst: int
10555         Destination file descriptor.
10556     count: Py_ssize_t
10557         Number of bytes to copy.
10558     offset_src: object = None
10559         Starting offset in src.
10560     offset_dst: object = None
10561         Starting offset in dst.
10562 
10563 Copy count bytes from one file descriptor to another.
10564 
10565 If offset_src is None, then src is read from the current position;
10566 respectively for offset_dst.
10567 [clinic start generated code]*/
10568 
10569 static PyObject *
os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst)10570 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10571                         PyObject *offset_src, PyObject *offset_dst)
10572 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10573 {
10574     off_t offset_src_val, offset_dst_val;
10575     off_t *p_offset_src = NULL;
10576     off_t *p_offset_dst = NULL;
10577     Py_ssize_t ret;
10578     int async_err = 0;
10579     /* The flags argument is provided to allow
10580      * for future extensions and currently must be to 0. */
10581     int flags = 0;
10582 
10583 
10584     if (count < 0) {
10585         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10586         return NULL;
10587     }
10588 
10589     if (offset_src != Py_None) {
10590         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10591             return NULL;
10592         }
10593         p_offset_src = &offset_src_val;
10594     }
10595 
10596     if (offset_dst != Py_None) {
10597         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10598             return NULL;
10599         }
10600         p_offset_dst = &offset_dst_val;
10601     }
10602 
10603     do {
10604         Py_BEGIN_ALLOW_THREADS
10605         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10606         Py_END_ALLOW_THREADS
10607     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10608 
10609     if (ret < 0) {
10610         return (!async_err) ? posix_error() : NULL;
10611     }
10612 
10613     return PyLong_FromSsize_t(ret);
10614 }
10615 #endif /* HAVE_COPY_FILE_RANGE*/
10616 
10617 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10618 /*[clinic input]
10619 
10620 os.splice
10621     src: int
10622         Source file descriptor.
10623     dst: int
10624         Destination file descriptor.
10625     count: Py_ssize_t
10626         Number of bytes to copy.
10627     offset_src: object = None
10628         Starting offset in src.
10629     offset_dst: object = None
10630         Starting offset in dst.
10631     flags: unsigned_int = 0
10632         Flags to modify the semantics of the call.
10633 
10634 Transfer count bytes from one pipe to a descriptor or vice versa.
10635 
10636 If offset_src is None, then src is read from the current position;
10637 respectively for offset_dst. The offset associated to the file
10638 descriptor that refers to a pipe must be None.
10639 [clinic start generated code]*/
10640 
10641 static PyObject *
os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count, PyObject *offset_src, PyObject *offset_dst, unsigned int flags)10642 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10643                PyObject *offset_src, PyObject *offset_dst,
10644                unsigned int flags)
10645 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10646 {
10647     off_t offset_src_val, offset_dst_val;
10648     off_t *p_offset_src = NULL;
10649     off_t *p_offset_dst = NULL;
10650     Py_ssize_t ret;
10651     int async_err = 0;
10652 
10653     if (count < 0) {
10654         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10655         return NULL;
10656     }
10657 
10658     if (offset_src != Py_None) {
10659         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10660             return NULL;
10661         }
10662         p_offset_src = &offset_src_val;
10663     }
10664 
10665     if (offset_dst != Py_None) {
10666         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10667             return NULL;
10668         }
10669         p_offset_dst = &offset_dst_val;
10670     }
10671 
10672     do {
10673         Py_BEGIN_ALLOW_THREADS
10674         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10675         Py_END_ALLOW_THREADS
10676     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10677 
10678     if (ret < 0) {
10679         return (!async_err) ? posix_error() : NULL;
10680     }
10681 
10682     return PyLong_FromSsize_t(ret);
10683 }
10684 #endif /* HAVE_SPLICE*/
10685 
10686 #ifdef HAVE_MKFIFO
10687 /*[clinic input]
10688 os.mkfifo
10689 
10690     path: path_t
10691     mode: int=0o666
10692     *
10693     dir_fd: dir_fd(requires='mkfifoat')=None
10694 
10695 Create a "fifo" (a POSIX named pipe).
10696 
10697 If dir_fd is not None, it should be a file descriptor open to a directory,
10698   and path should be relative; path will then be relative to that directory.
10699 dir_fd may not be implemented on your platform.
10700   If it is unavailable, using it will raise a NotImplementedError.
10701 [clinic start generated code]*/
10702 
10703 static PyObject *
os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)10704 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10705 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10706 {
10707     int result;
10708     int async_err = 0;
10709 #ifdef HAVE_MKFIFOAT
10710     int mkfifoat_unavailable = 0;
10711 #endif
10712 
10713     do {
10714         Py_BEGIN_ALLOW_THREADS
10715 #ifdef HAVE_MKFIFOAT
10716         if (dir_fd != DEFAULT_DIR_FD) {
10717             if (HAVE_MKFIFOAT_RUNTIME) {
10718                 result = mkfifoat(dir_fd, path->narrow, mode);
10719 
10720             } else {
10721                 mkfifoat_unavailable = 1;
10722                 result = 0;
10723             }
10724         } else
10725 #endif
10726             result = mkfifo(path->narrow, mode);
10727         Py_END_ALLOW_THREADS
10728     } while (result != 0 && errno == EINTR &&
10729              !(async_err = PyErr_CheckSignals()));
10730 
10731 #ifdef HAVE_MKFIFOAT
10732     if (mkfifoat_unavailable) {
10733         argument_unavailable_error(NULL, "dir_fd");
10734         return NULL;
10735     }
10736 #endif
10737 
10738     if (result != 0)
10739         return (!async_err) ? posix_error() : NULL;
10740 
10741     Py_RETURN_NONE;
10742 }
10743 #endif /* HAVE_MKFIFO */
10744 
10745 
10746 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10747 /*[clinic input]
10748 os.mknod
10749 
10750     path: path_t
10751     mode: int=0o600
10752     device: dev_t=0
10753     *
10754     dir_fd: dir_fd(requires='mknodat')=None
10755 
10756 Create a node in the file system.
10757 
10758 Create a node in the file system (file, device special file or named pipe)
10759 at path.  mode specifies both the permissions to use and the
10760 type of node to be created, being combined (bitwise OR) with one of
10761 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10762 device defines the newly created device special file (probably using
10763 os.makedev()).  Otherwise device is ignored.
10764 
10765 If dir_fd is not None, it should be a file descriptor open to a directory,
10766   and path should be relative; path will then be relative to that directory.
10767 dir_fd may not be implemented on your platform.
10768   If it is unavailable, using it will raise a NotImplementedError.
10769 [clinic start generated code]*/
10770 
10771 static PyObject *
os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device, int dir_fd)10772 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10773               int dir_fd)
10774 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10775 {
10776     int result;
10777     int async_err = 0;
10778 #ifdef HAVE_MKNODAT
10779     int mknodat_unavailable = 0;
10780 #endif
10781 
10782     do {
10783         Py_BEGIN_ALLOW_THREADS
10784 #ifdef HAVE_MKNODAT
10785         if (dir_fd != DEFAULT_DIR_FD) {
10786             if (HAVE_MKNODAT_RUNTIME) {
10787                 result = mknodat(dir_fd, path->narrow, mode, device);
10788 
10789             } else {
10790                 mknodat_unavailable = 1;
10791                 result = 0;
10792             }
10793         } else
10794 #endif
10795             result = mknod(path->narrow, mode, device);
10796         Py_END_ALLOW_THREADS
10797     } while (result != 0 && errno == EINTR &&
10798              !(async_err = PyErr_CheckSignals()));
10799 #ifdef HAVE_MKNODAT
10800     if (mknodat_unavailable) {
10801         argument_unavailable_error(NULL, "dir_fd");
10802         return NULL;
10803     }
10804 #endif
10805     if (result != 0)
10806         return (!async_err) ? posix_error() : NULL;
10807 
10808     Py_RETURN_NONE;
10809 }
10810 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10811 
10812 
10813 #ifdef HAVE_DEVICE_MACROS
10814 /*[clinic input]
10815 os.major -> unsigned_int
10816 
10817     device: dev_t
10818     /
10819 
10820 Extracts a device major number from a raw device number.
10821 [clinic start generated code]*/
10822 
10823 static unsigned int
os_major_impl(PyObject *module, dev_t device)10824 os_major_impl(PyObject *module, dev_t device)
10825 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10826 {
10827     return major(device);
10828 }
10829 
10830 
10831 /*[clinic input]
10832 os.minor -> unsigned_int
10833 
10834     device: dev_t
10835     /
10836 
10837 Extracts a device minor number from a raw device number.
10838 [clinic start generated code]*/
10839 
10840 static unsigned int
os_minor_impl(PyObject *module, dev_t device)10841 os_minor_impl(PyObject *module, dev_t device)
10842 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10843 {
10844     return minor(device);
10845 }
10846 
10847 
10848 /*[clinic input]
10849 os.makedev -> dev_t
10850 
10851     major: int
10852     minor: int
10853     /
10854 
10855 Composes a raw device number from the major and minor device numbers.
10856 [clinic start generated code]*/
10857 
10858 static dev_t
os_makedev_impl(PyObject *module, int major, int minor)10859 os_makedev_impl(PyObject *module, int major, int minor)
10860 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10861 {
10862     return makedev(major, minor);
10863 }
10864 #endif /* HAVE_DEVICE_MACROS */
10865 
10866 
10867 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10868 /*[clinic input]
10869 os.ftruncate
10870 
10871     fd: int
10872     length: Py_off_t
10873     /
10874 
10875 Truncate a file, specified by file descriptor, to a specific length.
10876 [clinic start generated code]*/
10877 
10878 static PyObject *
os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)10879 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10880 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10881 {
10882     int result;
10883     int async_err = 0;
10884 
10885     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10886         return NULL;
10887     }
10888 
10889     do {
10890         Py_BEGIN_ALLOW_THREADS
10891         _Py_BEGIN_SUPPRESS_IPH
10892 #ifdef MS_WINDOWS
10893         result = _chsize_s(fd, length);
10894 #else
10895         result = ftruncate(fd, length);
10896 #endif
10897         _Py_END_SUPPRESS_IPH
10898         Py_END_ALLOW_THREADS
10899     } while (result != 0 && errno == EINTR &&
10900              !(async_err = PyErr_CheckSignals()));
10901     if (result != 0)
10902         return (!async_err) ? posix_error() : NULL;
10903     Py_RETURN_NONE;
10904 }
10905 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10906 
10907 
10908 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10909 /*[clinic input]
10910 os.truncate
10911     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10912     length: Py_off_t
10913 
10914 Truncate a file, specified by path, to a specific length.
10915 
10916 On some platforms, path may also be specified as an open file descriptor.
10917   If this functionality is unavailable, using it raises an exception.
10918 [clinic start generated code]*/
10919 
10920 static PyObject *
os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)10921 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10922 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10923 {
10924     int result;
10925 #ifdef MS_WINDOWS
10926     int fd;
10927 #endif
10928 
10929     if (path->fd != -1)
10930         return os_ftruncate_impl(module, path->fd, length);
10931 
10932     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10933         return NULL;
10934     }
10935 
10936     Py_BEGIN_ALLOW_THREADS
10937     _Py_BEGIN_SUPPRESS_IPH
10938 #ifdef MS_WINDOWS
10939     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10940     if (fd < 0)
10941         result = -1;
10942     else {
10943         result = _chsize_s(fd, length);
10944         close(fd);
10945         if (result < 0)
10946             errno = result;
10947     }
10948 #else
10949     result = truncate(path->narrow, length);
10950 #endif
10951     _Py_END_SUPPRESS_IPH
10952     Py_END_ALLOW_THREADS
10953     if (result < 0)
10954         return posix_path_error(path);
10955 
10956     Py_RETURN_NONE;
10957 }
10958 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10959 
10960 
10961 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10962    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10963    defined, which is the case in Python on AIX. AIX bug report:
10964    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10965 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10966 #  define POSIX_FADVISE_AIX_BUG
10967 #endif
10968 
10969 
10970 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10971 /*[clinic input]
10972 os.posix_fallocate
10973 
10974     fd: int
10975     offset: Py_off_t
10976     length: Py_off_t
10977     /
10978 
10979 Ensure a file has allocated at least a particular number of bytes on disk.
10980 
10981 Ensure that the file specified by fd encompasses a range of bytes
10982 starting at offset bytes from the beginning and continuing for length bytes.
10983 [clinic start generated code]*/
10984 
10985 static PyObject *
os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length)10986 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10987                         Py_off_t length)
10988 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10989 {
10990     int result;
10991     int async_err = 0;
10992 
10993     do {
10994         Py_BEGIN_ALLOW_THREADS
10995         result = posix_fallocate(fd, offset, length);
10996         Py_END_ALLOW_THREADS
10997     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10998 
10999     if (result == 0)
11000         Py_RETURN_NONE;
11001 
11002     if (async_err)
11003         return NULL;
11004 
11005     errno = result;
11006     return posix_error();
11007 }
11008 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
11009 
11010 
11011 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
11012 /*[clinic input]
11013 os.posix_fadvise
11014 
11015     fd: int
11016     offset: Py_off_t
11017     length: Py_off_t
11018     advice: int
11019     /
11020 
11021 Announce an intention to access data in a specific pattern.
11022 
11023 Announce an intention to access data in a specific pattern, thus allowing
11024 the kernel to make optimizations.
11025 The advice applies to the region of the file specified by fd starting at
11026 offset and continuing for length bytes.
11027 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
11028 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
11029 POSIX_FADV_DONTNEED.
11030 [clinic start generated code]*/
11031 
11032 static PyObject *
os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, Py_off_t length, int advice)11033 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
11034                       Py_off_t length, int advice)
11035 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
11036 {
11037     int result;
11038     int async_err = 0;
11039 
11040     do {
11041         Py_BEGIN_ALLOW_THREADS
11042         result = posix_fadvise(fd, offset, length, advice);
11043         Py_END_ALLOW_THREADS
11044     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11045 
11046     if (result == 0)
11047         Py_RETURN_NONE;
11048 
11049     if (async_err)
11050         return NULL;
11051 
11052     errno = result;
11053     return posix_error();
11054 }
11055 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11056 
11057 
11058 #ifdef MS_WINDOWS
11059 static PyObject*
win32_putenv(PyObject *name, PyObject *value)11060 win32_putenv(PyObject *name, PyObject *value)
11061 {
11062     /* Search from index 1 because on Windows starting '=' is allowed for
11063        defining hidden environment variables. */
11064     if (PyUnicode_GET_LENGTH(name) == 0 ||
11065         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11066     {
11067         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11068         return NULL;
11069     }
11070     PyObject *unicode;
11071     if (value != NULL) {
11072         unicode = PyUnicode_FromFormat("%U=%U", name, value);
11073     }
11074     else {
11075         unicode = PyUnicode_FromFormat("%U=", name);
11076     }
11077     if (unicode == NULL) {
11078         return NULL;
11079     }
11080 
11081     Py_ssize_t size;
11082     /* PyUnicode_AsWideCharString() rejects embedded null characters */
11083     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11084     Py_DECREF(unicode);
11085 
11086     if (env == NULL) {
11087         return NULL;
11088     }
11089     if (size > _MAX_ENV) {
11090         PyErr_Format(PyExc_ValueError,
11091                      "the environment variable is longer than %u characters",
11092                      _MAX_ENV);
11093         PyMem_Free(env);
11094         return NULL;
11095     }
11096 
11097     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11098        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11099        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11100 
11101        Prefer _wputenv() to be compatible with C libraries using CRT
11102        variables and CRT functions using these variables (ex: getenv()). */
11103     int err = _wputenv(env);
11104     PyMem_Free(env);
11105 
11106     if (err) {
11107         posix_error();
11108         return NULL;
11109     }
11110 
11111     Py_RETURN_NONE;
11112 }
11113 #endif
11114 
11115 
11116 #ifdef MS_WINDOWS
11117 /*[clinic input]
11118 os.putenv
11119 
11120     name: unicode
11121     value: unicode
11122     /
11123 
11124 Change or add an environment variable.
11125 [clinic start generated code]*/
11126 
11127 static PyObject *
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)11128 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11129 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11130 {
11131     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11132         return NULL;
11133     }
11134     return win32_putenv(name, value);
11135 }
11136 #else
11137 /*[clinic input]
11138 os.putenv
11139 
11140     name: FSConverter
11141     value: FSConverter
11142     /
11143 
11144 Change or add an environment variable.
11145 [clinic start generated code]*/
11146 
11147 static PyObject *
os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)11148 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11149 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11150 {
11151     const char *name_string = PyBytes_AS_STRING(name);
11152     const char *value_string = PyBytes_AS_STRING(value);
11153 
11154     if (strchr(name_string, '=') != NULL) {
11155         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11156         return NULL;
11157     }
11158 
11159     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11160         return NULL;
11161     }
11162 
11163     if (setenv(name_string, value_string, 1)) {
11164         return posix_error();
11165     }
11166     Py_RETURN_NONE;
11167 }
11168 #endif  /* !defined(MS_WINDOWS) */
11169 
11170 
11171 #ifdef MS_WINDOWS
11172 /*[clinic input]
11173 os.unsetenv
11174     name: unicode
11175     /
11176 
11177 Delete an environment variable.
11178 [clinic start generated code]*/
11179 
11180 static PyObject *
os_unsetenv_impl(PyObject *module, PyObject *name)11181 os_unsetenv_impl(PyObject *module, PyObject *name)
11182 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11183 {
11184     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11185         return NULL;
11186     }
11187     return win32_putenv(name, NULL);
11188 }
11189 #else
11190 /*[clinic input]
11191 os.unsetenv
11192     name: FSConverter
11193     /
11194 
11195 Delete an environment variable.
11196 [clinic start generated code]*/
11197 
11198 static PyObject *
os_unsetenv_impl(PyObject *module, PyObject *name)11199 os_unsetenv_impl(PyObject *module, PyObject *name)
11200 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11201 {
11202     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11203         return NULL;
11204     }
11205 #ifdef HAVE_BROKEN_UNSETENV
11206     unsetenv(PyBytes_AS_STRING(name));
11207 #else
11208     int err = unsetenv(PyBytes_AS_STRING(name));
11209     if (err) {
11210         return posix_error();
11211     }
11212 #endif
11213 
11214     Py_RETURN_NONE;
11215 }
11216 #endif /* !MS_WINDOWS */
11217 
11218 
11219 /*[clinic input]
11220 os.strerror
11221 
11222     code: int
11223     /
11224 
11225 Translate an error code to a message string.
11226 [clinic start generated code]*/
11227 
11228 static PyObject *
os_strerror_impl(PyObject *module, int code)11229 os_strerror_impl(PyObject *module, int code)
11230 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11231 {
11232     char *message = strerror(code);
11233     if (message == NULL) {
11234         PyErr_SetString(PyExc_ValueError,
11235                         "strerror() argument out of range");
11236         return NULL;
11237     }
11238     return PyUnicode_DecodeLocale(message, "surrogateescape");
11239 }
11240 
11241 
11242 #ifdef HAVE_SYS_WAIT_H
11243 #ifdef WCOREDUMP
11244 /*[clinic input]
11245 os.WCOREDUMP -> bool
11246 
11247     status: int
11248     /
11249 
11250 Return True if the process returning status was dumped to a core file.
11251 [clinic start generated code]*/
11252 
11253 static int
os_WCOREDUMP_impl(PyObject *module, int status)11254 os_WCOREDUMP_impl(PyObject *module, int status)
11255 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11256 {
11257     WAIT_TYPE wait_status;
11258     WAIT_STATUS_INT(wait_status) = status;
11259     return WCOREDUMP(wait_status);
11260 }
11261 #endif /* WCOREDUMP */
11262 
11263 
11264 #ifdef WIFCONTINUED
11265 /*[clinic input]
11266 os.WIFCONTINUED -> bool
11267 
11268     status: int
11269 
11270 Return True if a particular process was continued from a job control stop.
11271 
11272 Return True if the process returning status was continued from a
11273 job control stop.
11274 [clinic start generated code]*/
11275 
11276 static int
os_WIFCONTINUED_impl(PyObject *module, int status)11277 os_WIFCONTINUED_impl(PyObject *module, int status)
11278 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11279 {
11280     WAIT_TYPE wait_status;
11281     WAIT_STATUS_INT(wait_status) = status;
11282     return WIFCONTINUED(wait_status);
11283 }
11284 #endif /* WIFCONTINUED */
11285 
11286 
11287 #ifdef WIFSTOPPED
11288 /*[clinic input]
11289 os.WIFSTOPPED -> bool
11290 
11291     status: int
11292 
11293 Return True if the process returning status was stopped.
11294 [clinic start generated code]*/
11295 
11296 static int
os_WIFSTOPPED_impl(PyObject *module, int status)11297 os_WIFSTOPPED_impl(PyObject *module, int status)
11298 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11299 {
11300     WAIT_TYPE wait_status;
11301     WAIT_STATUS_INT(wait_status) = status;
11302     return WIFSTOPPED(wait_status);
11303 }
11304 #endif /* WIFSTOPPED */
11305 
11306 
11307 #ifdef WIFSIGNALED
11308 /*[clinic input]
11309 os.WIFSIGNALED -> bool
11310 
11311     status: int
11312 
11313 Return True if the process returning status was terminated by a signal.
11314 [clinic start generated code]*/
11315 
11316 static int
os_WIFSIGNALED_impl(PyObject *module, int status)11317 os_WIFSIGNALED_impl(PyObject *module, int status)
11318 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11319 {
11320     WAIT_TYPE wait_status;
11321     WAIT_STATUS_INT(wait_status) = status;
11322     return WIFSIGNALED(wait_status);
11323 }
11324 #endif /* WIFSIGNALED */
11325 
11326 
11327 #ifdef WIFEXITED
11328 /*[clinic input]
11329 os.WIFEXITED -> bool
11330 
11331     status: int
11332 
11333 Return True if the process returning status exited via the exit() system call.
11334 [clinic start generated code]*/
11335 
11336 static int
os_WIFEXITED_impl(PyObject *module, int status)11337 os_WIFEXITED_impl(PyObject *module, int status)
11338 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11339 {
11340     WAIT_TYPE wait_status;
11341     WAIT_STATUS_INT(wait_status) = status;
11342     return WIFEXITED(wait_status);
11343 }
11344 #endif /* WIFEXITED */
11345 
11346 
11347 #ifdef WEXITSTATUS
11348 /*[clinic input]
11349 os.WEXITSTATUS -> int
11350 
11351     status: int
11352 
11353 Return the process return code from status.
11354 [clinic start generated code]*/
11355 
11356 static int
os_WEXITSTATUS_impl(PyObject *module, int status)11357 os_WEXITSTATUS_impl(PyObject *module, int status)
11358 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11359 {
11360     WAIT_TYPE wait_status;
11361     WAIT_STATUS_INT(wait_status) = status;
11362     return WEXITSTATUS(wait_status);
11363 }
11364 #endif /* WEXITSTATUS */
11365 
11366 
11367 #ifdef WTERMSIG
11368 /*[clinic input]
11369 os.WTERMSIG -> int
11370 
11371     status: int
11372 
11373 Return the signal that terminated the process that provided the status value.
11374 [clinic start generated code]*/
11375 
11376 static int
os_WTERMSIG_impl(PyObject *module, int status)11377 os_WTERMSIG_impl(PyObject *module, int status)
11378 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11379 {
11380     WAIT_TYPE wait_status;
11381     WAIT_STATUS_INT(wait_status) = status;
11382     return WTERMSIG(wait_status);
11383 }
11384 #endif /* WTERMSIG */
11385 
11386 
11387 #ifdef WSTOPSIG
11388 /*[clinic input]
11389 os.WSTOPSIG -> int
11390 
11391     status: int
11392 
11393 Return the signal that stopped the process that provided the status value.
11394 [clinic start generated code]*/
11395 
11396 static int
os_WSTOPSIG_impl(PyObject *module, int status)11397 os_WSTOPSIG_impl(PyObject *module, int status)
11398 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11399 {
11400     WAIT_TYPE wait_status;
11401     WAIT_STATUS_INT(wait_status) = status;
11402     return WSTOPSIG(wait_status);
11403 }
11404 #endif /* WSTOPSIG */
11405 #endif /* HAVE_SYS_WAIT_H */
11406 
11407 
11408 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11409 #ifdef _SCO_DS
11410 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11411    needed definitions in sys/statvfs.h */
11412 #define _SVID3
11413 #endif
11414 #include <sys/statvfs.h>
11415 
11416 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st)11417 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11418     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11419     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11420     if (v == NULL)
11421         return NULL;
11422 
11423 #if !defined(HAVE_LARGEFILE_SUPPORT)
11424     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11425     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11426     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11427     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11428     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11429     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11430     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11431     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11432     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11433     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11434 #else
11435     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11436     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11437     PyStructSequence_SET_ITEM(v, 2,
11438                               PyLong_FromLongLong((long long) st.f_blocks));
11439     PyStructSequence_SET_ITEM(v, 3,
11440                               PyLong_FromLongLong((long long) st.f_bfree));
11441     PyStructSequence_SET_ITEM(v, 4,
11442                               PyLong_FromLongLong((long long) st.f_bavail));
11443     PyStructSequence_SET_ITEM(v, 5,
11444                               PyLong_FromLongLong((long long) st.f_files));
11445     PyStructSequence_SET_ITEM(v, 6,
11446                               PyLong_FromLongLong((long long) st.f_ffree));
11447     PyStructSequence_SET_ITEM(v, 7,
11448                               PyLong_FromLongLong((long long) st.f_favail));
11449     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11450     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11451 #endif
11452 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11453  * (issue #32390). */
11454 #if defined(_AIX) && defined(_ALL_SOURCE)
11455     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11456 #else
11457     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11458 #endif
11459     if (PyErr_Occurred()) {
11460         Py_DECREF(v);
11461         return NULL;
11462     }
11463 
11464     return v;
11465 }
11466 
11467 
11468 /*[clinic input]
11469 os.fstatvfs
11470     fd: int
11471     /
11472 
11473 Perform an fstatvfs system call on the given fd.
11474 
11475 Equivalent to statvfs(fd).
11476 [clinic start generated code]*/
11477 
11478 static PyObject *
os_fstatvfs_impl(PyObject *module, int fd)11479 os_fstatvfs_impl(PyObject *module, int fd)
11480 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11481 {
11482     int result;
11483     int async_err = 0;
11484     struct statvfs st;
11485 
11486     do {
11487         Py_BEGIN_ALLOW_THREADS
11488         result = fstatvfs(fd, &st);
11489         Py_END_ALLOW_THREADS
11490     } while (result != 0 && errno == EINTR &&
11491              !(async_err = PyErr_CheckSignals()));
11492     if (result != 0)
11493         return (!async_err) ? posix_error() : NULL;
11494 
11495     return _pystatvfs_fromstructstatvfs(module, st);
11496 }
11497 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11498 
11499 
11500 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11501 #include <sys/statvfs.h>
11502 /*[clinic input]
11503 os.statvfs
11504 
11505     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11506 
11507 Perform a statvfs system call on the given path.
11508 
11509 path may always be specified as a string.
11510 On some platforms, path may also be specified as an open file descriptor.
11511   If this functionality is unavailable, using it raises an exception.
11512 [clinic start generated code]*/
11513 
11514 static PyObject *
os_statvfs_impl(PyObject *module, path_t *path)11515 os_statvfs_impl(PyObject *module, path_t *path)
11516 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11517 {
11518     int result;
11519     struct statvfs st;
11520 
11521     Py_BEGIN_ALLOW_THREADS
11522 #ifdef HAVE_FSTATVFS
11523     if (path->fd != -1) {
11524         result = fstatvfs(path->fd, &st);
11525     }
11526     else
11527 #endif
11528         result = statvfs(path->narrow, &st);
11529     Py_END_ALLOW_THREADS
11530 
11531     if (result) {
11532         return path_error(path);
11533     }
11534 
11535     return _pystatvfs_fromstructstatvfs(module, st);
11536 }
11537 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11538 
11539 
11540 #ifdef MS_WINDOWS
11541 /*[clinic input]
11542 os._getdiskusage
11543 
11544     path: path_t
11545 
11546 Return disk usage statistics about the given path as a (total, free) tuple.
11547 [clinic start generated code]*/
11548 
11549 static PyObject *
os__getdiskusage_impl(PyObject *module, path_t *path)11550 os__getdiskusage_impl(PyObject *module, path_t *path)
11551 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11552 {
11553     BOOL retval;
11554     ULARGE_INTEGER _, total, free;
11555     DWORD err = 0;
11556 
11557     Py_BEGIN_ALLOW_THREADS
11558     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11559     Py_END_ALLOW_THREADS
11560     if (retval == 0) {
11561         if (GetLastError() == ERROR_DIRECTORY) {
11562             wchar_t *dir_path = NULL;
11563 
11564             dir_path = PyMem_New(wchar_t, path->length + 1);
11565             if (dir_path == NULL) {
11566                 return PyErr_NoMemory();
11567             }
11568 
11569             wcscpy_s(dir_path, path->length + 1, path->wide);
11570 
11571             if (_dirnameW(dir_path) != -1) {
11572                 Py_BEGIN_ALLOW_THREADS
11573                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11574                 Py_END_ALLOW_THREADS
11575             }
11576             /* Record the last error in case it's modified by PyMem_Free. */
11577             err = GetLastError();
11578             PyMem_Free(dir_path);
11579             if (retval) {
11580                 goto success;
11581             }
11582         }
11583         return PyErr_SetFromWindowsErr(err);
11584     }
11585 
11586 success:
11587     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11588 }
11589 #endif /* MS_WINDOWS */
11590 
11591 
11592 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11593  * It maps strings representing configuration variable names to
11594  * integer values, allowing those functions to be called with the
11595  * magic names instead of polluting the module's namespace with tons of
11596  * rarely-used constants.  There are three separate tables that use
11597  * these definitions.
11598  *
11599  * This code is always included, even if none of the interfaces that
11600  * need it are included.  The #if hackery needed to avoid it would be
11601  * sufficiently pervasive that it's not worth the loss of readability.
11602  */
11603 struct constdef {
11604     const char *name;
11605     int value;
11606 };
11607 
11608 static int
conv_confname(PyObject *arg, int *valuep, struct constdef *table, size_t tablesize)11609 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11610               size_t tablesize)
11611 {
11612     if (PyLong_Check(arg)) {
11613         int value = _PyLong_AsInt(arg);
11614         if (value == -1 && PyErr_Occurred())
11615             return 0;
11616         *valuep = value;
11617         return 1;
11618     }
11619     else {
11620         /* look up the value in the table using a binary search */
11621         size_t lo = 0;
11622         size_t mid;
11623         size_t hi = tablesize;
11624         int cmp;
11625         const char *confname;
11626         if (!PyUnicode_Check(arg)) {
11627             PyErr_SetString(PyExc_TypeError,
11628                 "configuration names must be strings or integers");
11629             return 0;
11630         }
11631         confname = PyUnicode_AsUTF8(arg);
11632         if (confname == NULL)
11633             return 0;
11634         while (lo < hi) {
11635             mid = (lo + hi) / 2;
11636             cmp = strcmp(confname, table[mid].name);
11637             if (cmp < 0)
11638                 hi = mid;
11639             else if (cmp > 0)
11640                 lo = mid + 1;
11641             else {
11642                 *valuep = table[mid].value;
11643                 return 1;
11644             }
11645         }
11646         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11647         return 0;
11648     }
11649 }
11650 
11651 
11652 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11653 static struct constdef  posix_constants_pathconf[] = {
11654 #ifdef _PC_ABI_AIO_XFER_MAX
11655     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11656 #endif
11657 #ifdef _PC_ABI_ASYNC_IO
11658     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11659 #endif
11660 #ifdef _PC_ASYNC_IO
11661     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11662 #endif
11663 #ifdef _PC_CHOWN_RESTRICTED
11664     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11665 #endif
11666 #ifdef _PC_FILESIZEBITS
11667     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11668 #endif
11669 #ifdef _PC_LAST
11670     {"PC_LAST", _PC_LAST},
11671 #endif
11672 #ifdef _PC_LINK_MAX
11673     {"PC_LINK_MAX",     _PC_LINK_MAX},
11674 #endif
11675 #ifdef _PC_MAX_CANON
11676     {"PC_MAX_CANON",    _PC_MAX_CANON},
11677 #endif
11678 #ifdef _PC_MAX_INPUT
11679     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11680 #endif
11681 #ifdef _PC_NAME_MAX
11682     {"PC_NAME_MAX",     _PC_NAME_MAX},
11683 #endif
11684 #ifdef _PC_NO_TRUNC
11685     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11686 #endif
11687 #ifdef _PC_PATH_MAX
11688     {"PC_PATH_MAX",     _PC_PATH_MAX},
11689 #endif
11690 #ifdef _PC_PIPE_BUF
11691     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11692 #endif
11693 #ifdef _PC_PRIO_IO
11694     {"PC_PRIO_IO",      _PC_PRIO_IO},
11695 #endif
11696 #ifdef _PC_SOCK_MAXBUF
11697     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11698 #endif
11699 #ifdef _PC_SYNC_IO
11700     {"PC_SYNC_IO",      _PC_SYNC_IO},
11701 #endif
11702 #ifdef _PC_VDISABLE
11703     {"PC_VDISABLE",     _PC_VDISABLE},
11704 #endif
11705 #ifdef _PC_ACL_ENABLED
11706     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11707 #endif
11708 #ifdef _PC_MIN_HOLE_SIZE
11709     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11710 #endif
11711 #ifdef _PC_ALLOC_SIZE_MIN
11712     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11713 #endif
11714 #ifdef _PC_REC_INCR_XFER_SIZE
11715     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11716 #endif
11717 #ifdef _PC_REC_MAX_XFER_SIZE
11718     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11719 #endif
11720 #ifdef _PC_REC_MIN_XFER_SIZE
11721     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11722 #endif
11723 #ifdef _PC_REC_XFER_ALIGN
11724     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11725 #endif
11726 #ifdef _PC_SYMLINK_MAX
11727     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11728 #endif
11729 #ifdef _PC_XATTR_ENABLED
11730     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11731 #endif
11732 #ifdef _PC_XATTR_EXISTS
11733     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11734 #endif
11735 #ifdef _PC_TIMESTAMP_RESOLUTION
11736     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11737 #endif
11738 };
11739 
11740 static int
conv_path_confname(PyObject *arg, int *valuep)11741 conv_path_confname(PyObject *arg, int *valuep)
11742 {
11743     return conv_confname(arg, valuep, posix_constants_pathconf,
11744                          sizeof(posix_constants_pathconf)
11745                            / sizeof(struct constdef));
11746 }
11747 #endif
11748 
11749 
11750 #ifdef HAVE_FPATHCONF
11751 /*[clinic input]
11752 os.fpathconf -> long
11753 
11754     fd: fildes
11755     name: path_confname
11756     /
11757 
11758 Return the configuration limit name for the file descriptor fd.
11759 
11760 If there is no limit, return -1.
11761 [clinic start generated code]*/
11762 
11763 static long
os_fpathconf_impl(PyObject *module, int fd, int name)11764 os_fpathconf_impl(PyObject *module, int fd, int name)
11765 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11766 {
11767     long limit;
11768 
11769     errno = 0;
11770     limit = fpathconf(fd, name);
11771     if (limit == -1 && errno != 0)
11772         posix_error();
11773 
11774     return limit;
11775 }
11776 #endif /* HAVE_FPATHCONF */
11777 
11778 
11779 #ifdef HAVE_PATHCONF
11780 /*[clinic input]
11781 os.pathconf -> long
11782     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11783     name: path_confname
11784 
11785 Return the configuration limit name for the file or directory path.
11786 
11787 If there is no limit, return -1.
11788 On some platforms, path may also be specified as an open file descriptor.
11789   If this functionality is unavailable, using it raises an exception.
11790 [clinic start generated code]*/
11791 
11792 static long
os_pathconf_impl(PyObject *module, path_t *path, int name)11793 os_pathconf_impl(PyObject *module, path_t *path, int name)
11794 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11795 {
11796     long limit;
11797 
11798     errno = 0;
11799 #ifdef HAVE_FPATHCONF
11800     if (path->fd != -1)
11801         limit = fpathconf(path->fd, name);
11802     else
11803 #endif
11804         limit = pathconf(path->narrow, name);
11805     if (limit == -1 && errno != 0) {
11806         if (errno == EINVAL)
11807             /* could be a path or name problem */
11808             posix_error();
11809         else
11810             path_error(path);
11811     }
11812 
11813     return limit;
11814 }
11815 #endif /* HAVE_PATHCONF */
11816 
11817 #ifdef HAVE_CONFSTR
11818 static struct constdef posix_constants_confstr[] = {
11819 #ifdef _CS_ARCHITECTURE
11820     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11821 #endif
11822 #ifdef _CS_GNU_LIBC_VERSION
11823     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11824 #endif
11825 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11826     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11827 #endif
11828 #ifdef _CS_HOSTNAME
11829     {"CS_HOSTNAME",     _CS_HOSTNAME},
11830 #endif
11831 #ifdef _CS_HW_PROVIDER
11832     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11833 #endif
11834 #ifdef _CS_HW_SERIAL
11835     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11836 #endif
11837 #ifdef _CS_INITTAB_NAME
11838     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11839 #endif
11840 #ifdef _CS_LFS64_CFLAGS
11841     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11842 #endif
11843 #ifdef _CS_LFS64_LDFLAGS
11844     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11845 #endif
11846 #ifdef _CS_LFS64_LIBS
11847     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11848 #endif
11849 #ifdef _CS_LFS64_LINTFLAGS
11850     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11851 #endif
11852 #ifdef _CS_LFS_CFLAGS
11853     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11854 #endif
11855 #ifdef _CS_LFS_LDFLAGS
11856     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11857 #endif
11858 #ifdef _CS_LFS_LIBS
11859     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11860 #endif
11861 #ifdef _CS_LFS_LINTFLAGS
11862     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11863 #endif
11864 #ifdef _CS_MACHINE
11865     {"CS_MACHINE",      _CS_MACHINE},
11866 #endif
11867 #ifdef _CS_PATH
11868     {"CS_PATH", _CS_PATH},
11869 #endif
11870 #ifdef _CS_RELEASE
11871     {"CS_RELEASE",      _CS_RELEASE},
11872 #endif
11873 #ifdef _CS_SRPC_DOMAIN
11874     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11875 #endif
11876 #ifdef _CS_SYSNAME
11877     {"CS_SYSNAME",      _CS_SYSNAME},
11878 #endif
11879 #ifdef _CS_VERSION
11880     {"CS_VERSION",      _CS_VERSION},
11881 #endif
11882 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11883     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11884 #endif
11885 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11886     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11887 #endif
11888 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11889     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11890 #endif
11891 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11892     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11893 #endif
11894 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11895     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11896 #endif
11897 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11898     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11899 #endif
11900 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11901     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11902 #endif
11903 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11904     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11905 #endif
11906 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11907     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11908 #endif
11909 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11910     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11911 #endif
11912 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11913     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11914 #endif
11915 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11916     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11917 #endif
11918 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11919     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11920 #endif
11921 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11922     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11923 #endif
11924 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11925     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11926 #endif
11927 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11928     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11929 #endif
11930 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11931     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11932 #endif
11933 #ifdef _MIPS_CS_BASE
11934     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11935 #endif
11936 #ifdef _MIPS_CS_HOSTID
11937     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11938 #endif
11939 #ifdef _MIPS_CS_HW_NAME
11940     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11941 #endif
11942 #ifdef _MIPS_CS_NUM_PROCESSORS
11943     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11944 #endif
11945 #ifdef _MIPS_CS_OSREL_MAJ
11946     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11947 #endif
11948 #ifdef _MIPS_CS_OSREL_MIN
11949     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11950 #endif
11951 #ifdef _MIPS_CS_OSREL_PATCH
11952     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11953 #endif
11954 #ifdef _MIPS_CS_OS_NAME
11955     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11956 #endif
11957 #ifdef _MIPS_CS_OS_PROVIDER
11958     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11959 #endif
11960 #ifdef _MIPS_CS_PROCESSORS
11961     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11962 #endif
11963 #ifdef _MIPS_CS_SERIAL
11964     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11965 #endif
11966 #ifdef _MIPS_CS_VENDOR
11967     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11968 #endif
11969 };
11970 
11971 static int
conv_confstr_confname(PyObject *arg, int *valuep)11972 conv_confstr_confname(PyObject *arg, int *valuep)
11973 {
11974     return conv_confname(arg, valuep, posix_constants_confstr,
11975                          sizeof(posix_constants_confstr)
11976                            / sizeof(struct constdef));
11977 }
11978 
11979 
11980 /*[clinic input]
11981 os.confstr
11982 
11983     name: confstr_confname
11984     /
11985 
11986 Return a string-valued system configuration variable.
11987 [clinic start generated code]*/
11988 
11989 static PyObject *
os_confstr_impl(PyObject *module, int name)11990 os_confstr_impl(PyObject *module, int name)
11991 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11992 {
11993     PyObject *result = NULL;
11994     char buffer[255];
11995     size_t len;
11996 
11997     errno = 0;
11998     len = confstr(name, buffer, sizeof(buffer));
11999     if (len == 0) {
12000         if (errno) {
12001             posix_error();
12002             return NULL;
12003         }
12004         else {
12005             Py_RETURN_NONE;
12006         }
12007     }
12008 
12009     if (len >= sizeof(buffer)) {
12010         size_t len2;
12011         char *buf = PyMem_Malloc(len);
12012         if (buf == NULL)
12013             return PyErr_NoMemory();
12014         len2 = confstr(name, buf, len);
12015         assert(len == len2);
12016         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
12017         PyMem_Free(buf);
12018     }
12019     else
12020         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
12021     return result;
12022 }
12023 #endif /* HAVE_CONFSTR */
12024 
12025 
12026 #ifdef HAVE_SYSCONF
12027 static struct constdef posix_constants_sysconf[] = {
12028 #ifdef _SC_2_CHAR_TERM
12029     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
12030 #endif
12031 #ifdef _SC_2_C_BIND
12032     {"SC_2_C_BIND",     _SC_2_C_BIND},
12033 #endif
12034 #ifdef _SC_2_C_DEV
12035     {"SC_2_C_DEV",      _SC_2_C_DEV},
12036 #endif
12037 #ifdef _SC_2_C_VERSION
12038     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
12039 #endif
12040 #ifdef _SC_2_FORT_DEV
12041     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
12042 #endif
12043 #ifdef _SC_2_FORT_RUN
12044     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
12045 #endif
12046 #ifdef _SC_2_LOCALEDEF
12047     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
12048 #endif
12049 #ifdef _SC_2_SW_DEV
12050     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
12051 #endif
12052 #ifdef _SC_2_UPE
12053     {"SC_2_UPE",        _SC_2_UPE},
12054 #endif
12055 #ifdef _SC_2_VERSION
12056     {"SC_2_VERSION",    _SC_2_VERSION},
12057 #endif
12058 #ifdef _SC_ABI_ASYNCHRONOUS_IO
12059     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
12060 #endif
12061 #ifdef _SC_ACL
12062     {"SC_ACL",  _SC_ACL},
12063 #endif
12064 #ifdef _SC_AIO_LISTIO_MAX
12065     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
12066 #endif
12067 #ifdef _SC_AIO_MAX
12068     {"SC_AIO_MAX",      _SC_AIO_MAX},
12069 #endif
12070 #ifdef _SC_AIO_PRIO_DELTA_MAX
12071     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
12072 #endif
12073 #ifdef _SC_ARG_MAX
12074     {"SC_ARG_MAX",      _SC_ARG_MAX},
12075 #endif
12076 #ifdef _SC_ASYNCHRONOUS_IO
12077     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
12078 #endif
12079 #ifdef _SC_ATEXIT_MAX
12080     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
12081 #endif
12082 #ifdef _SC_AUDIT
12083     {"SC_AUDIT",        _SC_AUDIT},
12084 #endif
12085 #ifdef _SC_AVPHYS_PAGES
12086     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12087 #endif
12088 #ifdef _SC_BC_BASE_MAX
12089     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
12090 #endif
12091 #ifdef _SC_BC_DIM_MAX
12092     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
12093 #endif
12094 #ifdef _SC_BC_SCALE_MAX
12095     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12096 #endif
12097 #ifdef _SC_BC_STRING_MAX
12098     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
12099 #endif
12100 #ifdef _SC_CAP
12101     {"SC_CAP",  _SC_CAP},
12102 #endif
12103 #ifdef _SC_CHARCLASS_NAME_MAX
12104     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
12105 #endif
12106 #ifdef _SC_CHAR_BIT
12107     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
12108 #endif
12109 #ifdef _SC_CHAR_MAX
12110     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
12111 #endif
12112 #ifdef _SC_CHAR_MIN
12113     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
12114 #endif
12115 #ifdef _SC_CHILD_MAX
12116     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
12117 #endif
12118 #ifdef _SC_CLK_TCK
12119     {"SC_CLK_TCK",      _SC_CLK_TCK},
12120 #endif
12121 #ifdef _SC_COHER_BLKSZ
12122     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
12123 #endif
12124 #ifdef _SC_COLL_WEIGHTS_MAX
12125     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
12126 #endif
12127 #ifdef _SC_DCACHE_ASSOC
12128     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12129 #endif
12130 #ifdef _SC_DCACHE_BLKSZ
12131     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12132 #endif
12133 #ifdef _SC_DCACHE_LINESZ
12134     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
12135 #endif
12136 #ifdef _SC_DCACHE_SZ
12137     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
12138 #endif
12139 #ifdef _SC_DCACHE_TBLKSZ
12140     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
12141 #endif
12142 #ifdef _SC_DELAYTIMER_MAX
12143     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
12144 #endif
12145 #ifdef _SC_EQUIV_CLASS_MAX
12146     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
12147 #endif
12148 #ifdef _SC_EXPR_NEST_MAX
12149     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
12150 #endif
12151 #ifdef _SC_FSYNC
12152     {"SC_FSYNC",        _SC_FSYNC},
12153 #endif
12154 #ifdef _SC_GETGR_R_SIZE_MAX
12155     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
12156 #endif
12157 #ifdef _SC_GETPW_R_SIZE_MAX
12158     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
12159 #endif
12160 #ifdef _SC_ICACHE_ASSOC
12161     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12162 #endif
12163 #ifdef _SC_ICACHE_BLKSZ
12164     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12165 #endif
12166 #ifdef _SC_ICACHE_LINESZ
12167     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
12168 #endif
12169 #ifdef _SC_ICACHE_SZ
12170     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
12171 #endif
12172 #ifdef _SC_INF
12173     {"SC_INF",  _SC_INF},
12174 #endif
12175 #ifdef _SC_INT_MAX
12176     {"SC_INT_MAX",      _SC_INT_MAX},
12177 #endif
12178 #ifdef _SC_INT_MIN
12179     {"SC_INT_MIN",      _SC_INT_MIN},
12180 #endif
12181 #ifdef _SC_IOV_MAX
12182     {"SC_IOV_MAX",      _SC_IOV_MAX},
12183 #endif
12184 #ifdef _SC_IP_SECOPTS
12185     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
12186 #endif
12187 #ifdef _SC_JOB_CONTROL
12188     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
12189 #endif
12190 #ifdef _SC_KERN_POINTERS
12191     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
12192 #endif
12193 #ifdef _SC_KERN_SIM
12194     {"SC_KERN_SIM",     _SC_KERN_SIM},
12195 #endif
12196 #ifdef _SC_LINE_MAX
12197     {"SC_LINE_MAX",     _SC_LINE_MAX},
12198 #endif
12199 #ifdef _SC_LOGIN_NAME_MAX
12200     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
12201 #endif
12202 #ifdef _SC_LOGNAME_MAX
12203     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
12204 #endif
12205 #ifdef _SC_LONG_BIT
12206     {"SC_LONG_BIT",     _SC_LONG_BIT},
12207 #endif
12208 #ifdef _SC_MAC
12209     {"SC_MAC",  _SC_MAC},
12210 #endif
12211 #ifdef _SC_MAPPED_FILES
12212     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12213 #endif
12214 #ifdef _SC_MAXPID
12215     {"SC_MAXPID",       _SC_MAXPID},
12216 #endif
12217 #ifdef _SC_MB_LEN_MAX
12218     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
12219 #endif
12220 #ifdef _SC_MEMLOCK
12221     {"SC_MEMLOCK",      _SC_MEMLOCK},
12222 #endif
12223 #ifdef _SC_MEMLOCK_RANGE
12224     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
12225 #endif
12226 #ifdef _SC_MEMORY_PROTECTION
12227     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
12228 #endif
12229 #ifdef _SC_MESSAGE_PASSING
12230     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
12231 #endif
12232 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12233     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12234 #endif
12235 #ifdef _SC_MQ_OPEN_MAX
12236     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
12237 #endif
12238 #ifdef _SC_MQ_PRIO_MAX
12239     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
12240 #endif
12241 #ifdef _SC_NACLS_MAX
12242     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
12243 #endif
12244 #ifdef _SC_NGROUPS_MAX
12245     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
12246 #endif
12247 #ifdef _SC_NL_ARGMAX
12248     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
12249 #endif
12250 #ifdef _SC_NL_LANGMAX
12251     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
12252 #endif
12253 #ifdef _SC_NL_MSGMAX
12254     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
12255 #endif
12256 #ifdef _SC_NL_NMAX
12257     {"SC_NL_NMAX",      _SC_NL_NMAX},
12258 #endif
12259 #ifdef _SC_NL_SETMAX
12260     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
12261 #endif
12262 #ifdef _SC_NL_TEXTMAX
12263     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
12264 #endif
12265 #ifdef _SC_NPROCESSORS_CONF
12266     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
12267 #endif
12268 #ifdef _SC_NPROCESSORS_ONLN
12269     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
12270 #endif
12271 #ifdef _SC_NPROC_CONF
12272     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
12273 #endif
12274 #ifdef _SC_NPROC_ONLN
12275     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
12276 #endif
12277 #ifdef _SC_NZERO
12278     {"SC_NZERO",        _SC_NZERO},
12279 #endif
12280 #ifdef _SC_OPEN_MAX
12281     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
12282 #endif
12283 #ifdef _SC_PAGESIZE
12284     {"SC_PAGESIZE",     _SC_PAGESIZE},
12285 #endif
12286 #ifdef _SC_PAGE_SIZE
12287     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
12288 #endif
12289 #ifdef _SC_AIX_REALMEM
12290     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12291 #endif
12292 #ifdef _SC_PASS_MAX
12293     {"SC_PASS_MAX",     _SC_PASS_MAX},
12294 #endif
12295 #ifdef _SC_PHYS_PAGES
12296     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
12297 #endif
12298 #ifdef _SC_PII
12299     {"SC_PII",  _SC_PII},
12300 #endif
12301 #ifdef _SC_PII_INTERNET
12302     {"SC_PII_INTERNET", _SC_PII_INTERNET},
12303 #endif
12304 #ifdef _SC_PII_INTERNET_DGRAM
12305     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
12306 #endif
12307 #ifdef _SC_PII_INTERNET_STREAM
12308     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
12309 #endif
12310 #ifdef _SC_PII_OSI
12311     {"SC_PII_OSI",      _SC_PII_OSI},
12312 #endif
12313 #ifdef _SC_PII_OSI_CLTS
12314     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12315 #endif
12316 #ifdef _SC_PII_OSI_COTS
12317     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12318 #endif
12319 #ifdef _SC_PII_OSI_M
12320     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
12321 #endif
12322 #ifdef _SC_PII_SOCKET
12323     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
12324 #endif
12325 #ifdef _SC_PII_XTI
12326     {"SC_PII_XTI",      _SC_PII_XTI},
12327 #endif
12328 #ifdef _SC_POLL
12329     {"SC_POLL", _SC_POLL},
12330 #endif
12331 #ifdef _SC_PRIORITIZED_IO
12332     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
12333 #endif
12334 #ifdef _SC_PRIORITY_SCHEDULING
12335     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
12336 #endif
12337 #ifdef _SC_REALTIME_SIGNALS
12338     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
12339 #endif
12340 #ifdef _SC_RE_DUP_MAX
12341     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
12342 #endif
12343 #ifdef _SC_RTSIG_MAX
12344     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
12345 #endif
12346 #ifdef _SC_SAVED_IDS
12347     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
12348 #endif
12349 #ifdef _SC_SCHAR_MAX
12350     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
12351 #endif
12352 #ifdef _SC_SCHAR_MIN
12353     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
12354 #endif
12355 #ifdef _SC_SELECT
12356     {"SC_SELECT",       _SC_SELECT},
12357 #endif
12358 #ifdef _SC_SEMAPHORES
12359     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12360 #endif
12361 #ifdef _SC_SEM_NSEMS_MAX
12362     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12363 #endif
12364 #ifdef _SC_SEM_VALUE_MAX
12365     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12366 #endif
12367 #ifdef _SC_SHARED_MEMORY_OBJECTS
12368     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12369 #endif
12370 #ifdef _SC_SHRT_MAX
12371     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12372 #endif
12373 #ifdef _SC_SHRT_MIN
12374     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12375 #endif
12376 #ifdef _SC_SIGQUEUE_MAX
12377     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12378 #endif
12379 #ifdef _SC_SIGRT_MAX
12380     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12381 #endif
12382 #ifdef _SC_SIGRT_MIN
12383     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12384 #endif
12385 #ifdef _SC_SOFTPOWER
12386     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12387 #endif
12388 #ifdef _SC_SPLIT_CACHE
12389     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12390 #endif
12391 #ifdef _SC_SSIZE_MAX
12392     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12393 #endif
12394 #ifdef _SC_STACK_PROT
12395     {"SC_STACK_PROT",   _SC_STACK_PROT},
12396 #endif
12397 #ifdef _SC_STREAM_MAX
12398     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12399 #endif
12400 #ifdef _SC_SYNCHRONIZED_IO
12401     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12402 #endif
12403 #ifdef _SC_THREADS
12404     {"SC_THREADS",      _SC_THREADS},
12405 #endif
12406 #ifdef _SC_THREAD_ATTR_STACKADDR
12407     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12408 #endif
12409 #ifdef _SC_THREAD_ATTR_STACKSIZE
12410     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12411 #endif
12412 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12413     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12414 #endif
12415 #ifdef _SC_THREAD_KEYS_MAX
12416     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12417 #endif
12418 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12419     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12420 #endif
12421 #ifdef _SC_THREAD_PRIO_INHERIT
12422     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12423 #endif
12424 #ifdef _SC_THREAD_PRIO_PROTECT
12425     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12426 #endif
12427 #ifdef _SC_THREAD_PROCESS_SHARED
12428     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12429 #endif
12430 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12431     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12432 #endif
12433 #ifdef _SC_THREAD_STACK_MIN
12434     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12435 #endif
12436 #ifdef _SC_THREAD_THREADS_MAX
12437     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12438 #endif
12439 #ifdef _SC_TIMERS
12440     {"SC_TIMERS",       _SC_TIMERS},
12441 #endif
12442 #ifdef _SC_TIMER_MAX
12443     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12444 #endif
12445 #ifdef _SC_TTY_NAME_MAX
12446     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12447 #endif
12448 #ifdef _SC_TZNAME_MAX
12449     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12450 #endif
12451 #ifdef _SC_T_IOV_MAX
12452     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12453 #endif
12454 #ifdef _SC_UCHAR_MAX
12455     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12456 #endif
12457 #ifdef _SC_UINT_MAX
12458     {"SC_UINT_MAX",     _SC_UINT_MAX},
12459 #endif
12460 #ifdef _SC_UIO_MAXIOV
12461     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12462 #endif
12463 #ifdef _SC_ULONG_MAX
12464     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12465 #endif
12466 #ifdef _SC_USHRT_MAX
12467     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12468 #endif
12469 #ifdef _SC_VERSION
12470     {"SC_VERSION",      _SC_VERSION},
12471 #endif
12472 #ifdef _SC_WORD_BIT
12473     {"SC_WORD_BIT",     _SC_WORD_BIT},
12474 #endif
12475 #ifdef _SC_XBS5_ILP32_OFF32
12476     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12477 #endif
12478 #ifdef _SC_XBS5_ILP32_OFFBIG
12479     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12480 #endif
12481 #ifdef _SC_XBS5_LP64_OFF64
12482     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12483 #endif
12484 #ifdef _SC_XBS5_LPBIG_OFFBIG
12485     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12486 #endif
12487 #ifdef _SC_XOPEN_CRYPT
12488     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12489 #endif
12490 #ifdef _SC_XOPEN_ENH_I18N
12491     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12492 #endif
12493 #ifdef _SC_XOPEN_LEGACY
12494     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12495 #endif
12496 #ifdef _SC_XOPEN_REALTIME
12497     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12498 #endif
12499 #ifdef _SC_XOPEN_REALTIME_THREADS
12500     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12501 #endif
12502 #ifdef _SC_XOPEN_SHM
12503     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12504 #endif
12505 #ifdef _SC_XOPEN_UNIX
12506     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12507 #endif
12508 #ifdef _SC_XOPEN_VERSION
12509     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12510 #endif
12511 #ifdef _SC_XOPEN_XCU_VERSION
12512     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12513 #endif
12514 #ifdef _SC_XOPEN_XPG2
12515     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12516 #endif
12517 #ifdef _SC_XOPEN_XPG3
12518     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12519 #endif
12520 #ifdef _SC_XOPEN_XPG4
12521     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12522 #endif
12523 #ifdef _SC_MINSIGSTKSZ
12524     {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
12525 #endif
12526 };
12527 
12528 static int
conv_sysconf_confname(PyObject *arg, int *valuep)12529 conv_sysconf_confname(PyObject *arg, int *valuep)
12530 {
12531     return conv_confname(arg, valuep, posix_constants_sysconf,
12532                          sizeof(posix_constants_sysconf)
12533                            / sizeof(struct constdef));
12534 }
12535 
12536 
12537 /*[clinic input]
12538 os.sysconf -> long
12539     name: sysconf_confname
12540     /
12541 
12542 Return an integer-valued system configuration variable.
12543 [clinic start generated code]*/
12544 
12545 static long
os_sysconf_impl(PyObject *module, int name)12546 os_sysconf_impl(PyObject *module, int name)
12547 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12548 {
12549     long value;
12550 
12551     errno = 0;
12552     value = sysconf(name);
12553     if (value == -1 && errno != 0)
12554         posix_error();
12555     return value;
12556 }
12557 #endif /* HAVE_SYSCONF */
12558 
12559 
12560 /* This code is used to ensure that the tables of configuration value names
12561  * are in sorted order as required by conv_confname(), and also to build
12562  * the exported dictionaries that are used to publish information about the
12563  * names available on the host platform.
12564  *
12565  * Sorting the table at runtime ensures that the table is properly ordered
12566  * when used, even for platforms we're not able to test on.  It also makes
12567  * it easier to add additional entries to the tables.
12568  */
12569 
12570 static int
cmp_constdefs(const void *v1, const void *v2)12571 cmp_constdefs(const void *v1,  const void *v2)
12572 {
12573     const struct constdef *c1 =
12574     (const struct constdef *) v1;
12575     const struct constdef *c2 =
12576     (const struct constdef *) v2;
12577 
12578     return strcmp(c1->name, c2->name);
12579 }
12580 
12581 static int
setup_confname_table(struct constdef *table, size_t tablesize, const char *tablename, PyObject *module)12582 setup_confname_table(struct constdef *table, size_t tablesize,
12583                      const char *tablename, PyObject *module)
12584 {
12585     PyObject *d = NULL;
12586     size_t i;
12587 
12588     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12589     d = PyDict_New();
12590     if (d == NULL)
12591         return -1;
12592 
12593     for (i=0; i < tablesize; ++i) {
12594         PyObject *o = PyLong_FromLong(table[i].value);
12595         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12596             Py_XDECREF(o);
12597             Py_DECREF(d);
12598             return -1;
12599         }
12600         Py_DECREF(o);
12601     }
12602     return PyModule_AddObject(module, tablename, d);
12603 }
12604 
12605 /* Return -1 on failure, 0 on success. */
12606 static int
setup_confname_tables(PyObject *module)12607 setup_confname_tables(PyObject *module)
12608 {
12609 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12610     if (setup_confname_table(posix_constants_pathconf,
12611                              sizeof(posix_constants_pathconf)
12612                                / sizeof(struct constdef),
12613                              "pathconf_names", module))
12614         return -1;
12615 #endif
12616 #ifdef HAVE_CONFSTR
12617     if (setup_confname_table(posix_constants_confstr,
12618                              sizeof(posix_constants_confstr)
12619                                / sizeof(struct constdef),
12620                              "confstr_names", module))
12621         return -1;
12622 #endif
12623 #ifdef HAVE_SYSCONF
12624     if (setup_confname_table(posix_constants_sysconf,
12625                              sizeof(posix_constants_sysconf)
12626                                / sizeof(struct constdef),
12627                              "sysconf_names", module))
12628         return -1;
12629 #endif
12630     return 0;
12631 }
12632 
12633 
12634 /*[clinic input]
12635 os.abort
12636 
12637 Abort the interpreter immediately.
12638 
12639 This function 'dumps core' or otherwise fails in the hardest way possible
12640 on the hosting operating system.  This function never returns.
12641 [clinic start generated code]*/
12642 
12643 static PyObject *
os_abort_impl(PyObject *module)12644 os_abort_impl(PyObject *module)
12645 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12646 {
12647     abort();
12648     /*NOTREACHED*/
12649 #ifndef __clang__
12650     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12651        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12652        is smarter and emits a warning on the return. */
12653     Py_FatalError("abort() called from Python code didn't abort!");
12654     return NULL;
12655 #endif
12656 }
12657 
12658 #ifdef MS_WINDOWS
12659 /* Grab ShellExecute dynamically from shell32 */
12660 static int has_ShellExecute = -1;
12661 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12662                                               LPCWSTR, INT);
12663 static int
check_ShellExecutenull12664 check_ShellExecute()
12665 {
12666     HINSTANCE hShell32;
12667 
12668     /* only recheck */
12669     if (-1 == has_ShellExecute) {
12670         Py_BEGIN_ALLOW_THREADS
12671         /* Security note: this call is not vulnerable to "DLL hijacking".
12672            SHELL32 is part of "KnownDLLs" and so Windows always load
12673            the system SHELL32.DLL, even if there is another SHELL32.DLL
12674            in the DLL search path. */
12675         hShell32 = LoadLibraryW(L"SHELL32");
12676         if (hShell32) {
12677             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12678                                             "ShellExecuteW");
12679             has_ShellExecute = Py_ShellExecuteW != NULL;
12680         } else {
12681             has_ShellExecute = 0;
12682         }
12683         Py_END_ALLOW_THREADS
12684     }
12685     return has_ShellExecute;
12686 }
12687 
12688 
12689 /*[clinic input]
12690 os.startfile
12691     filepath: path_t
12692     operation: Py_UNICODE = NULL
12693     arguments: Py_UNICODE = NULL
12694     cwd: path_t(nullable=True) = None
12695     show_cmd: int = 1
12696 
12697 Start a file with its associated application.
12698 
12699 When "operation" is not specified or "open", this acts like
12700 double-clicking the file in Explorer, or giving the file name as an
12701 argument to the DOS "start" command: the file is opened with whatever
12702 application (if any) its extension is associated.
12703 When another "operation" is given, it specifies what should be done with
12704 the file.  A typical operation is "print".
12705 
12706 "arguments" is passed to the application, but should be omitted if the
12707 file is a document.
12708 
12709 "cwd" is the working directory for the operation. If "filepath" is
12710 relative, it will be resolved against this directory. This argument
12711 should usually be an absolute path.
12712 
12713 "show_cmd" can be used to override the recommended visibility option.
12714 See the Windows ShellExecute documentation for values.
12715 
12716 startfile returns as soon as the associated application is launched.
12717 There is no option to wait for the application to close, and no way
12718 to retrieve the application's exit status.
12719 
12720 The filepath is relative to the current directory.  If you want to use
12721 an absolute path, make sure the first character is not a slash ("/");
12722 the underlying Win32 ShellExecute function doesn't work if it is.
12723 [clinic start generated code]*/
12724 
12725 static PyObject *
os_startfile_impl(PyObject *module, path_t *filepath, const Py_UNICODE *operation, const Py_UNICODE *arguments, path_t *cwd, int show_cmd)12726 os_startfile_impl(PyObject *module, path_t *filepath,
12727                   const Py_UNICODE *operation, const Py_UNICODE *arguments,
12728                   path_t *cwd, int show_cmd)
12729 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12730 {
12731     HINSTANCE rc;
12732 
12733     if(!check_ShellExecute()) {
12734         /* If the OS doesn't have ShellExecute, return a
12735            NotImplementedError. */
12736         return PyErr_Format(PyExc_NotImplementedError,
12737             "startfile not available on this platform");
12738     }
12739 
12740     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12741         return NULL;
12742     }
12743     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12744                     arguments, cwd->object ? cwd->object : Py_None,
12745                     show_cmd) < 0) {
12746         return NULL;
12747     }
12748 
12749     Py_BEGIN_ALLOW_THREADS
12750     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12751                           arguments, cwd->wide, show_cmd);
12752     Py_END_ALLOW_THREADS
12753 
12754     if (rc <= (HINSTANCE)32) {
12755         win32_error_object("startfile", filepath->object);
12756         return NULL;
12757     }
12758     Py_RETURN_NONE;
12759 }
12760 #endif /* MS_WINDOWS */
12761 
12762 
12763 #ifdef HAVE_GETLOADAVG
12764 /*[clinic input]
12765 os.getloadavg
12766 
12767 Return average recent system load information.
12768 
12769 Return the number of processes in the system run queue averaged over
12770 the last 1, 5, and 15 minutes as a tuple of three floats.
12771 Raises OSError if the load average was unobtainable.
12772 [clinic start generated code]*/
12773 
12774 static PyObject *
os_getloadavg_impl(PyObject *module)12775 os_getloadavg_impl(PyObject *module)
12776 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12777 {
12778     double loadavg[3];
12779     if (getloadavg(loadavg, 3)!=3) {
12780         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12781         return NULL;
12782     } else
12783         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12784 }
12785 #endif /* HAVE_GETLOADAVG */
12786 
12787 
12788 /*[clinic input]
12789 os.device_encoding
12790     fd: int
12791 
12792 Return a string describing the encoding of a terminal's file descriptor.
12793 
12794 The file descriptor must be attached to a terminal.
12795 If the device is not a terminal, return None.
12796 [clinic start generated code]*/
12797 
12798 static PyObject *
os_device_encoding_impl(PyObject *module, int fd)12799 os_device_encoding_impl(PyObject *module, int fd)
12800 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12801 {
12802     return _Py_device_encoding(fd);
12803 }
12804 
12805 
12806 #ifdef HAVE_SETRESUID
12807 /*[clinic input]
12808 os.setresuid
12809 
12810     ruid: uid_t
12811     euid: uid_t
12812     suid: uid_t
12813     /
12814 
12815 Set the current process's real, effective, and saved user ids.
12816 [clinic start generated code]*/
12817 
12818 static PyObject *
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)12819 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12820 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12821 {
12822     if (setresuid(ruid, euid, suid) < 0)
12823         return posix_error();
12824     Py_RETURN_NONE;
12825 }
12826 #endif /* HAVE_SETRESUID */
12827 
12828 
12829 #ifdef HAVE_SETRESGID
12830 /*[clinic input]
12831 os.setresgid
12832 
12833     rgid: gid_t
12834     egid: gid_t
12835     sgid: gid_t
12836     /
12837 
12838 Set the current process's real, effective, and saved group ids.
12839 [clinic start generated code]*/
12840 
12841 static PyObject *
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)12842 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12843 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12844 {
12845     if (setresgid(rgid, egid, sgid) < 0)
12846         return posix_error();
12847     Py_RETURN_NONE;
12848 }
12849 #endif /* HAVE_SETRESGID */
12850 
12851 
12852 #ifdef HAVE_GETRESUID
12853 /*[clinic input]
12854 os.getresuid
12855 
12856 Return a tuple of the current process's real, effective, and saved user ids.
12857 [clinic start generated code]*/
12858 
12859 static PyObject *
os_getresuid_impl(PyObject *module)12860 os_getresuid_impl(PyObject *module)
12861 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12862 {
12863     uid_t ruid, euid, suid;
12864     if (getresuid(&ruid, &euid, &suid) < 0)
12865         return posix_error();
12866     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12867                                   _PyLong_FromUid(euid),
12868                                   _PyLong_FromUid(suid));
12869 }
12870 #endif /* HAVE_GETRESUID */
12871 
12872 
12873 #ifdef HAVE_GETRESGID
12874 /*[clinic input]
12875 os.getresgid
12876 
12877 Return a tuple of the current process's real, effective, and saved group ids.
12878 [clinic start generated code]*/
12879 
12880 static PyObject *
os_getresgid_impl(PyObject *module)12881 os_getresgid_impl(PyObject *module)
12882 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12883 {
12884     gid_t rgid, egid, sgid;
12885     if (getresgid(&rgid, &egid, &sgid) < 0)
12886         return posix_error();
12887     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12888                                   _PyLong_FromGid(egid),
12889                                   _PyLong_FromGid(sgid));
12890 }
12891 #endif /* HAVE_GETRESGID */
12892 
12893 
12894 #ifdef USE_XATTRS
12895 /*[clinic input]
12896 os.getxattr
12897 
12898     path: path_t(allow_fd=True)
12899     attribute: path_t
12900     *
12901     follow_symlinks: bool = True
12902 
12903 Return the value of extended attribute attribute on path.
12904 
12905 path may be either a string, a path-like object, or an open file descriptor.
12906 If follow_symlinks is False, and the last element of the path is a symbolic
12907   link, getxattr will examine the symbolic link itself instead of the file
12908   the link points to.
12909 
12910 [clinic start generated code]*/
12911 
12912 static PyObject *
os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks)12913 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12914                  int follow_symlinks)
12915 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12916 {
12917     Py_ssize_t i;
12918     PyObject *buffer = NULL;
12919 
12920     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12921         return NULL;
12922 
12923     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12924         return NULL;
12925     }
12926 
12927     for (i = 0; ; i++) {
12928         void *ptr;
12929         ssize_t result;
12930         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12931         Py_ssize_t buffer_size = buffer_sizes[i];
12932         if (!buffer_size) {
12933             path_error(path);
12934             return NULL;
12935         }
12936         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12937         if (!buffer)
12938             return NULL;
12939         ptr = PyBytes_AS_STRING(buffer);
12940 
12941         Py_BEGIN_ALLOW_THREADS;
12942         if (path->fd >= 0)
12943             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12944         else if (follow_symlinks)
12945             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12946         else
12947             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12948         Py_END_ALLOW_THREADS;
12949 
12950         if (result < 0) {
12951             Py_DECREF(buffer);
12952             if (errno == ERANGE)
12953                 continue;
12954             path_error(path);
12955             return NULL;
12956         }
12957 
12958         if (result != buffer_size) {
12959             /* Can only shrink. */
12960             _PyBytes_Resize(&buffer, result);
12961         }
12962         break;
12963     }
12964 
12965     return buffer;
12966 }
12967 
12968 
12969 /*[clinic input]
12970 os.setxattr
12971 
12972     path: path_t(allow_fd=True)
12973     attribute: path_t
12974     value: Py_buffer
12975     flags: int = 0
12976     *
12977     follow_symlinks: bool = True
12978 
12979 Set extended attribute attribute on path to value.
12980 
12981 path may be either a string, a path-like object,  or an open file descriptor.
12982 If follow_symlinks is False, and the last element of the path is a symbolic
12983   link, setxattr will modify the symbolic link itself instead of the file
12984   the link points to.
12985 
12986 [clinic start generated code]*/
12987 
12988 static PyObject *
os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks)12989 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12990                  Py_buffer *value, int flags, int follow_symlinks)
12991 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12992 {
12993     ssize_t result;
12994 
12995     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12996         return NULL;
12997 
12998     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12999                     value->buf, value->len, flags) < 0) {
13000         return NULL;
13001     }
13002 
13003     Py_BEGIN_ALLOW_THREADS;
13004     if (path->fd > -1)
13005         result = fsetxattr(path->fd, attribute->narrow,
13006                            value->buf, value->len, flags);
13007     else if (follow_symlinks)
13008         result = setxattr(path->narrow, attribute->narrow,
13009                            value->buf, value->len, flags);
13010     else
13011         result = lsetxattr(path->narrow, attribute->narrow,
13012                            value->buf, value->len, flags);
13013     Py_END_ALLOW_THREADS;
13014 
13015     if (result) {
13016         path_error(path);
13017         return NULL;
13018     }
13019 
13020     Py_RETURN_NONE;
13021 }
13022 
13023 
13024 /*[clinic input]
13025 os.removexattr
13026 
13027     path: path_t(allow_fd=True)
13028     attribute: path_t
13029     *
13030     follow_symlinks: bool = True
13031 
13032 Remove extended attribute attribute on path.
13033 
13034 path may be either a string, a path-like object, or an open file descriptor.
13035 If follow_symlinks is False, and the last element of the path is a symbolic
13036   link, removexattr will modify the symbolic link itself instead of the file
13037   the link points to.
13038 
13039 [clinic start generated code]*/
13040 
13041 static PyObject *
os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute, int follow_symlinks)13042 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13043                     int follow_symlinks)
13044 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13045 {
13046     ssize_t result;
13047 
13048     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13049         return NULL;
13050 
13051     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13052         return NULL;
13053     }
13054 
13055     Py_BEGIN_ALLOW_THREADS;
13056     if (path->fd > -1)
13057         result = fremovexattr(path->fd, attribute->narrow);
13058     else if (follow_symlinks)
13059         result = removexattr(path->narrow, attribute->narrow);
13060     else
13061         result = lremovexattr(path->narrow, attribute->narrow);
13062     Py_END_ALLOW_THREADS;
13063 
13064     if (result) {
13065         return path_error(path);
13066     }
13067 
13068     Py_RETURN_NONE;
13069 }
13070 
13071 
13072 /*[clinic input]
13073 os.listxattr
13074 
13075     path: path_t(allow_fd=True, nullable=True) = None
13076     *
13077     follow_symlinks: bool = True
13078 
13079 Return a list of extended attributes on path.
13080 
13081 path may be either None, a string, a path-like object, or an open file descriptor.
13082 if path is None, listxattr will examine the current directory.
13083 If follow_symlinks is False, and the last element of the path is a symbolic
13084   link, listxattr will examine the symbolic link itself instead of the file
13085   the link points to.
13086 [clinic start generated code]*/
13087 
13088 static PyObject *
os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)13089 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13090 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13091 {
13092     Py_ssize_t i;
13093     PyObject *result = NULL;
13094     const char *name;
13095     char *buffer = NULL;
13096 
13097     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13098         goto exit;
13099 
13100     if (PySys_Audit("os.listxattr", "(O)",
13101                     path->object ? path->object : Py_None) < 0) {
13102         return NULL;
13103     }
13104 
13105     name = path->narrow ? path->narrow : ".";
13106 
13107     for (i = 0; ; i++) {
13108         const char *start, *trace, *end;
13109         ssize_t length;
13110         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13111         Py_ssize_t buffer_size = buffer_sizes[i];
13112         if (!buffer_size) {
13113             /* ERANGE */
13114             path_error(path);
13115             break;
13116         }
13117         buffer = PyMem_Malloc(buffer_size);
13118         if (!buffer) {
13119             PyErr_NoMemory();
13120             break;
13121         }
13122 
13123         Py_BEGIN_ALLOW_THREADS;
13124         if (path->fd > -1)
13125             length = flistxattr(path->fd, buffer, buffer_size);
13126         else if (follow_symlinks)
13127             length = listxattr(name, buffer, buffer_size);
13128         else
13129             length = llistxattr(name, buffer, buffer_size);
13130         Py_END_ALLOW_THREADS;
13131 
13132         if (length < 0) {
13133             if (errno == ERANGE) {
13134                 PyMem_Free(buffer);
13135                 buffer = NULL;
13136                 continue;
13137             }
13138             path_error(path);
13139             break;
13140         }
13141 
13142         result = PyList_New(0);
13143         if (!result) {
13144             goto exit;
13145         }
13146 
13147         end = buffer + length;
13148         for (trace = start = buffer; trace != end; trace++) {
13149             if (!*trace) {
13150                 int error;
13151                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13152                                                                  trace - start);
13153                 if (!attribute) {
13154                     Py_DECREF(result);
13155                     result = NULL;
13156                     goto exit;
13157                 }
13158                 error = PyList_Append(result, attribute);
13159                 Py_DECREF(attribute);
13160                 if (error) {
13161                     Py_DECREF(result);
13162                     result = NULL;
13163                     goto exit;
13164                 }
13165                 start = trace + 1;
13166             }
13167         }
13168     break;
13169     }
13170 exit:
13171     if (buffer)
13172         PyMem_Free(buffer);
13173     return result;
13174 }
13175 #endif /* USE_XATTRS */
13176 
13177 
13178 /*[clinic input]
13179 os.urandom
13180 
13181     size: Py_ssize_t
13182     /
13183 
13184 Return a bytes object containing random bytes suitable for cryptographic use.
13185 [clinic start generated code]*/
13186 
13187 static PyObject *
os_urandom_impl(PyObject *module, Py_ssize_t size)13188 os_urandom_impl(PyObject *module, Py_ssize_t size)
13189 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13190 {
13191     PyObject *bytes;
13192     int result;
13193 
13194     if (size < 0)
13195         return PyErr_Format(PyExc_ValueError,
13196                             "negative argument not allowed");
13197     bytes = PyBytes_FromStringAndSize(NULL, size);
13198     if (bytes == NULL)
13199         return NULL;
13200 
13201     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13202     if (result == -1) {
13203         Py_DECREF(bytes);
13204         return NULL;
13205     }
13206     return bytes;
13207 }
13208 
13209 #ifdef HAVE_MEMFD_CREATE
13210 /*[clinic input]
13211 os.memfd_create
13212 
13213     name: FSConverter
13214     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13215 
13216 [clinic start generated code]*/
13217 
13218 static PyObject *
os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)13219 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13220 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13221 {
13222     int fd;
13223     const char *bytes = PyBytes_AS_STRING(name);
13224     Py_BEGIN_ALLOW_THREADS
13225     fd = memfd_create(bytes, flags);
13226     Py_END_ALLOW_THREADS
13227     if (fd == -1) {
13228         return PyErr_SetFromErrno(PyExc_OSError);
13229     }
13230     return PyLong_FromLong(fd);
13231 }
13232 #endif
13233 
13234 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13235 /*[clinic input]
13236 os.eventfd
13237 
13238     initval: unsigned_int
13239     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13240 
13241 Creates and returns an event notification file descriptor.
13242 [clinic start generated code]*/
13243 
13244 static PyObject *
os_eventfd_impl(PyObject *module, unsigned int initval, int flags)13245 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13246 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13247 
13248 {
13249     /* initval is limited to uint32_t, internal counter is uint64_t */
13250     int fd;
13251     Py_BEGIN_ALLOW_THREADS
13252     fd = eventfd(initval, flags);
13253     Py_END_ALLOW_THREADS
13254     if (fd == -1) {
13255         return PyErr_SetFromErrno(PyExc_OSError);
13256     }
13257     return PyLong_FromLong(fd);
13258 }
13259 
13260 /*[clinic input]
13261 os.eventfd_read
13262 
13263     fd: fildes
13264 
13265 Read eventfd value
13266 [clinic start generated code]*/
13267 
13268 static PyObject *
os_eventfd_read_impl(PyObject *module, int fd)13269 os_eventfd_read_impl(PyObject *module, int fd)
13270 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13271 {
13272     eventfd_t value;
13273     int result;
13274     Py_BEGIN_ALLOW_THREADS
13275     result = eventfd_read(fd, &value);
13276     Py_END_ALLOW_THREADS
13277     if (result == -1) {
13278         return PyErr_SetFromErrno(PyExc_OSError);
13279     }
13280     return PyLong_FromUnsignedLongLong(value);
13281 }
13282 
13283 /*[clinic input]
13284 os.eventfd_write
13285 
13286     fd: fildes
13287     value: unsigned_long_long
13288 
13289 Write eventfd value.
13290 [clinic start generated code]*/
13291 
13292 static PyObject *
os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)13293 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13294 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13295 {
13296     int result;
13297     Py_BEGIN_ALLOW_THREADS
13298     result = eventfd_write(fd, value);
13299     Py_END_ALLOW_THREADS
13300     if (result == -1) {
13301         return PyErr_SetFromErrno(PyExc_OSError);
13302     }
13303     Py_RETURN_NONE;
13304 }
13305 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
13306 
13307 /* Terminal size querying */
13308 
13309 PyDoc_STRVAR(TerminalSize_docstring,
13310     "A tuple of (columns, lines) for holding terminal window size");
13311 
13312 static PyStructSequence_Field TerminalSize_fields[] = {
13313     {"columns", "width of the terminal window in characters"},
13314     {"lines", "height of the terminal window in characters"},
13315     {NULL, NULL}
13316 };
13317 
13318 static PyStructSequence_Desc TerminalSize_desc = {
13319     "os.terminal_size",
13320     TerminalSize_docstring,
13321     TerminalSize_fields,
13322     2,
13323 };
13324 
13325 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13326 /*[clinic input]
13327 os.get_terminal_size
13328 
13329     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13330     /
13331 
13332 Return the size of the terminal window as (columns, lines).
13333 
13334 The optional argument fd (default standard output) specifies
13335 which file descriptor should be queried.
13336 
13337 If the file descriptor is not connected to a terminal, an OSError
13338 is thrown.
13339 
13340 This function will only be defined if an implementation is
13341 available for this system.
13342 
13343 shutil.get_terminal_size is the high-level function which should
13344 normally be used, os.get_terminal_size is the low-level implementation.
13345 [clinic start generated code]*/
13346 
13347 static PyObject *
os_get_terminal_size_impl(PyObject *module, int fd)13348 os_get_terminal_size_impl(PyObject *module, int fd)
13349 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13350 {
13351     int columns, lines;
13352     PyObject *termsize;
13353 
13354     /* Under some conditions stdout may not be connected and
13355      * fileno(stdout) may point to an invalid file descriptor. For example
13356      * GUI apps don't have valid standard streams by default.
13357      *
13358      * If this happens, and the optional fd argument is not present,
13359      * the ioctl below will fail returning EBADF. This is what we want.
13360      */
13361 
13362 #ifdef TERMSIZE_USE_IOCTL
13363     {
13364         struct winsize w;
13365         if (ioctl(fd, TIOCGWINSZ, &w))
13366             return PyErr_SetFromErrno(PyExc_OSError);
13367         columns = w.ws_col;
13368         lines = w.ws_row;
13369     }
13370 #endif /* TERMSIZE_USE_IOCTL */
13371 
13372 #ifdef TERMSIZE_USE_CONIO
13373     {
13374         DWORD nhandle;
13375         HANDLE handle;
13376         CONSOLE_SCREEN_BUFFER_INFO csbi;
13377         switch (fd) {
13378         case 0: nhandle = STD_INPUT_HANDLE;
13379             break;
13380         case 1: nhandle = STD_OUTPUT_HANDLE;
13381             break;
13382         case 2: nhandle = STD_ERROR_HANDLE;
13383             break;
13384         default:
13385             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13386         }
13387         handle = GetStdHandle(nhandle);
13388         if (handle == NULL)
13389             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13390         if (handle == INVALID_HANDLE_VALUE)
13391             return PyErr_SetFromWindowsErr(0);
13392 
13393         if (!GetConsoleScreenBufferInfo(handle, &csbi))
13394             return PyErr_SetFromWindowsErr(0);
13395 
13396         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13397         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13398     }
13399 #endif /* TERMSIZE_USE_CONIO */
13400 
13401     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13402     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13403     if (termsize == NULL)
13404         return NULL;
13405     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13406     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13407     if (PyErr_Occurred()) {
13408         Py_DECREF(termsize);
13409         return NULL;
13410     }
13411     return termsize;
13412 }
13413 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13414 
13415 
13416 /*[clinic input]
13417 os.cpu_count
13418 
13419 Return the number of CPUs in the system; return None if indeterminable.
13420 
13421 This number is not equivalent to the number of CPUs the current process can
13422 use.  The number of usable CPUs can be obtained with
13423 ``len(os.sched_getaffinity(0))``
13424 [clinic start generated code]*/
13425 
13426 static PyObject *
os_cpu_count_impl(PyObject *module)13427 os_cpu_count_impl(PyObject *module)
13428 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13429 {
13430     int ncpu = 0;
13431 #ifdef MS_WINDOWS
13432     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13433 #elif defined(__hpux)
13434     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13435 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13436     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13437 #elif defined(__VXWORKS__)
13438     ncpu = _Py_popcount32(vxCpuEnabledGet());
13439 #elif defined(__DragonFly__) || \
13440       defined(__OpenBSD__)   || \
13441       defined(__FreeBSD__)   || \
13442       defined(__NetBSD__)    || \
13443       defined(__APPLE__)
13444     int mib[2];
13445     size_t len = sizeof(ncpu);
13446     mib[0] = CTL_HW;
13447     mib[1] = HW_NCPU;
13448     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13449         ncpu = 0;
13450 #endif
13451     if (ncpu >= 1)
13452         return PyLong_FromLong(ncpu);
13453     else
13454         Py_RETURN_NONE;
13455 }
13456 
13457 
13458 /*[clinic input]
13459 os.get_inheritable -> bool
13460 
13461     fd: int
13462     /
13463 
13464 Get the close-on-exe flag of the specified file descriptor.
13465 [clinic start generated code]*/
13466 
13467 static int
os_get_inheritable_impl(PyObject *module, int fd)13468 os_get_inheritable_impl(PyObject *module, int fd)
13469 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13470 {
13471     int return_value;
13472     _Py_BEGIN_SUPPRESS_IPH
13473     return_value = _Py_get_inheritable(fd);
13474     _Py_END_SUPPRESS_IPH
13475     return return_value;
13476 }
13477 
13478 
13479 /*[clinic input]
13480 os.set_inheritable
13481     fd: int
13482     inheritable: int
13483     /
13484 
13485 Set the inheritable flag of the specified file descriptor.
13486 [clinic start generated code]*/
13487 
13488 static PyObject *
os_set_inheritable_impl(PyObject *module, int fd, int inheritable)13489 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13490 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13491 {
13492     int result;
13493 
13494     _Py_BEGIN_SUPPRESS_IPH
13495     result = _Py_set_inheritable(fd, inheritable, NULL);
13496     _Py_END_SUPPRESS_IPH
13497     if (result < 0)
13498         return NULL;
13499     Py_RETURN_NONE;
13500 }
13501 
13502 
13503 #ifdef MS_WINDOWS
13504 /*[clinic input]
13505 os.get_handle_inheritable -> bool
13506     handle: intptr_t
13507     /
13508 
13509 Get the close-on-exe flag of the specified file descriptor.
13510 [clinic start generated code]*/
13511 
13512 static int
os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)13513 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13514 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13515 {
13516     DWORD flags;
13517 
13518     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13519         PyErr_SetFromWindowsErr(0);
13520         return -1;
13521     }
13522 
13523     return flags & HANDLE_FLAG_INHERIT;
13524 }
13525 
13526 
13527 /*[clinic input]
13528 os.set_handle_inheritable
13529     handle: intptr_t
13530     inheritable: bool
13531     /
13532 
13533 Set the inheritable flag of the specified handle.
13534 [clinic start generated code]*/
13535 
13536 static PyObject *
os_set_handle_inheritable_impl(PyObject *module, intptr_t handle, int inheritable)13537 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13538                                int inheritable)
13539 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13540 {
13541     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13542     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13543         PyErr_SetFromWindowsErr(0);
13544         return NULL;
13545     }
13546     Py_RETURN_NONE;
13547 }
13548 #endif /* MS_WINDOWS */
13549 
13550 #ifndef MS_WINDOWS
13551 /*[clinic input]
13552 os.get_blocking -> bool
13553     fd: int
13554     /
13555 
13556 Get the blocking mode of the file descriptor.
13557 
13558 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13559 [clinic start generated code]*/
13560 
13561 static int
os_get_blocking_impl(PyObject *module, int fd)13562 os_get_blocking_impl(PyObject *module, int fd)
13563 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13564 {
13565     int blocking;
13566 
13567     _Py_BEGIN_SUPPRESS_IPH
13568     blocking = _Py_get_blocking(fd);
13569     _Py_END_SUPPRESS_IPH
13570     return blocking;
13571 }
13572 
13573 /*[clinic input]
13574 os.set_blocking
13575     fd: int
13576     blocking: bool(accept={int})
13577     /
13578 
13579 Set the blocking mode of the specified file descriptor.
13580 
13581 Set the O_NONBLOCK flag if blocking is False,
13582 clear the O_NONBLOCK flag otherwise.
13583 [clinic start generated code]*/
13584 
13585 static PyObject *
os_set_blocking_impl(PyObject *module, int fd, int blocking)13586 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13587 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13588 {
13589     int result;
13590 
13591     _Py_BEGIN_SUPPRESS_IPH
13592     result = _Py_set_blocking(fd, blocking);
13593     _Py_END_SUPPRESS_IPH
13594     if (result < 0)
13595         return NULL;
13596     Py_RETURN_NONE;
13597 }
13598 #endif   /* !MS_WINDOWS */
13599 
13600 
13601 /*[clinic input]
13602 class os.DirEntry "DirEntry *" "DirEntryType"
13603 [clinic start generated code]*/
13604 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13605 
13606 typedef struct {
13607     PyObject_HEAD
13608     PyObject *name;
13609     PyObject *path;
13610     PyObject *stat;
13611     PyObject *lstat;
13612 #ifdef MS_WINDOWS
13613     struct _Py_stat_struct win32_lstat;
13614     uint64_t win32_file_index;
13615     int got_file_index;
13616 #else /* POSIX */
13617 #ifdef HAVE_DIRENT_D_TYPE
13618     unsigned char d_type;
13619 #endif
13620     ino_t d_ino;
13621     int dir_fd;
13622 #endif
13623 } DirEntry;
13624 
13625 static void
DirEntry_dealloc(DirEntry *entry)13626 DirEntry_dealloc(DirEntry *entry)
13627 {
13628     PyTypeObject *tp = Py_TYPE(entry);
13629     Py_XDECREF(entry->name);
13630     Py_XDECREF(entry->path);
13631     Py_XDECREF(entry->stat);
13632     Py_XDECREF(entry->lstat);
13633     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13634     free_func(entry);
13635     Py_DECREF(tp);
13636 }
13637 
13638 /* Forward reference */
13639 static int
13640 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13641                    int follow_symlinks, unsigned short mode_bits);
13642 
13643 /*[clinic input]
13644 os.DirEntry.is_symlink -> bool
13645     defining_class: defining_class
13646     /
13647 
13648 Return True if the entry is a symbolic link; cached per entry.
13649 [clinic start generated code]*/
13650 
13651 static int
os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)13652 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13653 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13654 {
13655 #ifdef MS_WINDOWS
13656     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13657 #elif defined(HAVE_DIRENT_D_TYPE)
13658     /* POSIX */
13659     if (self->d_type != DT_UNKNOWN)
13660         return self->d_type == DT_LNK;
13661     else
13662         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13663 #else
13664     /* POSIX without d_type */
13665     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13666 #endif
13667 }
13668 
13669 static PyObject *
DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)13670 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13671 {
13672     int result;
13673     STRUCT_STAT st;
13674     PyObject *ub;
13675 
13676 #ifdef MS_WINDOWS
13677     if (!PyUnicode_FSDecoder(self->path, &ub))
13678         return NULL;
13679 #if USE_UNICODE_WCHAR_CACHE
13680 _Py_COMP_DIAG_PUSH
13681 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13682     const wchar_t *path = PyUnicode_AsUnicode(ub);
13683 _Py_COMP_DIAG_POP
13684 #else /* USE_UNICODE_WCHAR_CACHE */
13685     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13686     Py_DECREF(ub);
13687 #endif /* USE_UNICODE_WCHAR_CACHE */
13688 #else /* POSIX */
13689     if (!PyUnicode_FSConverter(self->path, &ub))
13690         return NULL;
13691     const char *path = PyBytes_AS_STRING(ub);
13692     if (self->dir_fd != DEFAULT_DIR_FD) {
13693 #ifdef HAVE_FSTATAT
13694       if (HAVE_FSTATAT_RUNTIME) {
13695         Py_BEGIN_ALLOW_THREADS
13696         result = fstatat(self->dir_fd, path, &st,
13697                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13698         Py_END_ALLOW_THREADS
13699       } else
13700 
13701 #endif /* HAVE_FSTATAT */
13702       {
13703         Py_DECREF(ub);
13704         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13705         return NULL;
13706       }
13707     }
13708     else
13709 #endif
13710     {
13711         Py_BEGIN_ALLOW_THREADS
13712         if (follow_symlinks) {
13713             result = STAT(path, &st);
13714         }
13715         else {
13716             result = LSTAT(path, &st);
13717         }
13718         Py_END_ALLOW_THREADS
13719     }
13720 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13721     PyMem_Free(path);
13722 #else /* USE_UNICODE_WCHAR_CACHE */
13723     Py_DECREF(ub);
13724 #endif /* USE_UNICODE_WCHAR_CACHE */
13725 
13726     if (result != 0)
13727         return path_object_error(self->path);
13728 
13729     return _pystat_fromstructstat(module, &st);
13730 }
13731 
13732 static PyObject *
DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)13733 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13734 {
13735     if (!self->lstat) {
13736         PyObject *module = PyType_GetModule(defining_class);
13737 #ifdef MS_WINDOWS
13738         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13739 #else /* POSIX */
13740         self->lstat = DirEntry_fetch_stat(module, self, 0);
13741 #endif
13742     }
13743     Py_XINCREF(self->lstat);
13744     return self->lstat;
13745 }
13746 
13747 /*[clinic input]
13748 os.DirEntry.stat
13749     defining_class: defining_class
13750     /
13751     *
13752     follow_symlinks: bool = True
13753 
13754 Return stat_result object for the entry; cached per entry.
13755 [clinic start generated code]*/
13756 
13757 static PyObject *
os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks)13758 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13759                       int follow_symlinks)
13760 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13761 {
13762     if (!follow_symlinks) {
13763         return DirEntry_get_lstat(defining_class, self);
13764     }
13765 
13766     if (!self->stat) {
13767         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13768         if (result == -1) {
13769             return NULL;
13770         }
13771         if (result) {
13772             PyObject *module = PyType_GetModule(defining_class);
13773             self->stat = DirEntry_fetch_stat(module, self, 1);
13774         }
13775         else {
13776             self->stat = DirEntry_get_lstat(defining_class, self);
13777         }
13778     }
13779 
13780     Py_XINCREF(self->stat);
13781     return self->stat;
13782 }
13783 
13784 /* Set exception and return -1 on error, 0 for False, 1 for True */
13785 static int
DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self, int follow_symlinks, unsigned short mode_bits)13786 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13787                    int follow_symlinks, unsigned short mode_bits)
13788 {
13789     PyObject *stat = NULL;
13790     PyObject *st_mode = NULL;
13791     long mode;
13792     int result;
13793 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13794     int is_symlink;
13795     int need_stat;
13796 #endif
13797 #ifdef MS_WINDOWS
13798     unsigned long dir_bits;
13799 #endif
13800 
13801 #ifdef MS_WINDOWS
13802     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13803     need_stat = follow_symlinks && is_symlink;
13804 #elif defined(HAVE_DIRENT_D_TYPE)
13805     is_symlink = self->d_type == DT_LNK;
13806     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13807 #endif
13808 
13809 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13810     if (need_stat) {
13811 #endif
13812         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13813         if (!stat) {
13814             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13815                 /* If file doesn't exist (anymore), then return False
13816                    (i.e., say it's not a file/directory) */
13817                 PyErr_Clear();
13818                 return 0;
13819             }
13820             goto error;
13821         }
13822         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13823         st_mode = PyObject_GetAttr(stat, state->st_mode);
13824         if (!st_mode)
13825             goto error;
13826 
13827         mode = PyLong_AsLong(st_mode);
13828         if (mode == -1 && PyErr_Occurred())
13829             goto error;
13830         Py_CLEAR(st_mode);
13831         Py_CLEAR(stat);
13832         result = (mode & S_IFMT) == mode_bits;
13833 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13834     }
13835     else if (is_symlink) {
13836         assert(mode_bits != S_IFLNK);
13837         result = 0;
13838     }
13839     else {
13840         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13841 #ifdef MS_WINDOWS
13842         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13843         if (mode_bits == S_IFDIR)
13844             result = dir_bits != 0;
13845         else
13846             result = dir_bits == 0;
13847 #else /* POSIX */
13848         if (mode_bits == S_IFDIR)
13849             result = self->d_type == DT_DIR;
13850         else
13851             result = self->d_type == DT_REG;
13852 #endif
13853     }
13854 #endif
13855 
13856     return result;
13857 
13858 error:
13859     Py_XDECREF(st_mode);
13860     Py_XDECREF(stat);
13861     return -1;
13862 }
13863 
13864 /*[clinic input]
13865 os.DirEntry.is_dir -> bool
13866     defining_class: defining_class
13867     /
13868     *
13869     follow_symlinks: bool = True
13870 
13871 Return True if the entry is a directory; cached per entry.
13872 [clinic start generated code]*/
13873 
13874 static int
os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks)13875 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13876                         int follow_symlinks)
13877 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13878 {
13879     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13880 }
13881 
13882 /*[clinic input]
13883 os.DirEntry.is_file -> bool
13884     defining_class: defining_class
13885     /
13886     *
13887     follow_symlinks: bool = True
13888 
13889 Return True if the entry is a file; cached per entry.
13890 [clinic start generated code]*/
13891 
13892 static int
os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class, int follow_symlinks)13893 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13894                          int follow_symlinks)
13895 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13896 {
13897     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13898 }
13899 
13900 /*[clinic input]
13901 os.DirEntry.inode
13902 
13903 Return inode of the entry; cached per entry.
13904 [clinic start generated code]*/
13905 
13906 static PyObject *
os_DirEntry_inode_impl(DirEntry *self)13907 os_DirEntry_inode_impl(DirEntry *self)
13908 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13909 {
13910 #ifdef MS_WINDOWS
13911     if (!self->got_file_index) {
13912         PyObject *unicode;
13913         STRUCT_STAT stat;
13914         int result;
13915 
13916         if (!PyUnicode_FSDecoder(self->path, &unicode))
13917             return NULL;
13918 #if USE_UNICODE_WCHAR_CACHE
13919 _Py_COMP_DIAG_PUSH
13920 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13921         const wchar_t *path = PyUnicode_AsUnicode(unicode);
13922         result = LSTAT(path, &stat);
13923         Py_DECREF(unicode);
13924 _Py_COMP_DIAG_POP
13925 #else /* USE_UNICODE_WCHAR_CACHE */
13926         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13927         Py_DECREF(unicode);
13928         result = LSTAT(path, &stat);
13929         PyMem_Free(path);
13930 #endif /* USE_UNICODE_WCHAR_CACHE */
13931 
13932         if (result != 0)
13933             return path_object_error(self->path);
13934 
13935         self->win32_file_index = stat.st_ino;
13936         self->got_file_index = 1;
13937     }
13938     static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13939                   "DirEntry.win32_file_index is larger than unsigned long long");
13940     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13941 #else /* POSIX */
13942     static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13943                   "DirEntry.d_ino is larger than unsigned long long");
13944     return PyLong_FromUnsignedLongLong(self->d_ino);
13945 #endif
13946 }
13947 
13948 static PyObject *
DirEntry_repr(DirEntry *self)13949 DirEntry_repr(DirEntry *self)
13950 {
13951     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13952 }
13953 
13954 /*[clinic input]
13955 os.DirEntry.__fspath__
13956 
13957 Returns the path for the entry.
13958 [clinic start generated code]*/
13959 
13960 static PyObject *
os_DirEntry___fspath___impl(DirEntry *self)13961 os_DirEntry___fspath___impl(DirEntry *self)
13962 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13963 {
13964     Py_INCREF(self->path);
13965     return self->path;
13966 }
13967 
13968 static PyMemberDef DirEntry_members[] = {
13969     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13970      "the entry's base filename, relative to scandir() \"path\" argument"},
13971     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13972      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13973     {NULL}
13974 };
13975 
13976 #include "clinic/posixmodule.c.h"
13977 
13978 static PyMethodDef DirEntry_methods[] = {
13979     OS_DIRENTRY_IS_DIR_METHODDEF
13980     OS_DIRENTRY_IS_FILE_METHODDEF
13981     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13982     OS_DIRENTRY_STAT_METHODDEF
13983     OS_DIRENTRY_INODE_METHODDEF
13984     OS_DIRENTRY___FSPATH___METHODDEF
13985     {"__class_getitem__",       Py_GenericAlias,
13986     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13987     {NULL}
13988 };
13989 
13990 static PyType_Slot DirEntryType_slots[] = {
13991     {Py_tp_dealloc, DirEntry_dealloc},
13992     {Py_tp_repr, DirEntry_repr},
13993     {Py_tp_methods, DirEntry_methods},
13994     {Py_tp_members, DirEntry_members},
13995     {0, 0},
13996 };
13997 
13998 static PyType_Spec DirEntryType_spec = {
13999     MODNAME ".DirEntry",
14000     sizeof(DirEntry),
14001     0,
14002     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
14003     DirEntryType_slots
14004 };
14005 
14006 
14007 #ifdef MS_WINDOWS
14008 
14009 static wchar_t *
join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)14010 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
14011 {
14012     Py_ssize_t path_len;
14013     Py_ssize_t size;
14014     wchar_t *result;
14015     wchar_t ch;
14016 
14017     if (!path_wide) { /* Default arg: "." */
14018         path_wide = L".";
14019         path_len = 1;
14020     }
14021     else {
14022         path_len = wcslen(path_wide);
14023     }
14024 
14025     /* The +1's are for the path separator and the NUL */
14026     size = path_len + 1 + wcslen(filename) + 1;
14027     result = PyMem_New(wchar_t, size);
14028     if (!result) {
14029         PyErr_NoMemory();
14030         return NULL;
14031     }
14032     wcscpy(result, path_wide);
14033     if (path_len > 0) {
14034         ch = result[path_len - 1];
14035         if (ch != SEP && ch != ALTSEP && ch != L':')
14036             result[path_len++] = SEP;
14037         wcscpy(result + path_len, filename);
14038     }
14039     return result;
14040 }
14041 
14042 static PyObject *
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)14043 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14044 {
14045     DirEntry *entry;
14046     BY_HANDLE_FILE_INFORMATION file_info;
14047     ULONG reparse_tag;
14048     wchar_t *joined_path;
14049 
14050     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14051     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14052     if (!entry)
14053         return NULL;
14054     entry->name = NULL;
14055     entry->path = NULL;
14056     entry->stat = NULL;
14057     entry->lstat = NULL;
14058     entry->got_file_index = 0;
14059 
14060     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14061     if (!entry->name)
14062         goto error;
14063     if (path->narrow) {
14064         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14065         if (!entry->name)
14066             goto error;
14067     }
14068 
14069     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14070     if (!joined_path)
14071         goto error;
14072 
14073     entry->path = PyUnicode_FromWideChar(joined_path, -1);
14074     PyMem_Free(joined_path);
14075     if (!entry->path)
14076         goto error;
14077     if (path->narrow) {
14078         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14079         if (!entry->path)
14080             goto error;
14081     }
14082 
14083     find_data_to_file_info(dataW, &file_info, &reparse_tag);
14084     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
14085 
14086     return (PyObject *)entry;
14087 
14088 error:
14089     Py_DECREF(entry);
14090     return NULL;
14091 }
14092 
14093 #else /* POSIX */
14094 
14095 static char *
join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)14096 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14097 {
14098     Py_ssize_t path_len;
14099     Py_ssize_t size;
14100     char *result;
14101 
14102     if (!path_narrow) { /* Default arg: "." */
14103         path_narrow = ".";
14104         path_len = 1;
14105     }
14106     else {
14107         path_len = strlen(path_narrow);
14108     }
14109 
14110     if (filename_len == -1)
14111         filename_len = strlen(filename);
14112 
14113     /* The +1's are for the path separator and the NUL */
14114     size = path_len + 1 + filename_len + 1;
14115     result = PyMem_New(char, size);
14116     if (!result) {
14117         PyErr_NoMemory();
14118         return NULL;
14119     }
14120     strcpy(result, path_narrow);
14121     if (path_len > 0 && result[path_len - 1] != '/')
14122         result[path_len++] = '/';
14123     strcpy(result + path_len, filename);
14124     return result;
14125 }
14126 
14127 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 )14128 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14129                          Py_ssize_t name_len, ino_t d_ino
14130 #ifdef HAVE_DIRENT_D_TYPE
14131                          , unsigned char d_type
14132 #endif
14133                          )
14134 {
14135     DirEntry *entry;
14136     char *joined_path;
14137 
14138     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14139     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14140     if (!entry)
14141         return NULL;
14142     entry->name = NULL;
14143     entry->path = NULL;
14144     entry->stat = NULL;
14145     entry->lstat = NULL;
14146 
14147     if (path->fd != -1) {
14148         entry->dir_fd = path->fd;
14149         joined_path = NULL;
14150     }
14151     else {
14152         entry->dir_fd = DEFAULT_DIR_FD;
14153         joined_path = join_path_filename(path->narrow, name, name_len);
14154         if (!joined_path)
14155             goto error;
14156     }
14157 
14158     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14159         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14160         if (joined_path)
14161             entry->path = PyUnicode_DecodeFSDefault(joined_path);
14162     }
14163     else {
14164         entry->name = PyBytes_FromStringAndSize(name, name_len);
14165         if (joined_path)
14166             entry->path = PyBytes_FromString(joined_path);
14167     }
14168     PyMem_Free(joined_path);
14169     if (!entry->name)
14170         goto error;
14171 
14172     if (path->fd != -1) {
14173         entry->path = entry->name;
14174         Py_INCREF(entry->path);
14175     }
14176     else if (!entry->path)
14177         goto error;
14178 
14179 #ifdef HAVE_DIRENT_D_TYPE
14180     entry->d_type = d_type;
14181 #endif
14182     entry->d_ino = d_ino;
14183 
14184     return (PyObject *)entry;
14185 
14186 error:
14187     Py_XDECREF(entry);
14188     return NULL;
14189 }
14190 
14191 #endif
14192 
14193 
14194 typedef struct {
14195     PyObject_HEAD
14196     path_t path;
14197 #ifdef MS_WINDOWS
14198     HANDLE handle;
14199     WIN32_FIND_DATAW file_data;
14200     int first_time;
14201 #else /* POSIX */
14202     DIR *dirp;
14203 #endif
14204 #ifdef HAVE_FDOPENDIR
14205     int fd;
14206 #endif
14207 } ScandirIterator;
14208 
14209 #ifdef MS_WINDOWS
14210 
14211 static int
ScandirIterator_is_closed(ScandirIterator *iterator)14212 ScandirIterator_is_closed(ScandirIterator *iterator)
14213 {
14214     return iterator->handle == INVALID_HANDLE_VALUE;
14215 }
14216 
14217 static void
ScandirIterator_closedir(ScandirIterator *iterator)14218 ScandirIterator_closedir(ScandirIterator *iterator)
14219 {
14220     HANDLE handle = iterator->handle;
14221 
14222     if (handle == INVALID_HANDLE_VALUE)
14223         return;
14224 
14225     iterator->handle = INVALID_HANDLE_VALUE;
14226     Py_BEGIN_ALLOW_THREADS
14227     FindClose(handle);
14228     Py_END_ALLOW_THREADS
14229 }
14230 
14231 static PyObject *
ScandirIterator_iternext(ScandirIterator *iterator)14232 ScandirIterator_iternext(ScandirIterator *iterator)
14233 {
14234     WIN32_FIND_DATAW *file_data = &iterator->file_data;
14235     BOOL success;
14236     PyObject *entry;
14237 
14238     /* Happens if the iterator is iterated twice, or closed explicitly */
14239     if (iterator->handle == INVALID_HANDLE_VALUE)
14240         return NULL;
14241 
14242     while (1) {
14243         if (!iterator->first_time) {
14244             Py_BEGIN_ALLOW_THREADS
14245             success = FindNextFileW(iterator->handle, file_data);
14246             Py_END_ALLOW_THREADS
14247             if (!success) {
14248                 /* Error or no more files */
14249                 if (GetLastError() != ERROR_NO_MORE_FILES)
14250                     path_error(&iterator->path);
14251                 break;
14252             }
14253         }
14254         iterator->first_time = 0;
14255 
14256         /* Skip over . and .. */
14257         if (wcscmp(file_data->cFileName, L".") != 0 &&
14258             wcscmp(file_data->cFileName, L"..") != 0)
14259         {
14260             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14261             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14262             if (!entry)
14263                 break;
14264             return entry;
14265         }
14266 
14267         /* Loop till we get a non-dot directory or finish iterating */
14268     }
14269 
14270     /* Error or no more files */
14271     ScandirIterator_closedir(iterator);
14272     return NULL;
14273 }
14274 
14275 #else /* POSIX */
14276 
14277 static int
ScandirIterator_is_closed(ScandirIterator *iterator)14278 ScandirIterator_is_closed(ScandirIterator *iterator)
14279 {
14280     return !iterator->dirp;
14281 }
14282 
14283 static void
ScandirIterator_closedir(ScandirIterator *iterator)14284 ScandirIterator_closedir(ScandirIterator *iterator)
14285 {
14286     DIR *dirp = iterator->dirp;
14287 
14288     if (!dirp)
14289         return;
14290 
14291     iterator->dirp = NULL;
14292     Py_BEGIN_ALLOW_THREADS
14293 #ifdef HAVE_FDOPENDIR
14294     if (iterator->path.fd != -1)
14295         rewinddir(dirp);
14296 #endif
14297     closedir(dirp);
14298     Py_END_ALLOW_THREADS
14299     return;
14300 }
14301 
14302 static PyObject *
ScandirIterator_iternext(ScandirIterator *iterator)14303 ScandirIterator_iternext(ScandirIterator *iterator)
14304 {
14305     struct dirent *direntp;
14306     Py_ssize_t name_len;
14307     int is_dot;
14308     PyObject *entry;
14309 
14310     /* Happens if the iterator is iterated twice, or closed explicitly */
14311     if (!iterator->dirp)
14312         return NULL;
14313 
14314     while (1) {
14315         errno = 0;
14316         Py_BEGIN_ALLOW_THREADS
14317         direntp = readdir(iterator->dirp);
14318         Py_END_ALLOW_THREADS
14319 
14320         if (!direntp) {
14321             /* Error or no more files */
14322             if (errno != 0)
14323                 path_error(&iterator->path);
14324             break;
14325         }
14326 
14327         /* Skip over . and .. */
14328         name_len = NAMLEN(direntp);
14329         is_dot = direntp->d_name[0] == '.' &&
14330                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14331         if (!is_dot) {
14332             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14333             entry = DirEntry_from_posix_info(module,
14334                                              &iterator->path, direntp->d_name,
14335                                              name_len, direntp->d_ino
14336 #ifdef HAVE_DIRENT_D_TYPE
14337                                              , direntp->d_type
14338 #endif
14339                                             );
14340             if (!entry)
14341                 break;
14342             return entry;
14343         }
14344 
14345         /* Loop till we get a non-dot directory or finish iterating */
14346     }
14347 
14348     /* Error or no more files */
14349     ScandirIterator_closedir(iterator);
14350     return NULL;
14351 }
14352 
14353 #endif
14354 
14355 static PyObject *
ScandirIterator_close(ScandirIterator *self, PyObject *args)14356 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14357 {
14358     ScandirIterator_closedir(self);
14359     Py_RETURN_NONE;
14360 }
14361 
14362 static PyObject *
ScandirIterator_enter(PyObject *self, PyObject *args)14363 ScandirIterator_enter(PyObject *self, PyObject *args)
14364 {
14365     Py_INCREF(self);
14366     return self;
14367 }
14368 
14369 static PyObject *
ScandirIterator_exit(ScandirIterator *self, PyObject *args)14370 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14371 {
14372     ScandirIterator_closedir(self);
14373     Py_RETURN_NONE;
14374 }
14375 
14376 static void
ScandirIterator_finalize(ScandirIterator *iterator)14377 ScandirIterator_finalize(ScandirIterator *iterator)
14378 {
14379     PyObject *error_type, *error_value, *error_traceback;
14380 
14381     /* Save the current exception, if any. */
14382     PyErr_Fetch(&error_type, &error_value, &error_traceback);
14383 
14384     if (!ScandirIterator_is_closed(iterator)) {
14385         ScandirIterator_closedir(iterator);
14386 
14387         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14388                                   "unclosed scandir iterator %R", iterator)) {
14389             /* Spurious errors can appear at shutdown */
14390             if (PyErr_ExceptionMatches(PyExc_Warning)) {
14391                 PyErr_WriteUnraisable((PyObject *) iterator);
14392             }
14393         }
14394     }
14395 
14396     path_cleanup(&iterator->path);
14397 
14398     /* Restore the saved exception. */
14399     PyErr_Restore(error_type, error_value, error_traceback);
14400 }
14401 
14402 static void
ScandirIterator_dealloc(ScandirIterator *iterator)14403 ScandirIterator_dealloc(ScandirIterator *iterator)
14404 {
14405     PyTypeObject *tp = Py_TYPE(iterator);
14406     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14407         return;
14408 
14409     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14410     free_func(iterator);
14411     Py_DECREF(tp);
14412 }
14413 
14414 static PyMethodDef ScandirIterator_methods[] = {
14415     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14416     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14417     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14418     {NULL}
14419 };
14420 
14421 static PyType_Slot ScandirIteratorType_slots[] = {
14422     {Py_tp_dealloc, ScandirIterator_dealloc},
14423     {Py_tp_finalize, ScandirIterator_finalize},
14424     {Py_tp_iter, PyObject_SelfIter},
14425     {Py_tp_iternext, ScandirIterator_iternext},
14426     {Py_tp_methods, ScandirIterator_methods},
14427     {0, 0},
14428 };
14429 
14430 static PyType_Spec ScandirIteratorType_spec = {
14431     MODNAME ".ScandirIterator",
14432     sizeof(ScandirIterator),
14433     0,
14434     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14435     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14436     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14437         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14438     ScandirIteratorType_slots
14439 };
14440 
14441 /*[clinic input]
14442 os.scandir
14443 
14444     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14445 
14446 Return an iterator of DirEntry objects for given path.
14447 
14448 path can be specified as either str, bytes, or a path-like object.  If path
14449 is bytes, the names of yielded DirEntry objects will also be bytes; in
14450 all other circumstances they will be str.
14451 
14452 If path is None, uses the path='.'.
14453 [clinic start generated code]*/
14454 
14455 static PyObject *
os_scandir_impl(PyObject *module, path_t *path)14456 os_scandir_impl(PyObject *module, path_t *path)
14457 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14458 {
14459     ScandirIterator *iterator;
14460 #ifdef MS_WINDOWS
14461     wchar_t *path_strW;
14462 #else
14463     const char *path_str;
14464 #ifdef HAVE_FDOPENDIR
14465     int fd = -1;
14466 #endif
14467 #endif
14468 
14469     if (PySys_Audit("os.scandir", "O",
14470                     path->object ? path->object : Py_None) < 0) {
14471         return NULL;
14472     }
14473 
14474     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14475     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14476     if (!iterator)
14477         return NULL;
14478 
14479 #ifdef MS_WINDOWS
14480     iterator->handle = INVALID_HANDLE_VALUE;
14481 #else
14482     iterator->dirp = NULL;
14483 #endif
14484 
14485     /* Move the ownership to iterator->path */
14486     memcpy(&iterator->path, path, sizeof(path_t));
14487     memset(path, 0, sizeof(path_t));
14488 
14489 #ifdef MS_WINDOWS
14490     iterator->first_time = 1;
14491 
14492     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14493     if (!path_strW)
14494         goto error;
14495 
14496     Py_BEGIN_ALLOW_THREADS
14497     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14498     Py_END_ALLOW_THREADS
14499 
14500     PyMem_Free(path_strW);
14501 
14502     if (iterator->handle == INVALID_HANDLE_VALUE) {
14503         path_error(&iterator->path);
14504         goto error;
14505     }
14506 #else /* POSIX */
14507     errno = 0;
14508 #ifdef HAVE_FDOPENDIR
14509     if (iterator->path.fd != -1) {
14510       if (HAVE_FDOPENDIR_RUNTIME) {
14511         /* closedir() closes the FD, so we duplicate it */
14512         fd = _Py_dup(iterator->path.fd);
14513         if (fd == -1)
14514             goto error;
14515 
14516         Py_BEGIN_ALLOW_THREADS
14517         iterator->dirp = fdopendir(fd);
14518         Py_END_ALLOW_THREADS
14519       } else {
14520         PyErr_SetString(PyExc_TypeError,
14521             "scandir: path should be string, bytes, os.PathLike or None, not int");
14522         return NULL;
14523       }
14524     }
14525     else
14526 #endif
14527     {
14528         if (iterator->path.narrow)
14529             path_str = iterator->path.narrow;
14530         else
14531             path_str = ".";
14532 
14533         Py_BEGIN_ALLOW_THREADS
14534         iterator->dirp = opendir(path_str);
14535         Py_END_ALLOW_THREADS
14536     }
14537 
14538     if (!iterator->dirp) {
14539         path_error(&iterator->path);
14540 #ifdef HAVE_FDOPENDIR
14541         if (fd != -1) {
14542             Py_BEGIN_ALLOW_THREADS
14543             close(fd);
14544             Py_END_ALLOW_THREADS
14545         }
14546 #endif
14547         goto error;
14548     }
14549 #endif
14550 
14551     return (PyObject *)iterator;
14552 
14553 error:
14554     Py_DECREF(iterator);
14555     return NULL;
14556 }
14557 
14558 /*
14559     Return the file system path representation of the object.
14560 
14561     If the object is str or bytes, then allow it to pass through with
14562     an incremented refcount. If the object defines __fspath__(), then
14563     return the result of that method. All other types raise a TypeError.
14564 */
14565 PyObject *
PyOS_FSPath(PyObject *path)14566 PyOS_FSPath(PyObject *path)
14567 {
14568     /* For error message reasons, this function is manually inlined in
14569        path_converter(). */
14570     PyObject *func = NULL;
14571     PyObject *path_repr = NULL;
14572 
14573     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14574         Py_INCREF(path);
14575         return path;
14576     }
14577 
14578     func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14579     if (NULL == func) {
14580         return PyErr_Format(PyExc_TypeError,
14581                             "expected str, bytes or os.PathLike object, "
14582                             "not %.200s",
14583                             _PyType_Name(Py_TYPE(path)));
14584     }
14585 
14586     path_repr = _PyObject_CallNoArgs(func);
14587     Py_DECREF(func);
14588     if (NULL == path_repr) {
14589         return NULL;
14590     }
14591 
14592     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14593         PyErr_Format(PyExc_TypeError,
14594                      "expected %.200s.__fspath__() to return str or bytes, "
14595                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14596                      _PyType_Name(Py_TYPE(path_repr)));
14597         Py_DECREF(path_repr);
14598         return NULL;
14599     }
14600 
14601     return path_repr;
14602 }
14603 
14604 /*[clinic input]
14605 os.fspath
14606 
14607     path: object
14608 
14609 Return the file system path representation of the object.
14610 
14611 If the object is str or bytes, then allow it to pass through as-is. If the
14612 object defines __fspath__(), then return the result of that method. All other
14613 types raise a TypeError.
14614 [clinic start generated code]*/
14615 
14616 static PyObject *
os_fspath_impl(PyObject *module, PyObject *path)14617 os_fspath_impl(PyObject *module, PyObject *path)
14618 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14619 {
14620     return PyOS_FSPath(path);
14621 }
14622 
14623 #ifdef HAVE_GETRANDOM_SYSCALL
14624 /*[clinic input]
14625 os.getrandom
14626 
14627     size: Py_ssize_t
14628     flags: int=0
14629 
14630 Obtain a series of random bytes.
14631 [clinic start generated code]*/
14632 
14633 static PyObject *
os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)14634 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14635 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14636 {
14637     PyObject *bytes;
14638     Py_ssize_t n;
14639 
14640     if (size < 0) {
14641         errno = EINVAL;
14642         return posix_error();
14643     }
14644 
14645     bytes = PyBytes_FromStringAndSize(NULL, size);
14646     if (bytes == NULL) {
14647         PyErr_NoMemory();
14648         return NULL;
14649     }
14650 
14651     while (1) {
14652         n = syscall(SYS_getrandom,
14653                     PyBytes_AS_STRING(bytes),
14654                     PyBytes_GET_SIZE(bytes),
14655                     flags);
14656         if (n < 0 && errno == EINTR) {
14657             if (PyErr_CheckSignals() < 0) {
14658                 goto error;
14659             }
14660 
14661             /* getrandom() was interrupted by a signal: retry */
14662             continue;
14663         }
14664         break;
14665     }
14666 
14667     if (n < 0) {
14668         PyErr_SetFromErrno(PyExc_OSError);
14669         goto error;
14670     }
14671 
14672     if (n != size) {
14673         _PyBytes_Resize(&bytes, n);
14674     }
14675 
14676     return bytes;
14677 
14678 error:
14679     Py_DECREF(bytes);
14680     return NULL;
14681 }
14682 #endif   /* HAVE_GETRANDOM_SYSCALL */
14683 
14684 #ifdef MS_WINDOWS
14685 /* bpo-36085: Helper functions for managing DLL search directories
14686  * on win32
14687  */
14688 
14689 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14690 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14691 
14692 /*[clinic input]
14693 os._add_dll_directory
14694 
14695     path: path_t
14696 
14697 Add a path to the DLL search path.
14698 
14699 This search path is used when resolving dependencies for imported
14700 extension modules (the module itself is resolved through sys.path),
14701 and also by ctypes.
14702 
14703 Returns an opaque value that may be passed to os.remove_dll_directory
14704 to remove this directory from the search path.
14705 [clinic start generated code]*/
14706 
14707 static PyObject *
os__add_dll_directory_impl(PyObject *module, path_t *path)14708 os__add_dll_directory_impl(PyObject *module, path_t *path)
14709 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14710 {
14711     HMODULE hKernel32;
14712     PAddDllDirectory AddDllDirectory;
14713     DLL_DIRECTORY_COOKIE cookie = 0;
14714     DWORD err = 0;
14715 
14716     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14717         return NULL;
14718     }
14719 
14720     /* For Windows 7, we have to load this. As this will be a fairly
14721        infrequent operation, just do it each time. Kernel32 is always
14722        loaded. */
14723     Py_BEGIN_ALLOW_THREADS
14724     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14725         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14726             hKernel32, "AddDllDirectory")) ||
14727         !(cookie = (*AddDllDirectory)(path->wide))) {
14728         err = GetLastError();
14729     }
14730     Py_END_ALLOW_THREADS
14731 
14732     if (err) {
14733         return win32_error_object_err("add_dll_directory",
14734                                       path->object, err);
14735     }
14736 
14737     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14738 }
14739 
14740 /*[clinic input]
14741 os._remove_dll_directory
14742 
14743     cookie: object
14744 
14745 Removes a path from the DLL search path.
14746 
14747 The parameter is an opaque value that was returned from
14748 os.add_dll_directory. You can only remove directories that you added
14749 yourself.
14750 [clinic start generated code]*/
14751 
14752 static PyObject *
os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)14753 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14754 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14755 {
14756     HMODULE hKernel32;
14757     PRemoveDllDirectory RemoveDllDirectory;
14758     DLL_DIRECTORY_COOKIE cookieValue;
14759     DWORD err = 0;
14760 
14761     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14762         PyErr_SetString(PyExc_TypeError,
14763             "Provided cookie was not returned from os.add_dll_directory");
14764         return NULL;
14765     }
14766 
14767     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14768         cookie, "DLL directory cookie");
14769 
14770     /* For Windows 7, we have to load this. As this will be a fairly
14771        infrequent operation, just do it each time. Kernel32 is always
14772        loaded. */
14773     Py_BEGIN_ALLOW_THREADS
14774     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14775         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14776             hKernel32, "RemoveDllDirectory")) ||
14777         !(*RemoveDllDirectory)(cookieValue)) {
14778         err = GetLastError();
14779     }
14780     Py_END_ALLOW_THREADS
14781 
14782     if (err) {
14783         return win32_error_object_err("remove_dll_directory",
14784                                       NULL, err);
14785     }
14786 
14787     if (PyCapsule_SetName(cookie, NULL)) {
14788         return NULL;
14789     }
14790 
14791     Py_RETURN_NONE;
14792 }
14793 
14794 #endif
14795 
14796 
14797 /* Only check if WIFEXITED is available: expect that it comes
14798    with WEXITSTATUS, WIFSIGNALED, etc.
14799 
14800    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14801    subprocess can safely call it during late Python finalization without
14802    risking that used os attributes were set to None by finalize_modules(). */
14803 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14804 /*[clinic input]
14805 os.waitstatus_to_exitcode
14806 
14807     status as status_obj: object
14808 
14809 Convert a wait status to an exit code.
14810 
14811 On Unix:
14812 
14813 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14814 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14815 * Otherwise, raise a ValueError.
14816 
14817 On Windows, return status shifted right by 8 bits.
14818 
14819 On Unix, if the process is being traced or if waitpid() was called with
14820 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14821 This function must not be called if WIFSTOPPED(status) is true.
14822 [clinic start generated code]*/
14823 
14824 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)14825 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14826 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14827 {
14828 #ifndef MS_WINDOWS
14829     int status = _PyLong_AsInt(status_obj);
14830     if (status == -1 && PyErr_Occurred()) {
14831         return NULL;
14832     }
14833 
14834     WAIT_TYPE wait_status;
14835     WAIT_STATUS_INT(wait_status) = status;
14836     int exitcode;
14837     if (WIFEXITED(wait_status)) {
14838         exitcode = WEXITSTATUS(wait_status);
14839         /* Sanity check to provide warranty on the function behavior.
14840            It should not occur in practice */
14841         if (exitcode < 0) {
14842             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14843             return NULL;
14844         }
14845     }
14846     else if (WIFSIGNALED(wait_status)) {
14847         int signum = WTERMSIG(wait_status);
14848         /* Sanity check to provide warranty on the function behavior.
14849            It should not occurs in practice */
14850         if (signum <= 0) {
14851             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14852             return NULL;
14853         }
14854         exitcode = -signum;
14855     } else if (WIFSTOPPED(wait_status)) {
14856         /* Status only received if the process is being traced
14857            or if waitpid() was called with WUNTRACED option. */
14858         int signum = WSTOPSIG(wait_status);
14859         PyErr_Format(PyExc_ValueError,
14860                      "process stopped by delivery of signal %i",
14861                      signum);
14862         return NULL;
14863     }
14864     else {
14865         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14866         return NULL;
14867     }
14868     return PyLong_FromLong(exitcode);
14869 #else
14870     /* Windows implementation: see os.waitpid() implementation
14871        which uses _cwait(). */
14872     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14873     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14874         return NULL;
14875     }
14876 
14877     unsigned long long exitcode = (status >> 8);
14878     /* ExitProcess() accepts an UINT type:
14879        reject exit code which doesn't fit in an UINT */
14880     if (exitcode > UINT_MAX) {
14881         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14882         return NULL;
14883     }
14884     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14885 #endif
14886 }
14887 #endif
14888 
14889 
14890 static PyMethodDef posix_methods[] = {
14891 
14892     OS_STAT_METHODDEF
14893     OS_ACCESS_METHODDEF
14894     OS_TTYNAME_METHODDEF
14895     OS_CHDIR_METHODDEF
14896     OS_CHFLAGS_METHODDEF
14897     OS_CHMOD_METHODDEF
14898     OS_FCHMOD_METHODDEF
14899     OS_LCHMOD_METHODDEF
14900     OS_CHOWN_METHODDEF
14901     OS_FCHOWN_METHODDEF
14902     OS_LCHOWN_METHODDEF
14903     OS_LCHFLAGS_METHODDEF
14904     OS_CHROOT_METHODDEF
14905     OS_CTERMID_METHODDEF
14906     OS_GETCWD_METHODDEF
14907     OS_GETCWDB_METHODDEF
14908     OS_LINK_METHODDEF
14909     OS_LISTDIR_METHODDEF
14910     OS_LSTAT_METHODDEF
14911     OS_MKDIR_METHODDEF
14912     OS_NICE_METHODDEF
14913     OS_GETPRIORITY_METHODDEF
14914     OS_SETPRIORITY_METHODDEF
14915     OS_POSIX_SPAWN_METHODDEF
14916     OS_POSIX_SPAWNP_METHODDEF
14917     OS_READLINK_METHODDEF
14918     OS_COPY_FILE_RANGE_METHODDEF
14919     OS_SPLICE_METHODDEF
14920     OS_RENAME_METHODDEF
14921     OS_REPLACE_METHODDEF
14922     OS_RMDIR_METHODDEF
14923     OS_SYMLINK_METHODDEF
14924     OS_SYSTEM_METHODDEF
14925     OS_UMASK_METHODDEF
14926     OS_UNAME_METHODDEF
14927     OS_UNLINK_METHODDEF
14928     OS_REMOVE_METHODDEF
14929     OS_UTIME_METHODDEF
14930     OS_TIMES_METHODDEF
14931     OS__EXIT_METHODDEF
14932     OS__FCOPYFILE_METHODDEF
14933     OS_EXECV_METHODDEF
14934     OS_EXECVE_METHODDEF
14935     OS_SPAWNV_METHODDEF
14936     OS_SPAWNVE_METHODDEF
14937     OS_FORK1_METHODDEF
14938     OS_FORK_METHODDEF
14939     OS_REGISTER_AT_FORK_METHODDEF
14940     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14941     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14942     OS_SCHED_GETPARAM_METHODDEF
14943     OS_SCHED_GETSCHEDULER_METHODDEF
14944     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14945     OS_SCHED_SETPARAM_METHODDEF
14946     OS_SCHED_SETSCHEDULER_METHODDEF
14947     OS_SCHED_YIELD_METHODDEF
14948     OS_SCHED_SETAFFINITY_METHODDEF
14949     OS_SCHED_GETAFFINITY_METHODDEF
14950     OS_OPENPTY_METHODDEF
14951     OS_LOGIN_TTY_METHODDEF
14952     OS_FORKPTY_METHODDEF
14953     OS_GETEGID_METHODDEF
14954     OS_GETEUID_METHODDEF
14955     OS_GETGID_METHODDEF
14956     OS_GETGROUPLIST_METHODDEF
14957     OS_GETGROUPS_METHODDEF
14958     OS_GETPID_METHODDEF
14959     OS_GETPGRP_METHODDEF
14960     OS_GETPPID_METHODDEF
14961     OS_GETUID_METHODDEF
14962     OS_GETLOGIN_METHODDEF
14963     OS_KILL_METHODDEF
14964     OS_KILLPG_METHODDEF
14965     OS_PLOCK_METHODDEF
14966     OS_STARTFILE_METHODDEF
14967     OS_SETUID_METHODDEF
14968     OS_SETEUID_METHODDEF
14969     OS_SETREUID_METHODDEF
14970     OS_SETGID_METHODDEF
14971     OS_SETEGID_METHODDEF
14972     OS_SETREGID_METHODDEF
14973     OS_SETGROUPS_METHODDEF
14974     OS_INITGROUPS_METHODDEF
14975     OS_GETPGID_METHODDEF
14976     OS_SETPGRP_METHODDEF
14977     OS_WAIT_METHODDEF
14978     OS_WAIT3_METHODDEF
14979     OS_WAIT4_METHODDEF
14980     OS_WAITID_METHODDEF
14981     OS_WAITPID_METHODDEF
14982     OS_PIDFD_OPEN_METHODDEF
14983     OS_GETSID_METHODDEF
14984     OS_SETSID_METHODDEF
14985     OS_SETPGID_METHODDEF
14986     OS_TCGETPGRP_METHODDEF
14987     OS_TCSETPGRP_METHODDEF
14988     OS_OPEN_METHODDEF
14989     OS_CLOSE_METHODDEF
14990     OS_CLOSERANGE_METHODDEF
14991     OS_DEVICE_ENCODING_METHODDEF
14992     OS_DUP_METHODDEF
14993     OS_DUP2_METHODDEF
14994     OS_LOCKF_METHODDEF
14995     OS_LSEEK_METHODDEF
14996     OS_READ_METHODDEF
14997     OS_READV_METHODDEF
14998     OS_PREAD_METHODDEF
14999     OS_PREADV_METHODDEF
15000     OS_WRITE_METHODDEF
15001     OS_WRITEV_METHODDEF
15002     OS_PWRITE_METHODDEF
15003     OS_PWRITEV_METHODDEF
15004     OS_SENDFILE_METHODDEF
15005     OS_FSTAT_METHODDEF
15006     OS_ISATTY_METHODDEF
15007     OS_PIPE_METHODDEF
15008     OS_PIPE2_METHODDEF
15009     OS_MKFIFO_METHODDEF
15010     OS_MKNOD_METHODDEF
15011     OS_MAJOR_METHODDEF
15012     OS_MINOR_METHODDEF
15013     OS_MAKEDEV_METHODDEF
15014     OS_FTRUNCATE_METHODDEF
15015     OS_TRUNCATE_METHODDEF
15016     OS_POSIX_FALLOCATE_METHODDEF
15017     OS_POSIX_FADVISE_METHODDEF
15018     OS_PUTENV_METHODDEF
15019     OS_UNSETENV_METHODDEF
15020     OS_STRERROR_METHODDEF
15021     OS_FCHDIR_METHODDEF
15022     OS_FSYNC_METHODDEF
15023     OS_SYNC_METHODDEF
15024     OS_FDATASYNC_METHODDEF
15025     OS_WCOREDUMP_METHODDEF
15026     OS_WIFCONTINUED_METHODDEF
15027     OS_WIFSTOPPED_METHODDEF
15028     OS_WIFSIGNALED_METHODDEF
15029     OS_WIFEXITED_METHODDEF
15030     OS_WEXITSTATUS_METHODDEF
15031     OS_WTERMSIG_METHODDEF
15032     OS_WSTOPSIG_METHODDEF
15033     OS_FSTATVFS_METHODDEF
15034     OS_STATVFS_METHODDEF
15035     OS_CONFSTR_METHODDEF
15036     OS_SYSCONF_METHODDEF
15037     OS_FPATHCONF_METHODDEF
15038     OS_PATHCONF_METHODDEF
15039     OS_ABORT_METHODDEF
15040     OS__GETFULLPATHNAME_METHODDEF
15041     OS__GETDISKUSAGE_METHODDEF
15042     OS__GETFINALPATHNAME_METHODDEF
15043     OS__GETVOLUMEPATHNAME_METHODDEF
15044     OS__PATH_SPLITROOT_METHODDEF
15045     OS__PATH_NORMPATH_METHODDEF
15046     OS_GETLOADAVG_METHODDEF
15047     OS_URANDOM_METHODDEF
15048     OS_SETRESUID_METHODDEF
15049     OS_SETRESGID_METHODDEF
15050     OS_GETRESUID_METHODDEF
15051     OS_GETRESGID_METHODDEF
15052 
15053     OS_GETXATTR_METHODDEF
15054     OS_SETXATTR_METHODDEF
15055     OS_REMOVEXATTR_METHODDEF
15056     OS_LISTXATTR_METHODDEF
15057 
15058     OS_GET_TERMINAL_SIZE_METHODDEF
15059     OS_CPU_COUNT_METHODDEF
15060     OS_GET_INHERITABLE_METHODDEF
15061     OS_SET_INHERITABLE_METHODDEF
15062     OS_GET_HANDLE_INHERITABLE_METHODDEF
15063     OS_SET_HANDLE_INHERITABLE_METHODDEF
15064     OS_GET_BLOCKING_METHODDEF
15065     OS_SET_BLOCKING_METHODDEF
15066     OS_SCANDIR_METHODDEF
15067     OS_FSPATH_METHODDEF
15068     OS_GETRANDOM_METHODDEF
15069     OS_MEMFD_CREATE_METHODDEF
15070     OS_EVENTFD_METHODDEF
15071     OS_EVENTFD_READ_METHODDEF
15072     OS_EVENTFD_WRITE_METHODDEF
15073     OS__ADD_DLL_DIRECTORY_METHODDEF
15074     OS__REMOVE_DLL_DIRECTORY_METHODDEF
15075     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15076     {NULL,              NULL}            /* Sentinel */
15077 };
15078 
15079 static int
all_ins(PyObject *m)15080 all_ins(PyObject *m)
15081 {
15082 #ifdef F_OK
15083     if (PyModule_AddIntMacro(m, F_OK)) return -1;
15084 #endif
15085 #ifdef R_OK
15086     if (PyModule_AddIntMacro(m, R_OK)) return -1;
15087 #endif
15088 #ifdef W_OK
15089     if (PyModule_AddIntMacro(m, W_OK)) return -1;
15090 #endif
15091 #ifdef X_OK
15092     if (PyModule_AddIntMacro(m, X_OK)) return -1;
15093 #endif
15094 #ifdef NGROUPS_MAX
15095     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15096 #endif
15097 #ifdef TMP_MAX
15098     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15099 #endif
15100 #ifdef WCONTINUED
15101     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15102 #endif
15103 #ifdef WNOHANG
15104     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15105 #endif
15106 #ifdef WUNTRACED
15107     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15108 #endif
15109 #ifdef O_RDONLY
15110     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15111 #endif
15112 #ifdef O_WRONLY
15113     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15114 #endif
15115 #ifdef O_RDWR
15116     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15117 #endif
15118 #ifdef O_NDELAY
15119     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15120 #endif
15121 #ifdef O_NONBLOCK
15122     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15123 #endif
15124 #ifdef O_APPEND
15125     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15126 #endif
15127 #ifdef O_DSYNC
15128     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15129 #endif
15130 #ifdef O_RSYNC
15131     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15132 #endif
15133 #ifdef O_SYNC
15134     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15135 #endif
15136 #ifdef O_NOCTTY
15137     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15138 #endif
15139 #ifdef O_CREAT
15140     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15141 #endif
15142 #ifdef O_EXCL
15143     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15144 #endif
15145 #ifdef O_TRUNC
15146     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15147 #endif
15148 #ifdef O_BINARY
15149     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15150 #endif
15151 #ifdef O_TEXT
15152     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15153 #endif
15154 #ifdef O_XATTR
15155     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15156 #endif
15157 #ifdef O_LARGEFILE
15158     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15159 #endif
15160 #ifndef __GNU__
15161 #ifdef O_SHLOCK
15162     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15163 #endif
15164 #ifdef O_EXLOCK
15165     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15166 #endif
15167 #endif
15168 #ifdef O_EXEC
15169     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15170 #endif
15171 #ifdef O_SEARCH
15172     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15173 #endif
15174 #ifdef O_PATH
15175     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15176 #endif
15177 #ifdef O_TTY_INIT
15178     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15179 #endif
15180 #ifdef O_TMPFILE
15181     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15182 #endif
15183 #ifdef PRIO_PROCESS
15184     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15185 #endif
15186 #ifdef PRIO_PGRP
15187     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15188 #endif
15189 #ifdef PRIO_USER
15190     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15191 #endif
15192 #ifdef O_CLOEXEC
15193     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15194 #endif
15195 #ifdef O_ACCMODE
15196     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15197 #endif
15198 #ifdef O_EVTONLY
15199     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15200 #endif
15201 #ifdef O_FSYNC
15202     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15203 #endif
15204 #ifdef O_SYMLINK
15205     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15206 #endif
15207 
15208 #ifdef SEEK_HOLE
15209     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15210 #endif
15211 #ifdef SEEK_DATA
15212     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15213 #endif
15214 
15215 /* MS Windows */
15216 #ifdef O_NOINHERIT
15217     /* Don't inherit in child processes. */
15218     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15219 #endif
15220 #ifdef _O_SHORT_LIVED
15221     /* Optimize for short life (keep in memory). */
15222     /* MS forgot to define this one with a non-underscore form too. */
15223     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15224 #endif
15225 #ifdef O_TEMPORARY
15226     /* Automatically delete when last handle is closed. */
15227     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15228 #endif
15229 #ifdef O_RANDOM
15230     /* Optimize for random access. */
15231     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15232 #endif
15233 #ifdef O_SEQUENTIAL
15234     /* Optimize for sequential access. */
15235     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15236 #endif
15237 
15238 /* GNU extensions. */
15239 #ifdef O_ASYNC
15240     /* Send a SIGIO signal whenever input or output
15241        becomes available on file descriptor */
15242     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15243 #endif
15244 #ifdef O_DIRECT
15245     /* Direct disk access. */
15246     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15247 #endif
15248 #ifdef O_DIRECTORY
15249     /* Must be a directory.      */
15250     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15251 #endif
15252 #ifdef O_NOFOLLOW
15253     /* Do not follow links.      */
15254     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15255 #endif
15256 #ifdef O_NOFOLLOW_ANY
15257     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15258 #endif
15259 #ifdef O_NOLINKS
15260     /* Fails if link count of the named file is greater than 1 */
15261     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15262 #endif
15263 #ifdef O_NOATIME
15264     /* Do not update the access time. */
15265     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15266 #endif
15267 
15268     /* These come from sysexits.h */
15269 #ifdef EX_OK
15270     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15271 #endif /* EX_OK */
15272 #ifdef EX_USAGE
15273     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15274 #endif /* EX_USAGE */
15275 #ifdef EX_DATAERR
15276     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15277 #endif /* EX_DATAERR */
15278 #ifdef EX_NOINPUT
15279     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15280 #endif /* EX_NOINPUT */
15281 #ifdef EX_NOUSER
15282     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15283 #endif /* EX_NOUSER */
15284 #ifdef EX_NOHOST
15285     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15286 #endif /* EX_NOHOST */
15287 #ifdef EX_UNAVAILABLE
15288     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15289 #endif /* EX_UNAVAILABLE */
15290 #ifdef EX_SOFTWARE
15291     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15292 #endif /* EX_SOFTWARE */
15293 #ifdef EX_OSERR
15294     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15295 #endif /* EX_OSERR */
15296 #ifdef EX_OSFILE
15297     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15298 #endif /* EX_OSFILE */
15299 #ifdef EX_CANTCREAT
15300     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15301 #endif /* EX_CANTCREAT */
15302 #ifdef EX_IOERR
15303     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15304 #endif /* EX_IOERR */
15305 #ifdef EX_TEMPFAIL
15306     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15307 #endif /* EX_TEMPFAIL */
15308 #ifdef EX_PROTOCOL
15309     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15310 #endif /* EX_PROTOCOL */
15311 #ifdef EX_NOPERM
15312     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15313 #endif /* EX_NOPERM */
15314 #ifdef EX_CONFIG
15315     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15316 #endif /* EX_CONFIG */
15317 #ifdef EX_NOTFOUND
15318     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15319 #endif /* EX_NOTFOUND */
15320 
15321     /* statvfs */
15322 #ifdef ST_RDONLY
15323     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15324 #endif /* ST_RDONLY */
15325 #ifdef ST_NOSUID
15326     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15327 #endif /* ST_NOSUID */
15328 
15329        /* GNU extensions */
15330 #ifdef ST_NODEV
15331     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15332 #endif /* ST_NODEV */
15333 #ifdef ST_NOEXEC
15334     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15335 #endif /* ST_NOEXEC */
15336 #ifdef ST_SYNCHRONOUS
15337     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15338 #endif /* ST_SYNCHRONOUS */
15339 #ifdef ST_MANDLOCK
15340     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15341 #endif /* ST_MANDLOCK */
15342 #ifdef ST_WRITE
15343     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15344 #endif /* ST_WRITE */
15345 #ifdef ST_APPEND
15346     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15347 #endif /* ST_APPEND */
15348 #ifdef ST_NOATIME
15349     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15350 #endif /* ST_NOATIME */
15351 #ifdef ST_NODIRATIME
15352     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15353 #endif /* ST_NODIRATIME */
15354 #ifdef ST_RELATIME
15355     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15356 #endif /* ST_RELATIME */
15357 
15358     /* FreeBSD sendfile() constants */
15359 #ifdef SF_NODISKIO
15360     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15361 #endif
15362     /* is obsolete since the 11.x release */
15363 #ifdef SF_MNOWAIT
15364     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15365 #endif
15366 #ifdef SF_SYNC
15367     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15368 #endif
15369 #ifdef SF_NOCACHE
15370     if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15371 #endif
15372 
15373     /* constants for posix_fadvise */
15374 #ifdef POSIX_FADV_NORMAL
15375     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15376 #endif
15377 #ifdef POSIX_FADV_SEQUENTIAL
15378     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15379 #endif
15380 #ifdef POSIX_FADV_RANDOM
15381     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15382 #endif
15383 #ifdef POSIX_FADV_NOREUSE
15384     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15385 #endif
15386 #ifdef POSIX_FADV_WILLNEED
15387     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15388 #endif
15389 #ifdef POSIX_FADV_DONTNEED
15390     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15391 #endif
15392 
15393     /* constants for waitid */
15394 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15395     if (PyModule_AddIntMacro(m, P_PID)) return -1;
15396     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15397     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15398 #ifdef P_PIDFD
15399     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15400 #endif
15401 #endif
15402 #ifdef WEXITED
15403     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15404 #endif
15405 #ifdef WNOWAIT
15406     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15407 #endif
15408 #ifdef WSTOPPED
15409     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15410 #endif
15411 #ifdef CLD_EXITED
15412     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15413 #endif
15414 #ifdef CLD_KILLED
15415     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15416 #endif
15417 #ifdef CLD_DUMPED
15418     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15419 #endif
15420 #ifdef CLD_TRAPPED
15421     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15422 #endif
15423 #ifdef CLD_STOPPED
15424     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15425 #endif
15426 #ifdef CLD_CONTINUED
15427     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15428 #endif
15429 
15430     /* constants for lockf */
15431 #ifdef F_LOCK
15432     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15433 #endif
15434 #ifdef F_TLOCK
15435     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15436 #endif
15437 #ifdef F_ULOCK
15438     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15439 #endif
15440 #ifdef F_TEST
15441     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15442 #endif
15443 
15444 #ifdef RWF_DSYNC
15445     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15446 #endif
15447 #ifdef RWF_HIPRI
15448     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15449 #endif
15450 #ifdef RWF_SYNC
15451     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15452 #endif
15453 #ifdef RWF_NOWAIT
15454     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15455 #endif
15456 #ifdef RWF_APPEND
15457     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15458 #endif
15459 
15460 /* constants for splice */
15461 #if defined(HAVE_SPLICE) && defined(__linux__)
15462     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15463     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15464     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15465 #endif
15466 
15467 /* constants for posix_spawn */
15468 #ifdef HAVE_POSIX_SPAWN
15469     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15470     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15471     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15472 #endif
15473 
15474 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15475     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15476     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15477     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15478 #endif
15479 #ifdef HAVE_SPAWNV
15480     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15481     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15482 #endif
15483 
15484 #ifdef HAVE_SCHED_H
15485 #ifdef SCHED_OTHER
15486     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15487 #endif
15488 #ifdef SCHED_FIFO
15489     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15490 #endif
15491 #ifdef SCHED_RR
15492     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15493 #endif
15494 #ifdef SCHED_SPORADIC
15495     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15496 #endif
15497 #ifdef SCHED_BATCH
15498     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15499 #endif
15500 #ifdef SCHED_IDLE
15501     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15502 #endif
15503 #ifdef SCHED_RESET_ON_FORK
15504     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15505 #endif
15506 #ifdef SCHED_SYS
15507     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15508 #endif
15509 #ifdef SCHED_IA
15510     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15511 #endif
15512 #ifdef SCHED_FSS
15513     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15514 #endif
15515 #ifdef SCHED_FX
15516     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15517 #endif
15518 #endif
15519 
15520 #ifdef USE_XATTRS
15521     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15522     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15523     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15524 #endif
15525 
15526 #if HAVE_DECL_RTLD_LAZY
15527     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15528 #endif
15529 #if HAVE_DECL_RTLD_NOW
15530     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15531 #endif
15532 #if HAVE_DECL_RTLD_GLOBAL
15533     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15534 #endif
15535 #if HAVE_DECL_RTLD_LOCAL
15536     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15537 #endif
15538 #if HAVE_DECL_RTLD_NODELETE
15539     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15540 #endif
15541 #if HAVE_DECL_RTLD_NOLOAD
15542     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15543 #endif
15544 #if HAVE_DECL_RTLD_DEEPBIND
15545     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15546 #endif
15547 #if HAVE_DECL_RTLD_MEMBER
15548     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15549 #endif
15550 
15551 #ifdef HAVE_GETRANDOM_SYSCALL
15552     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15553     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15554 #endif
15555 #ifdef HAVE_MEMFD_CREATE
15556     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15557     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15558 #ifdef MFD_HUGETLB
15559     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15560 #endif
15561 #ifdef MFD_HUGE_SHIFT
15562     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15563 #endif
15564 #ifdef MFD_HUGE_MASK
15565     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15566 #endif
15567 #ifdef MFD_HUGE_64KB
15568     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15569 #endif
15570 #ifdef MFD_HUGE_512KB
15571     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15572 #endif
15573 #ifdef MFD_HUGE_1MB
15574     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15575 #endif
15576 #ifdef MFD_HUGE_2MB
15577     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15578 #endif
15579 #ifdef MFD_HUGE_8MB
15580     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15581 #endif
15582 #ifdef MFD_HUGE_16MB
15583     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15584 #endif
15585 #ifdef MFD_HUGE_32MB
15586     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15587 #endif
15588 #ifdef MFD_HUGE_256MB
15589     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15590 #endif
15591 #ifdef MFD_HUGE_512MB
15592     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15593 #endif
15594 #ifdef MFD_HUGE_1GB
15595     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15596 #endif
15597 #ifdef MFD_HUGE_2GB
15598     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15599 #endif
15600 #ifdef MFD_HUGE_16GB
15601     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15602 #endif
15603 #endif /* HAVE_MEMFD_CREATE */
15604 
15605 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15606     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15607 #ifdef EFD_NONBLOCK
15608     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15609 #endif
15610 #ifdef EFD_SEMAPHORE
15611     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15612 #endif
15613 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15614 
15615 #if defined(__APPLE__)
15616     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15617     if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15618     if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15619     if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15620 #endif
15621 
15622 #ifdef MS_WINDOWS
15623     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15624     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15625     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15626     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15627     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15628 #endif
15629 
15630     return 0;
15631 }
15632 
15633 
15634 
15635 #define PROBE(name, test) \
15636    static int name(void)  \
15637    {                      \
15638       if (test) {        \
15639           return 1;       \
15640       } else {            \
15641           return 0;       \
15642       }                   \
15643    }
15644 
15645 #ifdef HAVE_FSTATAT
15646 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15647 #endif
15648 
15649 #ifdef HAVE_FACCESSAT
15650 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15651 #endif
15652 
15653 #ifdef HAVE_FCHMODAT
15654 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15655 #endif
15656 
15657 #ifdef HAVE_FCHOWNAT
15658 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15659 #endif
15660 
15661 #ifdef HAVE_LINKAT
15662 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15663 #endif
15664 
15665 #ifdef HAVE_FDOPENDIR
15666 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15667 #endif
15668 
15669 #ifdef HAVE_MKDIRAT
15670 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15671 #endif
15672 
15673 #ifdef HAVE_MKFIFOAT
15674 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
15675 #endif
15676 
15677 #ifdef HAVE_MKNODAT
15678 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
15679 #endif
15680 
15681 #ifdef HAVE_RENAMEAT
15682 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15683 #endif
15684 
15685 #ifdef HAVE_UNLINKAT
15686 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15687 #endif
15688 
15689 #ifdef HAVE_OPENAT
15690 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15691 #endif
15692 
15693 #ifdef HAVE_READLINKAT
15694 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15695 #endif
15696 
15697 #ifdef HAVE_SYMLINKAT
15698 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15699 #endif
15700 
15701 #ifdef HAVE_FUTIMENS
15702 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15703 #endif
15704 
15705 #ifdef HAVE_UTIMENSAT
15706 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15707 #endif
15708 
15709 
15710 
15711 
15712 static const struct have_function {
15713     const char * const label;
15714     int (*probe)(void);
15715 } have_functions[] = {
15716 
15717 #ifdef HAVE_EVENTFD
15718     {"HAVE_EVENTFD", NULL},
15719 #endif
15720 
15721 #ifdef HAVE_FACCESSAT
15722     { "HAVE_FACCESSAT", probe_faccessat },
15723 #endif
15724 
15725 #ifdef HAVE_FCHDIR
15726     { "HAVE_FCHDIR", NULL },
15727 #endif
15728 
15729 #ifdef HAVE_FCHMOD
15730     { "HAVE_FCHMOD", NULL },
15731 #endif
15732 
15733 #ifdef HAVE_FCHMODAT
15734     { "HAVE_FCHMODAT", probe_fchmodat },
15735 #endif
15736 
15737 #ifdef HAVE_FCHOWN
15738     { "HAVE_FCHOWN", NULL },
15739 #endif
15740 
15741 #ifdef HAVE_FCHOWNAT
15742     { "HAVE_FCHOWNAT", probe_fchownat },
15743 #endif
15744 
15745 #ifdef HAVE_FEXECVE
15746     { "HAVE_FEXECVE", NULL },
15747 #endif
15748 
15749 #ifdef HAVE_FDOPENDIR
15750     { "HAVE_FDOPENDIR", probe_fdopendir },
15751 #endif
15752 
15753 #ifdef HAVE_FPATHCONF
15754     { "HAVE_FPATHCONF", NULL },
15755 #endif
15756 
15757 #ifdef HAVE_FSTATAT
15758     { "HAVE_FSTATAT", probe_fstatat },
15759 #endif
15760 
15761 #ifdef HAVE_FSTATVFS
15762     { "HAVE_FSTATVFS", NULL },
15763 #endif
15764 
15765 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15766     { "HAVE_FTRUNCATE", NULL },
15767 #endif
15768 
15769 #ifdef HAVE_FUTIMENS
15770     { "HAVE_FUTIMENS", probe_futimens },
15771 #endif
15772 
15773 #ifdef HAVE_FUTIMES
15774     { "HAVE_FUTIMES", NULL },
15775 #endif
15776 
15777 #ifdef HAVE_FUTIMESAT
15778     { "HAVE_FUTIMESAT", NULL },
15779 #endif
15780 
15781 #ifdef HAVE_LINKAT
15782     { "HAVE_LINKAT", probe_linkat },
15783 #endif
15784 
15785 #ifdef HAVE_LCHFLAGS
15786     { "HAVE_LCHFLAGS", NULL },
15787 #endif
15788 
15789 #ifdef HAVE_LCHMOD
15790     { "HAVE_LCHMOD", NULL },
15791 #endif
15792 
15793 #ifdef HAVE_LCHOWN
15794     { "HAVE_LCHOWN", NULL },
15795 #endif
15796 
15797 #ifdef HAVE_LSTAT
15798     { "HAVE_LSTAT", NULL },
15799 #endif
15800 
15801 #ifdef HAVE_LUTIMES
15802     { "HAVE_LUTIMES", NULL },
15803 #endif
15804 
15805 #ifdef HAVE_MEMFD_CREATE
15806     { "HAVE_MEMFD_CREATE", NULL },
15807 #endif
15808 
15809 #ifdef HAVE_MKDIRAT
15810     { "HAVE_MKDIRAT", probe_mkdirat },
15811 #endif
15812 
15813 #ifdef HAVE_MKFIFOAT
15814     { "HAVE_MKFIFOAT", probe_mkfifoat },
15815 #endif
15816 
15817 #ifdef HAVE_MKNODAT
15818     { "HAVE_MKNODAT", probe_mknodat },
15819 #endif
15820 
15821 #ifdef HAVE_OPENAT
15822     { "HAVE_OPENAT", probe_openat },
15823 #endif
15824 
15825 #ifdef HAVE_READLINKAT
15826     { "HAVE_READLINKAT", probe_readlinkat },
15827 #endif
15828 
15829 #ifdef HAVE_RENAMEAT
15830     { "HAVE_RENAMEAT", probe_renameat },
15831 #endif
15832 
15833 #ifdef HAVE_SYMLINKAT
15834     { "HAVE_SYMLINKAT", probe_symlinkat },
15835 #endif
15836 
15837 #ifdef HAVE_UNLINKAT
15838     { "HAVE_UNLINKAT", probe_unlinkat },
15839 #endif
15840 
15841 #ifdef HAVE_UTIMENSAT
15842     { "HAVE_UTIMENSAT", probe_utimensat },
15843 #endif
15844 
15845 #ifdef MS_WINDOWS
15846     { "MS_WINDOWS", NULL },
15847 #endif
15848 
15849     { NULL, NULL }
15850 };
15851 
15852 
15853 static int
posixmodule_exec(PyObject *m)15854 posixmodule_exec(PyObject *m)
15855 {
15856     _posixstate *state = get_posix_state(m);
15857 
15858 #if defined(HAVE_PWRITEV)
15859     if (HAVE_PWRITEV_RUNTIME) {} else {
15860         PyObject* dct = PyModule_GetDict(m);
15861 
15862         if (dct == NULL) {
15863             return -1;
15864         }
15865 
15866         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15867             PyErr_Clear();
15868         }
15869         if (PyDict_DelItemString(dct, "preadv") == -1) {
15870             PyErr_Clear();
15871         }
15872     }
15873 #endif
15874 
15875     /* Initialize environ dictionary */
15876     PyObject *v = convertenviron();
15877     Py_XINCREF(v);
15878     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15879         return -1;
15880     Py_DECREF(v);
15881 
15882     if (all_ins(m))
15883         return -1;
15884 
15885     if (setup_confname_tables(m))
15886         return -1;
15887 
15888     Py_INCREF(PyExc_OSError);
15889     PyModule_AddObject(m, "error", PyExc_OSError);
15890 
15891 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15892     waitid_result_desc.name = MODNAME ".waitid_result";
15893     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15894     if (WaitidResultType == NULL) {
15895         return -1;
15896     }
15897     Py_INCREF(WaitidResultType);
15898     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15899     state->WaitidResultType = WaitidResultType;
15900 #endif
15901 
15902     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15903     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15904     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15905     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15906     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15907     if (StatResultType == NULL) {
15908         return -1;
15909     }
15910     Py_INCREF(StatResultType);
15911     PyModule_AddObject(m, "stat_result", StatResultType);
15912     state->StatResultType = StatResultType;
15913     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15914     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15915 
15916     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15917     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15918     if (StatVFSResultType == NULL) {
15919         return -1;
15920     }
15921     Py_INCREF(StatVFSResultType);
15922     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15923     state->StatVFSResultType = StatVFSResultType;
15924 #ifdef NEED_TICKS_PER_SECOND
15925 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15926     ticks_per_second = sysconf(_SC_CLK_TCK);
15927 #  elif defined(HZ)
15928     ticks_per_second = HZ;
15929 #  else
15930     ticks_per_second = 60; /* magic fallback value; may be bogus */
15931 #  endif
15932 #endif
15933 
15934 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15935     sched_param_desc.name = MODNAME ".sched_param";
15936     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15937     if (SchedParamType == NULL) {
15938         return -1;
15939     }
15940     Py_INCREF(SchedParamType);
15941     PyModule_AddObject(m, "sched_param", SchedParamType);
15942     state->SchedParamType = SchedParamType;
15943     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15944 #endif
15945 
15946     /* initialize TerminalSize_info */
15947     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15948     if (TerminalSizeType == NULL) {
15949         return -1;
15950     }
15951     Py_INCREF(TerminalSizeType);
15952     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15953     state->TerminalSizeType = TerminalSizeType;
15954 
15955     /* initialize scandir types */
15956     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15957     if (ScandirIteratorType == NULL) {
15958         return -1;
15959     }
15960     state->ScandirIteratorType = ScandirIteratorType;
15961 
15962     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15963     if (DirEntryType == NULL) {
15964         return -1;
15965     }
15966     Py_INCREF(DirEntryType);
15967     PyModule_AddObject(m, "DirEntry", DirEntryType);
15968     state->DirEntryType = DirEntryType;
15969 
15970     times_result_desc.name = MODNAME ".times_result";
15971     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15972     if (TimesResultType == NULL) {
15973         return -1;
15974     }
15975     Py_INCREF(TimesResultType);
15976     PyModule_AddObject(m, "times_result", TimesResultType);
15977     state->TimesResultType = TimesResultType;
15978 
15979     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15980     if (UnameResultType == NULL) {
15981         return -1;
15982     }
15983     Py_INCREF(UnameResultType);
15984     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15985     state->UnameResultType = (PyObject *)UnameResultType;
15986 
15987     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15988         return -1;
15989 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15990     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15991     if (state->struct_rusage == NULL)
15992         return -1;
15993 #endif
15994     state->st_mode = PyUnicode_InternFromString("st_mode");
15995     if (state->st_mode == NULL)
15996         return -1;
15997 
15998     /* suppress "function not used" warnings */
15999     {
16000     int ignored;
16001     fd_specified("", -1);
16002     follow_symlinks_specified("", 1);
16003     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
16004     dir_fd_converter(Py_None, &ignored);
16005     dir_fd_unavailable(Py_None, &ignored);
16006     }
16007 
16008     /*
16009      * provide list of locally available functions
16010      * so os.py can populate support_* lists
16011      */
16012     PyObject *list = PyList_New(0);
16013     if (!list) {
16014         return -1;
16015     }
16016     for (const struct have_function *trace = have_functions; trace->label; trace++) {
16017         PyObject *unicode;
16018         if (trace->probe && !trace->probe()) continue;
16019         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
16020         if (!unicode)
16021             return -1;
16022         if (PyList_Append(list, unicode))
16023             return -1;
16024         Py_DECREF(unicode);
16025     }
16026 
16027     PyModule_AddObject(m, "_have_functions", list);
16028 
16029     return 0;
16030 }
16031 
16032 
16033 static PyModuleDef_Slot posixmodile_slots[] = {
16034     {Py_mod_exec, posixmodule_exec},
16035     {0, NULL}
16036 };
16037 
16038 static struct PyModuleDef posixmodule = {
16039     PyModuleDef_HEAD_INIT,
16040     .m_name = MODNAME,
16041     .m_doc = posix__doc__,
16042     .m_size = sizeof(_posixstate),
16043     .m_methods = posix_methods,
16044     .m_slots = posixmodile_slots,
16045     .m_traverse = _posix_traverse,
16046     .m_clear = _posix_clear,
16047     .m_free = _posix_free,
16048 };
16049 
16050 PyMODINIT_FUNC
INITFUNC(void)16051 INITFUNC(void)
16052 {
16053     return PyModuleDef_Init(&posixmodule);
16054 }
16055 
16056 #ifdef __cplusplus
16057 }
16058 #endif
16059