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 #include "structmember.h"         // PyMemberDef
38 #ifndef MS_WINDOWS
39 #  include "posixmodule.h"
40 #else
41 #  include "winreparse.h"
42 #endif
43 
44 #if !defined(EX_OK) && defined(EXIT_SUCCESS)
45 #  define EX_OK EXIT_SUCCESS
46 #endif
47 
48 /* On android API level 21, 'AT_EACCESS' is not declared although
49  * HAVE_FACCESSAT is defined. */
50 #ifdef __ANDROID__
51 #  undef HAVE_FACCESSAT
52 #endif
53 
54 #include <stdio.h>                // ctermid()
55 #include <stdlib.h>               // system()
56 
57 /*
58  * A number of APIs are available on macOS from a certain macOS version.
59  * To support building with a new SDK while deploying to older versions
60  * the availability test is split into two:
61  *   - HAVE_<FUNCTION>:  The configure check for compile time availability
62  *   - HAVE_<FUNCTION>_RUNTIME: Runtime check for availability
63  *
64  * The latter is always true when not on macOS, or when using a compiler
65  * that does not support __has_builtin (older versions of Xcode).
66  *
67  * Due to compiler restrictions there is one valid use of HAVE_<FUNCTION>_RUNTIME:
68  *    if (HAVE_<FUNCTION>_RUNTIME) { ... }
69  *
70  * In mixing the test with other tests or using negations will result in compile
71  * errors.
72  */
73 #if defined(__APPLE__)
74 
75 #if defined(__has_builtin)
76 #if __has_builtin(__builtin_available)
77 #define HAVE_BUILTIN_AVAILABLE 1
78 #endif
79 #endif
80 
81 #ifdef HAVE_BUILTIN_AVAILABLE
82 #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
83 #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
84 #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
85 #  define HAVE_FCHOWNAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
86 #  define HAVE_LINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
87 #  define HAVE_FDOPENDIR_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
88 #  define HAVE_MKDIRAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
89 #  define HAVE_RENAMEAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
90 #  define HAVE_UNLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
91 #  define HAVE_OPENAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
92 #  define HAVE_READLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
93 #  define HAVE_SYMLINKAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
94 #  define HAVE_FUTIMENS_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
95 #  define HAVE_UTIMENSAT_RUNTIME __builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
96 #  define HAVE_PWRITEV_RUNTIME __builtin_available(macOS 11.0, iOS 14.0, tvOS 14.0, watchOS 7.0, *)
97 #  define HAVE_MKFIFOAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
98 #  define HAVE_MKNODAT_RUNTIME __builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *)
99 
100 #  define HAVE_POSIX_SPAWN_SETSID_RUNTIME __builtin_available(macOS 10.15, *)
101 
102 #else /* Xcode 8 or earlier */
103 
104    /* __builtin_available is not present in these compilers, but
105     * some of the symbols might be weak linked (10.10 SDK or later
106     * deploying on 10.9.
107     *
108     * Fall back to the older style of availability checking for
109     * symbols introduced in macOS 10.10.
110     */
111 
112 #  ifdef HAVE_FSTATAT
113 #    define HAVE_FSTATAT_RUNTIME (fstatat != NULL)
114 #  endif
115 
116 #  ifdef HAVE_FACCESSAT
117 #    define HAVE_FACCESSAT_RUNTIME (faccessat != NULL)
118 #  endif
119 
120 #  ifdef HAVE_FCHMODAT
121 #    define HAVE_FCHMODAT_RUNTIME (fchmodat != NULL)
122 #  endif
123 
124 #  ifdef HAVE_FCHOWNAT
125 #    define HAVE_FCHOWNAT_RUNTIME (fchownat != NULL)
126 #  endif
127 
128 #  ifdef HAVE_LINKAT
129 #    define HAVE_LINKAT_RUNTIME (linkat != NULL)
130 #  endif
131 
132 #  ifdef HAVE_FDOPENDIR
133 #    define HAVE_FDOPENDIR_RUNTIME (fdopendir != NULL)
134 #  endif
135 
136 #  ifdef HAVE_MKDIRAT
137 #    define HAVE_MKDIRAT_RUNTIME (mkdirat != NULL)
138 #  endif
139 
140 #  ifdef HAVE_RENAMEAT
141 #    define HAVE_RENAMEAT_RUNTIME (renameat != NULL)
142 #  endif
143 
144 #  ifdef HAVE_UNLINKAT
145 #    define HAVE_UNLINKAT_RUNTIME (unlinkat != NULL)
146 #  endif
147 
148 #  ifdef HAVE_OPENAT
149 #    define HAVE_OPENAT_RUNTIME (openat != NULL)
150 #  endif
151 
152 #  ifdef HAVE_READLINKAT
153 #    define HAVE_READLINKAT_RUNTIME (readlinkat != NULL)
154 #  endif
155 
156 #  ifdef HAVE_SYMLINKAT
157 #    define HAVE_SYMLINKAT_RUNTIME (symlinkat != NULL)
158 #  endif
159 
160 #  ifdef HAVE_UTIMENSAT
161 #    define HAVE_UTIMENSAT_RUNTIME (utimensat != NULL)
162 #  endif
163 
164 #  ifdef HAVE_FUTIMENS
165 #    define HAVE_FUTIMENS_RUNTIME (futimens != NULL)
166 #  endif
167 
168 #  ifdef HAVE_PWRITEV
169 #    define HAVE_PWRITEV_RUNTIME (pwritev != NULL)
170 #  endif
171 
172 #  ifdef HAVE_MKFIFOAT
173 #    define HAVE_MKFIFOAT_RUNTIME (mkfifoat != NULL)
174 #  endif
175 
176 #  ifdef HAVE_MKNODAT
177 #    define HAVE_MKNODAT_RUNTIME (mknodat != NULL)
178 #  endif
179 
180 #endif
181 
182 #ifdef HAVE_FUTIMESAT
183 /* Some of the logic for weak linking depends on this assertion */
184 # error "HAVE_FUTIMESAT unexpectedly defined"
185 #endif
186 
187 #else
188 #  define HAVE_FSTATAT_RUNTIME 1
189 #  define HAVE_FACCESSAT_RUNTIME 1
190 #  define HAVE_FCHMODAT_RUNTIME 1
191 #  define HAVE_FCHOWNAT_RUNTIME 1
192 #  define HAVE_LINKAT_RUNTIME 1
193 #  define HAVE_FDOPENDIR_RUNTIME 1
194 #  define HAVE_MKDIRAT_RUNTIME 1
195 #  define HAVE_RENAMEAT_RUNTIME 1
196 #  define HAVE_UNLINKAT_RUNTIME 1
197 #  define HAVE_OPENAT_RUNTIME 1
198 #  define HAVE_READLINKAT_RUNTIME 1
199 #  define HAVE_SYMLINKAT_RUNTIME 1
200 #  define HAVE_FUTIMENS_RUNTIME 1
201 #  define HAVE_UTIMENSAT_RUNTIME 1
202 #  define HAVE_PWRITEV_RUNTIME 1
203 #  define HAVE_MKFIFOAT_RUNTIME 1
204 #  define HAVE_MKNODAT_RUNTIME 1
205 #endif
206 
207 
208 #ifdef __cplusplus
209 extern "C" {
210 #endif
211 
212 PyDoc_STRVAR(posix__doc__,
213 "This module provides access to operating system functionality that is\n\
214 standardized by the C Standard and the POSIX standard (a thinly\n\
215 disguised Unix interface).  Refer to the library manual and\n\
216 corresponding Unix manual entries for more information on calls.");
217 
218 
219 #ifdef HAVE_SYS_UIO_H
220 #  include <sys/uio.h>
221 #endif
222 
223 #ifdef HAVE_SYS_SYSMACROS_H
224 /* GNU C Library: major(), minor(), makedev() */
225 #  include <sys/sysmacros.h>
226 #endif
227 
228 #ifdef HAVE_SYS_TYPES_H
229 #  include <sys/types.h>
230 #endif /* HAVE_SYS_TYPES_H */
231 
232 #ifdef HAVE_SYS_STAT_H
233 #  include <sys/stat.h>
234 #endif /* HAVE_SYS_STAT_H */
235 
236 #ifdef HAVE_SYS_WAIT_H
237 #  include <sys/wait.h>           // WNOHANG
238 #endif
239 #ifdef HAVE_LINUX_WAIT_H
240 #  include <linux/wait.h>         // P_PIDFD
241 #endif
242 
243 #ifdef HAVE_SIGNAL_H
244 #  include <signal.h>
245 #endif
246 
247 #ifdef HAVE_FCNTL_H
248 #  include <fcntl.h>
249 #endif
250 
251 #ifdef HAVE_GRP_H
252 #  include <grp.h>
253 #endif
254 
255 #ifdef HAVE_SYSEXITS_H
256 #  include <sysexits.h>
257 #endif
258 
259 #ifdef HAVE_SYS_LOADAVG_H
260 #  include <sys/loadavg.h>
261 #endif
262 
263 #ifdef HAVE_SYS_SENDFILE_H
264 #  include <sys/sendfile.h>
265 #endif
266 
267 #if defined(__APPLE__)
268 #  include <copyfile.h>
269 #endif
270 
271 #ifdef HAVE_SCHED_H
272 #  include <sched.h>
273 #endif
274 
275 #ifdef HAVE_COPY_FILE_RANGE
276 #  include <unistd.h>
277 #endif
278 
279 #if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY)
280 #  undef HAVE_SCHED_SETAFFINITY
281 #endif
282 
283 #if defined(HAVE_SYS_XATTR_H) && defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__)
284 #  define USE_XATTRS
285 #  include <linux/limits.h>  // Needed for XATTR_SIZE_MAX on musl libc.
286 #endif
287 
288 #ifdef USE_XATTRS
289 #  include <sys/xattr.h>
290 #endif
291 
292 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
293 #  ifdef HAVE_SYS_SOCKET_H
294 #    include <sys/socket.h>
295 #  endif
296 #endif
297 
298 #ifdef HAVE_DLFCN_H
299 #  include <dlfcn.h>
300 #endif
301 
302 #ifdef __hpux
303 #  include <sys/mpctl.h>
304 #endif
305 
306 #if defined(__DragonFly__) || \
307     defined(__OpenBSD__)   || \
308     defined(__FreeBSD__)   || \
309     defined(__NetBSD__)    || \
310     defined(__APPLE__)
311 #  include <sys/sysctl.h>
312 #endif
313 
314 #ifdef HAVE_LINUX_RANDOM_H
315 #  include <linux/random.h>
316 #endif
317 #ifdef HAVE_GETRANDOM_SYSCALL
318 #  include <sys/syscall.h>
319 #endif
320 
321 #if defined(MS_WINDOWS)
322 #  define TERMSIZE_USE_CONIO
323 #elif defined(HAVE_SYS_IOCTL_H)
324 #  include <sys/ioctl.h>
325 #  if defined(HAVE_TERMIOS_H)
326 #    include <termios.h>
327 #  endif
328 #  if defined(TIOCGWINSZ)
329 #    define TERMSIZE_USE_IOCTL
330 #  endif
331 #endif /* MS_WINDOWS */
332 
333 /* Various compilers have only certain posix functions */
334 /* XXX Gosh I wish these were all moved into pyconfig.h */
335 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
336 #  define HAVE_OPENDIR    1
337 #  define HAVE_SYSTEM     1
338 #  include <process.h>
339 #else
340 #  ifdef _MSC_VER
341      /* Microsoft compiler */
342 #    define HAVE_GETPPID    1
343 #    define HAVE_GETLOGIN   1
344 #    define HAVE_SPAWNV     1
345 #    define HAVE_EXECV      1
346 #    define HAVE_WSPAWNV    1
347 #    define HAVE_WEXECV     1
348 #    define HAVE_PIPE       1
349 #    define HAVE_SYSTEM     1
350 #    define HAVE_CWAIT      1
351 #    define HAVE_FSYNC      1
352 #    define fsync _commit
353 #  endif  /* _MSC_VER */
354 #endif  /* ! __WATCOMC__ || __QNX__ */
355 
356 /*[clinic input]
357 # one of the few times we lie about this name!
358 module os
359 [clinic start generated code]*/
360 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/
361 
362 #ifndef _MSC_VER
363 
364 #if defined(__sgi)&&_COMPILER_VERSION>=700
365 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
366    (default) */
367 extern char        *ctermid_r(char *);
368 #endif
369 
370 #endif /* !_MSC_VER */
371 
372 #if defined(__VXWORKS__)
373 #  include <vxCpuLib.h>
374 #  include <rtpLib.h>
375 #  include <wait.h>
376 #  include <taskLib.h>
377 #  ifndef _P_WAIT
378 #    define _P_WAIT          0
379 #    define _P_NOWAIT        1
380 #    define _P_NOWAITO       1
381 #  endif
382 #endif /* __VXWORKS__ */
383 
384 #ifdef HAVE_POSIX_SPAWN
385 #  include <spawn.h>
386 #endif
387 
388 #ifdef HAVE_UTIME_H
389 #  include <utime.h>
390 #endif /* HAVE_UTIME_H */
391 
392 #ifdef HAVE_SYS_UTIME_H
393 #  include <sys/utime.h>
394 #  define HAVE_UTIME_H /* pretend we do for the rest of this file */
395 #endif /* HAVE_SYS_UTIME_H */
396 
397 #ifdef HAVE_SYS_TIMES_H
398 #  include <sys/times.h>
399 #endif /* HAVE_SYS_TIMES_H */
400 
401 #ifdef HAVE_SYS_PARAM_H
402 #  include <sys/param.h>
403 #endif /* HAVE_SYS_PARAM_H */
404 
405 #ifdef HAVE_SYS_UTSNAME_H
406 #  include <sys/utsname.h>
407 #endif /* HAVE_SYS_UTSNAME_H */
408 
409 #ifdef HAVE_DIRENT_H
410 #  include <dirent.h>
411 #  define NAMLEN(dirent) strlen((dirent)->d_name)
412 #else
413 #  if defined(__WATCOMC__) && !defined(__QNX__)
414 #    include <direct.h>
415 #    define NAMLEN(dirent) strlen((dirent)->d_name)
416 #  else
417 #    define dirent direct
418 #    define NAMLEN(dirent) (dirent)->d_namlen
419 #  endif
420 #  ifdef HAVE_SYS_NDIR_H
421 #    include <sys/ndir.h>
422 #  endif
423 #  ifdef HAVE_SYS_DIR_H
424 #    include <sys/dir.h>
425 #  endif
426 #  ifdef HAVE_NDIR_H
427 #    include <ndir.h>
428 #  endif
429 #endif
430 
431 #ifdef _MSC_VER
432 #  ifdef HAVE_DIRECT_H
433 #    include <direct.h>
434 #  endif
435 #  ifdef HAVE_IO_H
436 #    include <io.h>
437 #  endif
438 #  ifdef HAVE_PROCESS_H
439 #    include <process.h>
440 #  endif
441 #  include <malloc.h>
442 #endif /* _MSC_VER */
443 
444 #ifndef MAXPATHLEN
445 #  if defined(PATH_MAX) && PATH_MAX > 1024
446 #    define MAXPATHLEN PATH_MAX
447 #  else
448 #    define MAXPATHLEN 1024
449 #  endif
450 #endif /* MAXPATHLEN */
451 
452 #ifdef UNION_WAIT
453    /* Emulate some macros on systems that have a union instead of macros */
454 #  ifndef WIFEXITED
455 #    define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
456 #  endif
457 #  ifndef WEXITSTATUS
458 #    define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
459 #  endif
460 #  ifndef WTERMSIG
461 #    define WTERMSIG(u_wait) ((u_wait).w_termsig)
462 #  endif
463 #  define WAIT_TYPE union wait
464 #  define WAIT_STATUS_INT(s) (s.w_status)
465 #else
466    /* !UNION_WAIT */
467 #  define WAIT_TYPE int
468 #  define WAIT_STATUS_INT(s) (s)
469 #endif /* UNION_WAIT */
470 
471 /* Don't use the "_r" form if we don't need it (also, won't have a
472    prototype for it, at least on Solaris -- maybe others as well?). */
473 #if defined(HAVE_CTERMID_R)
474 #  define USE_CTERMID_R
475 #endif
476 
477 /* choose the appropriate stat and fstat functions and return structs */
478 #undef STAT
479 #undef FSTAT
480 #undef STRUCT_STAT
481 #ifdef MS_WINDOWS
482 #  define STAT win32_stat
483 #  define LSTAT win32_lstat
484 #  define FSTAT _Py_fstat_noraise
485 #  define STRUCT_STAT struct _Py_stat_struct
486 #else
487 #  define STAT stat
488 #  define LSTAT lstat
489 #  define FSTAT fstat
490 #  define STRUCT_STAT struct stat
491 #endif
492 
493 #if defined(MAJOR_IN_MKDEV)
494 #  include <sys/mkdev.h>
495 #else
496 #  if defined(MAJOR_IN_SYSMACROS)
497 #    include <sys/sysmacros.h>
498 #  endif
499 #  if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
500 #    include <sys/mkdev.h>
501 #  endif
502 #endif
503 
504 #ifdef MS_WINDOWS
505 #  define INITFUNC PyInit_nt
506 #  define MODNAME "nt"
507 #else
508 #  define INITFUNC PyInit_posix
509 #  define MODNAME "posix"
510 #endif
511 
512 #if defined(__sun)
513 /* Something to implement in autoconf, not present in autoconf 2.69 */
514 #  define HAVE_STRUCT_STAT_ST_FSTYPE 1
515 #endif
516 
517 /* memfd_create is either defined in sys/mman.h or sys/memfd.h
518  * linux/memfd.h defines additional flags
519  */
520 #ifdef HAVE_SYS_MMAN_H
521 #  include <sys/mman.h>
522 #endif
523 #ifdef HAVE_SYS_MEMFD_H
524 #  include <sys/memfd.h>
525 #endif
526 #ifdef HAVE_LINUX_MEMFD_H
527 #  include <linux/memfd.h>
528 #endif
529 
530 /* eventfd() */
531 #ifdef HAVE_SYS_EVENTFD_H
532 #  include <sys/eventfd.h>
533 #endif
534 
535 #ifdef _Py_MEMORY_SANITIZER
536 #  include <sanitizer/msan_interface.h>
537 #endif
538 
539 #ifdef HAVE_FORK
540 static void
run_at_forkers(PyObject * lst,int reverse)541 run_at_forkers(PyObject *lst, int reverse)
542 {
543     Py_ssize_t i;
544     PyObject *cpy;
545 
546     if (lst != NULL) {
547         assert(PyList_CheckExact(lst));
548 
549         /* Use a list copy in case register_at_fork() is called from
550          * one of the callbacks.
551          */
552         cpy = PyList_GetSlice(lst, 0, PyList_GET_SIZE(lst));
553         if (cpy == NULL)
554             PyErr_WriteUnraisable(lst);
555         else {
556             if (reverse)
557                 PyList_Reverse(cpy);
558             for (i = 0; i < PyList_GET_SIZE(cpy); i++) {
559                 PyObject *func, *res;
560                 func = PyList_GET_ITEM(cpy, i);
561                 res = _PyObject_CallNoArgs(func);
562                 if (res == NULL)
563                     PyErr_WriteUnraisable(func);
564                 else
565                     Py_DECREF(res);
566             }
567             Py_DECREF(cpy);
568         }
569     }
570 }
571 
572 void
PyOS_BeforeFork(void)573 PyOS_BeforeFork(void)
574 {
575     run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
576 
577     _PyImport_AcquireLock();
578 }
579 
580 void
PyOS_AfterFork_Parent(void)581 PyOS_AfterFork_Parent(void)
582 {
583     if (_PyImport_ReleaseLock() <= 0)
584         Py_FatalError("failed releasing import lock after fork");
585 
586     run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
587 }
588 
589 void
PyOS_AfterFork_Child(void)590 PyOS_AfterFork_Child(void)
591 {
592     PyStatus status;
593     _PyRuntimeState *runtime = &_PyRuntime;
594 
595     status = _PyGILState_Reinit(runtime);
596     if (_PyStatus_EXCEPTION(status)) {
597         goto fatal_error;
598     }
599 
600     PyThreadState *tstate = _PyThreadState_GET();
601     _Py_EnsureTstateNotNULL(tstate);
602 
603 #ifdef PY_HAVE_THREAD_NATIVE_ID
604     tstate->native_thread_id = PyThread_get_thread_native_id();
605 #endif
606 
607     status = _PyEval_ReInitThreads(tstate);
608     if (_PyStatus_EXCEPTION(status)) {
609         goto fatal_error;
610     }
611 
612     status = _PyImport_ReInitLock();
613     if (_PyStatus_EXCEPTION(status)) {
614         goto fatal_error;
615     }
616 
617     _PySignal_AfterFork();
618 
619     status = _PyRuntimeState_ReInitThreads(runtime);
620     if (_PyStatus_EXCEPTION(status)) {
621         goto fatal_error;
622     }
623 
624     status = _PyInterpreterState_DeleteExceptMain(runtime);
625     if (_PyStatus_EXCEPTION(status)) {
626         goto fatal_error;
627     }
628     assert(_PyThreadState_GET() == tstate);
629 
630     run_at_forkers(tstate->interp->after_forkers_child, 0);
631     return;
632 
633 fatal_error:
634     Py_ExitStatusException(status);
635 }
636 
637 static int
register_at_forker(PyObject ** lst,PyObject * func)638 register_at_forker(PyObject **lst, PyObject *func)
639 {
640     if (func == NULL)  /* nothing to register? do nothing. */
641         return 0;
642     if (*lst == NULL) {
643         *lst = PyList_New(0);
644         if (*lst == NULL)
645             return -1;
646     }
647     return PyList_Append(*lst, func);
648 }
649 #endif  /* HAVE_FORK */
650 
651 
652 /* Legacy wrapper */
653 void
PyOS_AfterFork(void)654 PyOS_AfterFork(void)
655 {
656 #ifdef HAVE_FORK
657     PyOS_AfterFork_Child();
658 #endif
659 }
660 
661 
662 #ifdef MS_WINDOWS
663 /* defined in fileutils.c */
664 void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
665 void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *,
666                                             ULONG, struct _Py_stat_struct *);
667 #endif
668 
669 
670 #ifndef MS_WINDOWS
671 PyObject *
_PyLong_FromUid(uid_t uid)672 _PyLong_FromUid(uid_t uid)
673 {
674     if (uid == (uid_t)-1)
675         return PyLong_FromLong(-1);
676     return PyLong_FromUnsignedLong(uid);
677 }
678 
679 PyObject *
_PyLong_FromGid(gid_t gid)680 _PyLong_FromGid(gid_t gid)
681 {
682     if (gid == (gid_t)-1)
683         return PyLong_FromLong(-1);
684     return PyLong_FromUnsignedLong(gid);
685 }
686 
687 int
_Py_Uid_Converter(PyObject * obj,uid_t * p)688 _Py_Uid_Converter(PyObject *obj, uid_t *p)
689 {
690     uid_t uid;
691     PyObject *index;
692     int overflow;
693     long result;
694     unsigned long uresult;
695 
696     index = _PyNumber_Index(obj);
697     if (index == NULL) {
698         PyErr_Format(PyExc_TypeError,
699                      "uid should be integer, not %.200s",
700                      _PyType_Name(Py_TYPE(obj)));
701         return 0;
702     }
703 
704     /*
705      * Handling uid_t is complicated for two reasons:
706      *  * Although uid_t is (always?) unsigned, it still
707      *    accepts -1.
708      *  * We don't know its size in advance--it may be
709      *    bigger than an int, or it may be smaller than
710      *    a long.
711      *
712      * So a bit of defensive programming is in order.
713      * Start with interpreting the value passed
714      * in as a signed long and see if it works.
715      */
716 
717     result = PyLong_AsLongAndOverflow(index, &overflow);
718 
719     if (!overflow) {
720         uid = (uid_t)result;
721 
722         if (result == -1) {
723             if (PyErr_Occurred())
724                 goto fail;
725             /* It's a legitimate -1, we're done. */
726             goto success;
727         }
728 
729         /* Any other negative number is disallowed. */
730         if (result < 0)
731             goto underflow;
732 
733         /* Ensure the value wasn't truncated. */
734         if (sizeof(uid_t) < sizeof(long) &&
735             (long)uid != result)
736             goto underflow;
737         goto success;
738     }
739 
740     if (overflow < 0)
741         goto underflow;
742 
743     /*
744      * Okay, the value overflowed a signed long.  If it
745      * fits in an *unsigned* long, it may still be okay,
746      * as uid_t may be unsigned long on this platform.
747      */
748     uresult = PyLong_AsUnsignedLong(index);
749     if (PyErr_Occurred()) {
750         if (PyErr_ExceptionMatches(PyExc_OverflowError))
751             goto overflow;
752         goto fail;
753     }
754 
755     uid = (uid_t)uresult;
756 
757     /*
758      * If uid == (uid_t)-1, the user actually passed in ULONG_MAX,
759      * but this value would get interpreted as (uid_t)-1  by chown
760      * and its siblings.   That's not what the user meant!  So we
761      * throw an overflow exception instead.   (We already
762      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
763      */
764     if (uid == (uid_t)-1)
765         goto overflow;
766 
767     /* Ensure the value wasn't truncated. */
768     if (sizeof(uid_t) < sizeof(long) &&
769         (unsigned long)uid != uresult)
770         goto overflow;
771     /* fallthrough */
772 
773 success:
774     Py_DECREF(index);
775     *p = uid;
776     return 1;
777 
778 underflow:
779     PyErr_SetString(PyExc_OverflowError,
780                     "uid is less than minimum");
781     goto fail;
782 
783 overflow:
784     PyErr_SetString(PyExc_OverflowError,
785                     "uid is greater than maximum");
786     /* fallthrough */
787 
788 fail:
789     Py_DECREF(index);
790     return 0;
791 }
792 
793 int
_Py_Gid_Converter(PyObject * obj,gid_t * p)794 _Py_Gid_Converter(PyObject *obj, gid_t *p)
795 {
796     gid_t gid;
797     PyObject *index;
798     int overflow;
799     long result;
800     unsigned long uresult;
801 
802     index = _PyNumber_Index(obj);
803     if (index == NULL) {
804         PyErr_Format(PyExc_TypeError,
805                      "gid should be integer, not %.200s",
806                      _PyType_Name(Py_TYPE(obj)));
807         return 0;
808     }
809 
810     /*
811      * Handling gid_t is complicated for two reasons:
812      *  * Although gid_t is (always?) unsigned, it still
813      *    accepts -1.
814      *  * We don't know its size in advance--it may be
815      *    bigger than an int, or it may be smaller than
816      *    a long.
817      *
818      * So a bit of defensive programming is in order.
819      * Start with interpreting the value passed
820      * in as a signed long and see if it works.
821      */
822 
823     result = PyLong_AsLongAndOverflow(index, &overflow);
824 
825     if (!overflow) {
826         gid = (gid_t)result;
827 
828         if (result == -1) {
829             if (PyErr_Occurred())
830                 goto fail;
831             /* It's a legitimate -1, we're done. */
832             goto success;
833         }
834 
835         /* Any other negative number is disallowed. */
836         if (result < 0) {
837             goto underflow;
838         }
839 
840         /* Ensure the value wasn't truncated. */
841         if (sizeof(gid_t) < sizeof(long) &&
842             (long)gid != result)
843             goto underflow;
844         goto success;
845     }
846 
847     if (overflow < 0)
848         goto underflow;
849 
850     /*
851      * Okay, the value overflowed a signed long.  If it
852      * fits in an *unsigned* long, it may still be okay,
853      * as gid_t may be unsigned long on this platform.
854      */
855     uresult = PyLong_AsUnsignedLong(index);
856     if (PyErr_Occurred()) {
857         if (PyErr_ExceptionMatches(PyExc_OverflowError))
858             goto overflow;
859         goto fail;
860     }
861 
862     gid = (gid_t)uresult;
863 
864     /*
865      * If gid == (gid_t)-1, the user actually passed in ULONG_MAX,
866      * but this value would get interpreted as (gid_t)-1  by chown
867      * and its siblings.   That's not what the user meant!  So we
868      * throw an overflow exception instead.   (We already
869      * handled a real -1 with PyLong_AsLongAndOverflow() above.)
870      */
871     if (gid == (gid_t)-1)
872         goto overflow;
873 
874     /* Ensure the value wasn't truncated. */
875     if (sizeof(gid_t) < sizeof(long) &&
876         (unsigned long)gid != uresult)
877         goto overflow;
878     /* fallthrough */
879 
880 success:
881     Py_DECREF(index);
882     *p = gid;
883     return 1;
884 
885 underflow:
886     PyErr_SetString(PyExc_OverflowError,
887                     "gid is less than minimum");
888     goto fail;
889 
890 overflow:
891     PyErr_SetString(PyExc_OverflowError,
892                     "gid is greater than maximum");
893     /* fallthrough */
894 
895 fail:
896     Py_DECREF(index);
897     return 0;
898 }
899 #endif /* MS_WINDOWS */
900 
901 
902 #define _PyLong_FromDev PyLong_FromLongLong
903 
904 
905 #if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) || defined(HAVE_DEVICE_MACROS)
906 static int
_Py_Dev_Converter(PyObject * obj,void * p)907 _Py_Dev_Converter(PyObject *obj, void *p)
908 {
909     *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj);
910     if (PyErr_Occurred())
911         return 0;
912     return 1;
913 }
914 #endif /* (HAVE_MKNOD && HAVE_MAKEDEV) || HAVE_DEVICE_MACROS */
915 
916 
917 #ifdef AT_FDCWD
918 /*
919  * Why the (int) cast?  Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965);
920  * without the int cast, the value gets interpreted as uint (4291925331),
921  * which doesn't play nicely with all the initializer lines in this file that
922  * look like this:
923  *      int dir_fd = DEFAULT_DIR_FD;
924  */
925 #define DEFAULT_DIR_FD (int)AT_FDCWD
926 #else
927 #define DEFAULT_DIR_FD (-100)
928 #endif
929 
930 static int
_fd_converter(PyObject * o,int * p)931 _fd_converter(PyObject *o, int *p)
932 {
933     int overflow;
934     long long_value;
935 
936     PyObject *index = _PyNumber_Index(o);
937     if (index == NULL) {
938         return 0;
939     }
940 
941     assert(PyLong_Check(index));
942     long_value = PyLong_AsLongAndOverflow(index, &overflow);
943     Py_DECREF(index);
944     assert(!PyErr_Occurred());
945     if (overflow > 0 || long_value > INT_MAX) {
946         PyErr_SetString(PyExc_OverflowError,
947                         "fd is greater than maximum");
948         return 0;
949     }
950     if (overflow < 0 || long_value < INT_MIN) {
951         PyErr_SetString(PyExc_OverflowError,
952                         "fd is less than minimum");
953         return 0;
954     }
955 
956     *p = (int)long_value;
957     return 1;
958 }
959 
960 static int
dir_fd_converter(PyObject * o,void * p)961 dir_fd_converter(PyObject *o, void *p)
962 {
963     if (o == Py_None) {
964         *(int *)p = DEFAULT_DIR_FD;
965         return 1;
966     }
967     else if (PyIndex_Check(o)) {
968         return _fd_converter(o, (int *)p);
969     }
970     else {
971         PyErr_Format(PyExc_TypeError,
972                      "argument should be integer or None, not %.200s",
973                      _PyType_Name(Py_TYPE(o)));
974         return 0;
975     }
976 }
977 
978 typedef struct {
979     PyObject *billion;
980     PyObject *DirEntryType;
981     PyObject *ScandirIteratorType;
982 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
983     PyObject *SchedParamType;
984 #endif
985     PyObject *StatResultType;
986     PyObject *StatVFSResultType;
987     PyObject *TerminalSizeType;
988     PyObject *TimesResultType;
989     PyObject *UnameResultType;
990 #if defined(HAVE_WAITID) && !defined(__APPLE__)
991     PyObject *WaitidResultType;
992 #endif
993 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
994     PyObject *struct_rusage;
995 #endif
996     PyObject *st_mode;
997 } _posixstate;
998 
999 
1000 static inline _posixstate*
get_posix_state(PyObject * module)1001 get_posix_state(PyObject *module)
1002 {
1003     void *state = _PyModule_GetState(module);
1004     assert(state != NULL);
1005     return (_posixstate *)state;
1006 }
1007 
1008 /*
1009  * A PyArg_ParseTuple "converter" function
1010  * that handles filesystem paths in the manner
1011  * preferred by the os module.
1012  *
1013  * path_converter accepts (Unicode) strings and their
1014  * subclasses, and bytes and their subclasses.  What
1015  * it does with the argument depends on the platform:
1016  *
1017  *   * On Windows, if we get a (Unicode) string we
1018  *     extract the wchar_t * and return it; if we get
1019  *     bytes we decode to wchar_t * and return that.
1020  *
1021  *   * On all other platforms, strings are encoded
1022  *     to bytes using PyUnicode_FSConverter, then we
1023  *     extract the char * from the bytes object and
1024  *     return that.
1025  *
1026  * path_converter also optionally accepts signed
1027  * integers (representing open file descriptors) instead
1028  * of path strings.
1029  *
1030  * Input fields:
1031  *   path.nullable
1032  *     If nonzero, the path is permitted to be None.
1033  *   path.allow_fd
1034  *     If nonzero, the path is permitted to be a file handle
1035  *     (a signed int) instead of a string.
1036  *   path.function_name
1037  *     If non-NULL, path_converter will use that as the name
1038  *     of the function in error messages.
1039  *     (If path.function_name is NULL it omits the function name.)
1040  *   path.argument_name
1041  *     If non-NULL, path_converter will use that as the name
1042  *     of the parameter in error messages.
1043  *     (If path.argument_name is NULL it uses "path".)
1044  *
1045  * Output fields:
1046  *   path.wide
1047  *     Points to the path if it was expressed as Unicode
1048  *     and was not encoded.  (Only used on Windows.)
1049  *   path.narrow
1050  *     Points to the path if it was expressed as bytes,
1051  *     or it was Unicode and was encoded to bytes. (On Windows,
1052  *     is a non-zero integer if the path was expressed as bytes.
1053  *     The type is deliberately incompatible to prevent misuse.)
1054  *   path.fd
1055  *     Contains a file descriptor if path.accept_fd was true
1056  *     and the caller provided a signed integer instead of any
1057  *     sort of string.
1058  *
1059  *     WARNING: if your "path" parameter is optional, and is
1060  *     unspecified, path_converter will never get called.
1061  *     So if you set allow_fd, you *MUST* initialize path.fd = -1
1062  *     yourself!
1063  *   path.length
1064  *     The length of the path in characters, if specified as
1065  *     a string.
1066  *   path.object
1067  *     The original object passed in (if get a PathLike object,
1068  *     the result of PyOS_FSPath() is treated as the original object).
1069  *     Own a reference to the object.
1070  *   path.cleanup
1071  *     For internal use only.  May point to a temporary object.
1072  *     (Pay no attention to the man behind the curtain.)
1073  *
1074  *   At most one of path.wide or path.narrow will be non-NULL.
1075  *   If path was None and path.nullable was set,
1076  *     or if path was an integer and path.allow_fd was set,
1077  *     both path.wide and path.narrow will be NULL
1078  *     and path.length will be 0.
1079  *
1080  *   path_converter takes care to not write to the path_t
1081  *   unless it's successful.  However it must reset the
1082  *   "cleanup" field each time it's called.
1083  *
1084  * Use as follows:
1085  *      path_t path;
1086  *      memset(&path, 0, sizeof(path));
1087  *      PyArg_ParseTuple(args, "O&", path_converter, &path);
1088  *      // ... use values from path ...
1089  *      path_cleanup(&path);
1090  *
1091  * (Note that if PyArg_Parse fails you don't need to call
1092  * path_cleanup().  However it is safe to do so.)
1093  */
1094 typedef struct {
1095     const char *function_name;
1096     const char *argument_name;
1097     int nullable;
1098     int allow_fd;
1099     const wchar_t *wide;
1100 #ifdef MS_WINDOWS
1101     BOOL narrow;
1102 #else
1103     const char *narrow;
1104 #endif
1105     int fd;
1106     Py_ssize_t length;
1107     PyObject *object;
1108     PyObject *cleanup;
1109 } path_t;
1110 
1111 #ifdef MS_WINDOWS
1112 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1113     {function_name, argument_name, nullable, allow_fd, NULL, FALSE, -1, 0, NULL, NULL}
1114 #else
1115 #define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \
1116     {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL}
1117 #endif
1118 
1119 static void
path_cleanup(path_t * path)1120 path_cleanup(path_t *path)
1121 {
1122 #if !USE_UNICODE_WCHAR_CACHE
1123     wchar_t *wide = (wchar_t *)path->wide;
1124     path->wide = NULL;
1125     PyMem_Free(wide);
1126 #endif /* USE_UNICODE_WCHAR_CACHE */
1127     Py_CLEAR(path->object);
1128     Py_CLEAR(path->cleanup);
1129 }
1130 
1131 static int
path_converter(PyObject * o,void * p)1132 path_converter(PyObject *o, void *p)
1133 {
1134     path_t *path = (path_t *)p;
1135     PyObject *bytes = NULL;
1136     Py_ssize_t length = 0;
1137     int is_index, is_buffer, is_bytes, is_unicode;
1138     const char *narrow;
1139 #ifdef MS_WINDOWS
1140     PyObject *wo = NULL;
1141     wchar_t *wide = NULL;
1142 #endif
1143 
1144 #define FORMAT_EXCEPTION(exc, fmt) \
1145     PyErr_Format(exc, "%s%s" fmt, \
1146         path->function_name ? path->function_name : "", \
1147         path->function_name ? ": "                : "", \
1148         path->argument_name ? path->argument_name : "path")
1149 
1150     /* Py_CLEANUP_SUPPORTED support */
1151     if (o == NULL) {
1152         path_cleanup(path);
1153         return 1;
1154     }
1155 
1156     /* Ensure it's always safe to call path_cleanup(). */
1157     path->object = path->cleanup = NULL;
1158     /* path->object owns a reference to the original object */
1159     Py_INCREF(o);
1160 
1161     if ((o == Py_None) && path->nullable) {
1162         path->wide = NULL;
1163 #ifdef MS_WINDOWS
1164         path->narrow = FALSE;
1165 #else
1166         path->narrow = NULL;
1167 #endif
1168         path->fd = -1;
1169         goto success_exit;
1170     }
1171 
1172     /* Only call this here so that we don't treat the return value of
1173        os.fspath() as an fd or buffer. */
1174     is_index = path->allow_fd && PyIndex_Check(o);
1175     is_buffer = PyObject_CheckBuffer(o);
1176     is_bytes = PyBytes_Check(o);
1177     is_unicode = PyUnicode_Check(o);
1178 
1179     if (!is_index && !is_buffer && !is_unicode && !is_bytes) {
1180         /* Inline PyOS_FSPath() for better error messages. */
1181         PyObject *func, *res;
1182 
1183         func = _PyObject_LookupSpecial(o, &_Py_ID(__fspath__));
1184         if (NULL == func) {
1185             goto error_format;
1186         }
1187         res = _PyObject_CallNoArgs(func);
1188         Py_DECREF(func);
1189         if (NULL == res) {
1190             goto error_exit;
1191         }
1192         else if (PyUnicode_Check(res)) {
1193             is_unicode = 1;
1194         }
1195         else if (PyBytes_Check(res)) {
1196             is_bytes = 1;
1197         }
1198         else {
1199             PyErr_Format(PyExc_TypeError,
1200                  "expected %.200s.__fspath__() to return str or bytes, "
1201                  "not %.200s", _PyType_Name(Py_TYPE(o)),
1202                  _PyType_Name(Py_TYPE(res)));
1203             Py_DECREF(res);
1204             goto error_exit;
1205         }
1206 
1207         /* still owns a reference to the original object */
1208         Py_DECREF(o);
1209         o = res;
1210     }
1211 
1212     if (is_unicode) {
1213 #ifdef MS_WINDOWS
1214 #if USE_UNICODE_WCHAR_CACHE
1215 _Py_COMP_DIAG_PUSH
1216 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1217         wide = PyUnicode_AsUnicodeAndSize(o, &length);
1218 _Py_COMP_DIAG_POP
1219 #else /* USE_UNICODE_WCHAR_CACHE */
1220         wide = PyUnicode_AsWideCharString(o, &length);
1221 #endif /* USE_UNICODE_WCHAR_CACHE */
1222         if (!wide) {
1223             goto error_exit;
1224         }
1225         if (length > 32767) {
1226             FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1227             goto error_exit;
1228         }
1229         if (wcslen(wide) != length) {
1230             FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1231             goto error_exit;
1232         }
1233 
1234         path->wide = wide;
1235         path->narrow = FALSE;
1236         path->fd = -1;
1237 #if !USE_UNICODE_WCHAR_CACHE
1238         wide = NULL;
1239 #endif /* USE_UNICODE_WCHAR_CACHE */
1240         goto success_exit;
1241 #else
1242         if (!PyUnicode_FSConverter(o, &bytes)) {
1243             goto error_exit;
1244         }
1245 #endif
1246     }
1247     else if (is_bytes) {
1248         bytes = o;
1249         Py_INCREF(bytes);
1250     }
1251     else if (is_buffer) {
1252         /* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1253            after removing support of non-bytes buffer objects. */
1254         if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
1255             "%s%s%s should be %s, not %.200s",
1256             path->function_name ? path->function_name : "",
1257             path->function_name ? ": "                : "",
1258             path->argument_name ? path->argument_name : "path",
1259             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1260                                                "integer or None" :
1261             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1262             path->nullable ? "string, bytes, os.PathLike or None" :
1263                              "string, bytes or os.PathLike",
1264             _PyType_Name(Py_TYPE(o)))) {
1265             goto error_exit;
1266         }
1267         bytes = PyBytes_FromObject(o);
1268         if (!bytes) {
1269             goto error_exit;
1270         }
1271     }
1272     else if (is_index) {
1273         if (!_fd_converter(o, &path->fd)) {
1274             goto error_exit;
1275         }
1276         path->wide = NULL;
1277 #ifdef MS_WINDOWS
1278         path->narrow = FALSE;
1279 #else
1280         path->narrow = NULL;
1281 #endif
1282         goto success_exit;
1283     }
1284     else {
1285  error_format:
1286         PyErr_Format(PyExc_TypeError, "%s%s%s should be %s, not %.200s",
1287             path->function_name ? path->function_name : "",
1288             path->function_name ? ": "                : "",
1289             path->argument_name ? path->argument_name : "path",
1290             path->allow_fd && path->nullable ? "string, bytes, os.PathLike, "
1291                                                "integer or None" :
1292             path->allow_fd ? "string, bytes, os.PathLike or integer" :
1293             path->nullable ? "string, bytes, os.PathLike or None" :
1294                              "string, bytes or os.PathLike",
1295             _PyType_Name(Py_TYPE(o)));
1296         goto error_exit;
1297     }
1298 
1299     length = PyBytes_GET_SIZE(bytes);
1300     narrow = PyBytes_AS_STRING(bytes);
1301     if ((size_t)length != strlen(narrow)) {
1302         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1303         goto error_exit;
1304     }
1305 
1306 #ifdef MS_WINDOWS
1307     wo = PyUnicode_DecodeFSDefaultAndSize(
1308         narrow,
1309         length
1310     );
1311     if (!wo) {
1312         goto error_exit;
1313     }
1314 
1315 #if USE_UNICODE_WCHAR_CACHE
1316 _Py_COMP_DIAG_PUSH
1317 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
1318     wide = PyUnicode_AsUnicodeAndSize(wo, &length);
1319 _Py_COMP_DIAG_POP
1320 #else /* USE_UNICODE_WCHAR_CACHE */
1321     wide = PyUnicode_AsWideCharString(wo, &length);
1322     Py_DECREF(wo);
1323 #endif /* USE_UNICODE_WCHAR_CACHE */
1324     if (!wide) {
1325         goto error_exit;
1326     }
1327     if (length > 32767) {
1328         FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows");
1329         goto error_exit;
1330     }
1331     if (wcslen(wide) != length) {
1332         FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s");
1333         goto error_exit;
1334     }
1335     path->wide = wide;
1336     path->narrow = TRUE;
1337     Py_DECREF(bytes);
1338 #if USE_UNICODE_WCHAR_CACHE
1339     path->cleanup = wo;
1340 #else /* USE_UNICODE_WCHAR_CACHE */
1341     wide = NULL;
1342 #endif /* USE_UNICODE_WCHAR_CACHE */
1343 #else
1344     path->wide = NULL;
1345     path->narrow = narrow;
1346     if (bytes == o) {
1347         /* Still a reference owned by path->object, don't have to
1348            worry about path->narrow is used after free. */
1349         Py_DECREF(bytes);
1350     }
1351     else {
1352         path->cleanup = bytes;
1353     }
1354 #endif
1355     path->fd = -1;
1356 
1357  success_exit:
1358     path->length = length;
1359     path->object = o;
1360     return Py_CLEANUP_SUPPORTED;
1361 
1362  error_exit:
1363     Py_XDECREF(o);
1364     Py_XDECREF(bytes);
1365 #ifdef MS_WINDOWS
1366 #if USE_UNICODE_WCHAR_CACHE
1367     Py_XDECREF(wo);
1368 #else /* USE_UNICODE_WCHAR_CACHE */
1369     PyMem_Free(wide);
1370 #endif /* USE_UNICODE_WCHAR_CACHE */
1371 #endif
1372     return 0;
1373 }
1374 
1375 static void
argument_unavailable_error(const char * function_name,const char * argument_name)1376 argument_unavailable_error(const char *function_name, const char *argument_name)
1377 {
1378     PyErr_Format(PyExc_NotImplementedError,
1379         "%s%s%s unavailable on this platform",
1380         (function_name != NULL) ? function_name : "",
1381         (function_name != NULL) ? ": ": "",
1382         argument_name);
1383 }
1384 
1385 static int
dir_fd_unavailable(PyObject * o,void * p)1386 dir_fd_unavailable(PyObject *o, void *p)
1387 {
1388     int dir_fd;
1389     if (!dir_fd_converter(o, &dir_fd))
1390         return 0;
1391     if (dir_fd != DEFAULT_DIR_FD) {
1392         argument_unavailable_error(NULL, "dir_fd");
1393         return 0;
1394     }
1395     *(int *)p = dir_fd;
1396     return 1;
1397 }
1398 
1399 static int
fd_specified(const char * function_name,int fd)1400 fd_specified(const char *function_name, int fd)
1401 {
1402     if (fd == -1)
1403         return 0;
1404 
1405     argument_unavailable_error(function_name, "fd");
1406     return 1;
1407 }
1408 
1409 static int
follow_symlinks_specified(const char * function_name,int follow_symlinks)1410 follow_symlinks_specified(const char *function_name, int follow_symlinks)
1411 {
1412     if (follow_symlinks)
1413         return 0;
1414 
1415     argument_unavailable_error(function_name, "follow_symlinks");
1416     return 1;
1417 }
1418 
1419 static int
path_and_dir_fd_invalid(const char * function_name,path_t * path,int dir_fd)1420 path_and_dir_fd_invalid(const char *function_name, path_t *path, int dir_fd)
1421 {
1422     if (!path->wide && (dir_fd != DEFAULT_DIR_FD)
1423 #ifndef MS_WINDOWS
1424         && !path->narrow
1425 #endif
1426     ) {
1427         PyErr_Format(PyExc_ValueError,
1428                      "%s: can't specify dir_fd without matching path",
1429                      function_name);
1430         return 1;
1431     }
1432     return 0;
1433 }
1434 
1435 static int
dir_fd_and_fd_invalid(const char * function_name,int dir_fd,int fd)1436 dir_fd_and_fd_invalid(const char *function_name, int dir_fd, int fd)
1437 {
1438     if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) {
1439         PyErr_Format(PyExc_ValueError,
1440                      "%s: can't specify both dir_fd and fd",
1441                      function_name);
1442         return 1;
1443     }
1444     return 0;
1445 }
1446 
1447 static int
fd_and_follow_symlinks_invalid(const char * function_name,int fd,int follow_symlinks)1448 fd_and_follow_symlinks_invalid(const char *function_name, int fd,
1449                                int follow_symlinks)
1450 {
1451     if ((fd > 0) && (!follow_symlinks)) {
1452         PyErr_Format(PyExc_ValueError,
1453                      "%s: cannot use fd and follow_symlinks together",
1454                      function_name);
1455         return 1;
1456     }
1457     return 0;
1458 }
1459 
1460 static int
dir_fd_and_follow_symlinks_invalid(const char * function_name,int dir_fd,int follow_symlinks)1461 dir_fd_and_follow_symlinks_invalid(const char *function_name, int dir_fd,
1462                                    int follow_symlinks)
1463 {
1464     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
1465         PyErr_Format(PyExc_ValueError,
1466                      "%s: cannot use dir_fd and follow_symlinks together",
1467                      function_name);
1468         return 1;
1469     }
1470     return 0;
1471 }
1472 
1473 #ifdef MS_WINDOWS
1474     typedef long long Py_off_t;
1475 #else
1476     typedef off_t Py_off_t;
1477 #endif
1478 
1479 static int
Py_off_t_converter(PyObject * arg,void * addr)1480 Py_off_t_converter(PyObject *arg, void *addr)
1481 {
1482 #ifdef HAVE_LARGEFILE_SUPPORT
1483     *((Py_off_t *)addr) = PyLong_AsLongLong(arg);
1484 #else
1485     *((Py_off_t *)addr) = PyLong_AsLong(arg);
1486 #endif
1487     if (PyErr_Occurred())
1488         return 0;
1489     return 1;
1490 }
1491 
1492 static PyObject *
PyLong_FromPy_off_t(Py_off_t offset)1493 PyLong_FromPy_off_t(Py_off_t offset)
1494 {
1495 #ifdef HAVE_LARGEFILE_SUPPORT
1496     return PyLong_FromLongLong(offset);
1497 #else
1498     return PyLong_FromLong(offset);
1499 #endif
1500 }
1501 
1502 #ifdef HAVE_SIGSET_T
1503 /* Convert an iterable of integers to a sigset.
1504    Return 1 on success, return 0 and raise an exception on error. */
1505 int
_Py_Sigset_Converter(PyObject * obj,void * addr)1506 _Py_Sigset_Converter(PyObject *obj, void *addr)
1507 {
1508     sigset_t *mask = (sigset_t *)addr;
1509     PyObject *iterator, *item;
1510     long signum;
1511     int overflow;
1512 
1513     // The extra parens suppress the unreachable-code warning with clang on MacOS
1514     if (sigemptyset(mask) < (0)) {
1515         /* Probably only if mask == NULL. */
1516         PyErr_SetFromErrno(PyExc_OSError);
1517         return 0;
1518     }
1519 
1520     iterator = PyObject_GetIter(obj);
1521     if (iterator == NULL) {
1522         return 0;
1523     }
1524 
1525     while ((item = PyIter_Next(iterator)) != NULL) {
1526         signum = PyLong_AsLongAndOverflow(item, &overflow);
1527         Py_DECREF(item);
1528         if (signum <= 0 || signum >= Py_NSIG) {
1529             if (overflow || signum != -1 || !PyErr_Occurred()) {
1530                 PyErr_Format(PyExc_ValueError,
1531                              "signal number %ld out of range [1; %i]",
1532                              signum, Py_NSIG - 1);
1533             }
1534             goto error;
1535         }
1536         if (sigaddset(mask, (int)signum)) {
1537             if (errno != EINVAL) {
1538                 /* Probably impossible */
1539                 PyErr_SetFromErrno(PyExc_OSError);
1540                 goto error;
1541             }
1542             /* For backwards compatibility, allow idioms such as
1543              * `range(1, NSIG)` but warn about invalid signal numbers
1544              */
1545             const char msg[] =
1546                 "invalid signal number %ld, please use valid_signals()";
1547             if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) {
1548                 goto error;
1549             }
1550         }
1551     }
1552     if (!PyErr_Occurred()) {
1553         Py_DECREF(iterator);
1554         return 1;
1555     }
1556 
1557 error:
1558     Py_DECREF(iterator);
1559     return 0;
1560 }
1561 #endif /* HAVE_SIGSET_T */
1562 
1563 #ifdef MS_WINDOWS
1564 
1565 static int
win32_get_reparse_tag(HANDLE reparse_point_handle,ULONG * reparse_tag)1566 win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
1567 {
1568     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
1569     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
1570     DWORD n_bytes_returned;
1571 
1572     if (0 == DeviceIoControl(
1573         reparse_point_handle,
1574         FSCTL_GET_REPARSE_POINT,
1575         NULL, 0, /* in buffer */
1576         target_buffer, sizeof(target_buffer),
1577         &n_bytes_returned,
1578         NULL)) /* we're not using OVERLAPPED_IO */
1579         return FALSE;
1580 
1581     if (reparse_tag)
1582         *reparse_tag = rdb->ReparseTag;
1583 
1584     return TRUE;
1585 }
1586 
1587 #endif /* MS_WINDOWS */
1588 
1589 /* Return a dictionary corresponding to the POSIX environment table */
1590 #if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1591 /* On Darwin/MacOSX a shared library or framework has no access to
1592 ** environ directly, we must obtain it with _NSGetEnviron(). See also
1593 ** man environ(7).
1594 */
1595 #include <crt_externs.h>
1596 #elif !defined(_MSC_VER) && (!defined(__WATCOMC__) || defined(__QNX__) || defined(__VXWORKS__))
1597 extern char **environ;
1598 #endif /* !_MSC_VER */
1599 
1600 static PyObject *
convertenviron(void)1601 convertenviron(void)
1602 {
1603     PyObject *d;
1604 #ifdef MS_WINDOWS
1605     wchar_t **e;
1606 #else
1607     char **e;
1608 #endif
1609 
1610     d = PyDict_New();
1611     if (d == NULL)
1612         return NULL;
1613 #ifdef MS_WINDOWS
1614     /* _wenviron must be initialized in this way if the program is started
1615        through main() instead of wmain(). */
1616     _wgetenv(L"");
1617     e = _wenviron;
1618 #elif defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED))
1619     /* environ is not accessible as an extern in a shared object on OSX; use
1620        _NSGetEnviron to resolve it. The value changes if you add environment
1621        variables between calls to Py_Initialize, so don't cache the value. */
1622     e = *_NSGetEnviron();
1623 #else
1624     e = environ;
1625 #endif
1626     if (e == NULL)
1627         return d;
1628     for (; *e != NULL; e++) {
1629         PyObject *k;
1630         PyObject *v;
1631 #ifdef MS_WINDOWS
1632         const wchar_t *p = wcschr(*e, L'=');
1633 #else
1634         const char *p = strchr(*e, '=');
1635 #endif
1636         if (p == NULL)
1637             continue;
1638 #ifdef MS_WINDOWS
1639         k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
1640 #else
1641         k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
1642 #endif
1643         if (k == NULL) {
1644             Py_DECREF(d);
1645             return NULL;
1646         }
1647 #ifdef MS_WINDOWS
1648         v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
1649 #else
1650         v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
1651 #endif
1652         if (v == NULL) {
1653             Py_DECREF(k);
1654             Py_DECREF(d);
1655             return NULL;
1656         }
1657         if (PyDict_SetDefault(d, k, v) == NULL) {
1658             Py_DECREF(v);
1659             Py_DECREF(k);
1660             Py_DECREF(d);
1661             return NULL;
1662         }
1663         Py_DECREF(k);
1664         Py_DECREF(v);
1665     }
1666     return d;
1667 }
1668 
1669 /* Set a POSIX-specific error from errno, and return NULL */
1670 
1671 static PyObject *
posix_error(void)1672 posix_error(void)
1673 {
1674     return PyErr_SetFromErrno(PyExc_OSError);
1675 }
1676 
1677 #ifdef MS_WINDOWS
1678 static PyObject *
win32_error(const char * function,const char * filename)1679 win32_error(const char* function, const char* filename)
1680 {
1681     /* XXX We should pass the function name along in the future.
1682        (winreg.c also wants to pass the function name.)
1683        This would however require an additional param to the
1684        Windows error object, which is non-trivial.
1685     */
1686     errno = GetLastError();
1687     if (filename)
1688         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
1689     else
1690         return PyErr_SetFromWindowsErr(errno);
1691 }
1692 
1693 static PyObject *
win32_error_object_err(const char * function,PyObject * filename,DWORD err)1694 win32_error_object_err(const char* function, PyObject* filename, DWORD err)
1695 {
1696     /* XXX - see win32_error for comments on 'function' */
1697     if (filename)
1698         return PyErr_SetExcFromWindowsErrWithFilenameObject(
1699                     PyExc_OSError,
1700                     err,
1701                     filename);
1702     else
1703         return PyErr_SetFromWindowsErr(err);
1704 }
1705 
1706 static PyObject *
win32_error_object(const char * function,PyObject * filename)1707 win32_error_object(const char* function, PyObject* filename)
1708 {
1709     errno = GetLastError();
1710     return win32_error_object_err(function, filename, errno);
1711 }
1712 
1713 #endif /* MS_WINDOWS */
1714 
1715 static PyObject *
posix_path_object_error(PyObject * path)1716 posix_path_object_error(PyObject *path)
1717 {
1718     return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
1719 }
1720 
1721 static PyObject *
path_object_error(PyObject * path)1722 path_object_error(PyObject *path)
1723 {
1724 #ifdef MS_WINDOWS
1725     return PyErr_SetExcFromWindowsErrWithFilenameObject(
1726                 PyExc_OSError, 0, path);
1727 #else
1728     return posix_path_object_error(path);
1729 #endif
1730 }
1731 
1732 static PyObject *
path_object_error2(PyObject * path,PyObject * path2)1733 path_object_error2(PyObject *path, PyObject *path2)
1734 {
1735 #ifdef MS_WINDOWS
1736     return PyErr_SetExcFromWindowsErrWithFilenameObjects(
1737                 PyExc_OSError, 0, path, path2);
1738 #else
1739     return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path, path2);
1740 #endif
1741 }
1742 
1743 static PyObject *
path_error(path_t * path)1744 path_error(path_t *path)
1745 {
1746     return path_object_error(path->object);
1747 }
1748 
1749 static PyObject *
posix_path_error(path_t * path)1750 posix_path_error(path_t *path)
1751 {
1752     return posix_path_object_error(path->object);
1753 }
1754 
1755 static PyObject *
path_error2(path_t * path,path_t * path2)1756 path_error2(path_t *path, path_t *path2)
1757 {
1758     return path_object_error2(path->object, path2->object);
1759 }
1760 
1761 
1762 /* POSIX generic methods */
1763 
1764 static PyObject *
posix_fildes_fd(int fd,int (* func)(int))1765 posix_fildes_fd(int fd, int (*func)(int))
1766 {
1767     int res;
1768     int async_err = 0;
1769 
1770     do {
1771         Py_BEGIN_ALLOW_THREADS
1772         _Py_BEGIN_SUPPRESS_IPH
1773         res = (*func)(fd);
1774         _Py_END_SUPPRESS_IPH
1775         Py_END_ALLOW_THREADS
1776     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
1777     if (res != 0)
1778         return (!async_err) ? posix_error() : NULL;
1779     Py_RETURN_NONE;
1780 }
1781 
1782 
1783 #ifdef MS_WINDOWS
1784 /* This is a reimplementation of the C library's chdir function,
1785    but one that produces Win32 errors instead of DOS error codes.
1786    chdir is essentially a wrapper around SetCurrentDirectory; however,
1787    it also needs to set "magic" environment variables indicating
1788    the per-drive current directory, which are of the form =<drive>: */
1789 static BOOL __stdcall
win32_wchdir(LPCWSTR path)1790 win32_wchdir(LPCWSTR path)
1791 {
1792     wchar_t path_buf[MAX_PATH], *new_path = path_buf;
1793     int result;
1794     wchar_t env[4] = L"=x:";
1795 
1796     if(!SetCurrentDirectoryW(path))
1797         return FALSE;
1798     result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path);
1799     if (!result)
1800         return FALSE;
1801     if (result > Py_ARRAY_LENGTH(path_buf)) {
1802         new_path = PyMem_RawMalloc(result * sizeof(wchar_t));
1803         if (!new_path) {
1804             SetLastError(ERROR_OUTOFMEMORY);
1805             return FALSE;
1806         }
1807         result = GetCurrentDirectoryW(result, new_path);
1808         if (!result) {
1809             PyMem_RawFree(new_path);
1810             return FALSE;
1811         }
1812     }
1813     int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 ||
1814                             wcsncmp(new_path, L"//", 2) == 0);
1815     if (!is_unc_like_path) {
1816         env[1] = new_path[0];
1817         result = SetEnvironmentVariableW(env, new_path);
1818     }
1819     if (new_path != path_buf)
1820         PyMem_RawFree(new_path);
1821     return result ? TRUE : FALSE;
1822 }
1823 #endif
1824 
1825 #ifdef MS_WINDOWS
1826 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
1827    - time stamps are restricted to second resolution
1828    - file modification times suffer from forth-and-back conversions between
1829      UTC and local time
1830    Therefore, we implement our own stat, based on the Win32 API directly.
1831 */
1832 #define HAVE_STAT_NSEC 1
1833 #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1
1834 #define HAVE_STRUCT_STAT_ST_REPARSE_TAG 1
1835 
1836 static void
find_data_to_file_info(WIN32_FIND_DATAW * pFileData,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1837 find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
1838                        BY_HANDLE_FILE_INFORMATION *info,
1839                        ULONG *reparse_tag)
1840 {
1841     memset(info, 0, sizeof(*info));
1842     info->dwFileAttributes = pFileData->dwFileAttributes;
1843     info->ftCreationTime   = pFileData->ftCreationTime;
1844     info->ftLastAccessTime = pFileData->ftLastAccessTime;
1845     info->ftLastWriteTime  = pFileData->ftLastWriteTime;
1846     info->nFileSizeHigh    = pFileData->nFileSizeHigh;
1847     info->nFileSizeLow     = pFileData->nFileSizeLow;
1848 /*  info->nNumberOfLinks   = 1; */
1849     if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1850         *reparse_tag = pFileData->dwReserved0;
1851     else
1852         *reparse_tag = 0;
1853 }
1854 
1855 static BOOL
attributes_from_dir(LPCWSTR pszFile,BY_HANDLE_FILE_INFORMATION * info,ULONG * reparse_tag)1856 attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1857 {
1858     HANDLE hFindFile;
1859     WIN32_FIND_DATAW FileData;
1860     LPCWSTR filename = pszFile;
1861     size_t n = wcslen(pszFile);
1862     if (n && (pszFile[n - 1] == L'\\' || pszFile[n - 1] == L'/')) {
1863         // cannot use PyMem_Malloc here because we do not hold the GIL
1864         filename = (LPCWSTR)malloc((n + 1) * sizeof(filename[0]));
1865         wcsncpy_s((LPWSTR)filename, n + 1, pszFile, n);
1866         while (--n > 0 && (filename[n] == L'\\' || filename[n] == L'/')) {
1867             ((LPWSTR)filename)[n] = L'\0';
1868         }
1869         if (!n || (n == 1 && filename[1] == L':')) {
1870             // Nothing left to query
1871             free((void *)filename);
1872             return FALSE;
1873         }
1874     }
1875     hFindFile = FindFirstFileW(filename, &FileData);
1876     if (pszFile != filename) {
1877         free((void *)filename);
1878     }
1879     if (hFindFile == INVALID_HANDLE_VALUE) {
1880         return FALSE;
1881     }
1882     FindClose(hFindFile);
1883     find_data_to_file_info(&FileData, info, reparse_tag);
1884     return TRUE;
1885 }
1886 
1887 static int
win32_xstat_impl(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)1888 win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
1889                  BOOL traverse)
1890 {
1891     HANDLE hFile;
1892     BY_HANDLE_FILE_INFORMATION fileInfo;
1893     FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
1894     DWORD fileType, error;
1895     BOOL isUnhandledTag = FALSE;
1896     int retval = 0;
1897 
1898     DWORD access = FILE_READ_ATTRIBUTES;
1899     DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; /* Allow opening directories. */
1900     if (!traverse) {
1901         flags |= FILE_FLAG_OPEN_REPARSE_POINT;
1902     }
1903 
1904     hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING, flags, NULL);
1905     if (hFile == INVALID_HANDLE_VALUE) {
1906         /* Either the path doesn't exist, or the caller lacks access. */
1907         error = GetLastError();
1908         switch (error) {
1909         case ERROR_ACCESS_DENIED:     /* Cannot sync or read attributes. */
1910         case ERROR_SHARING_VIOLATION: /* It's a paging file. */
1911             /* Try reading the parent directory. */
1912             if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
1913                 /* Cannot read the parent directory. */
1914                 switch (GetLastError()) {
1915                 case ERROR_FILE_NOT_FOUND: /* File cannot be found */
1916                 case ERROR_PATH_NOT_FOUND: /* File parent directory cannot be found */
1917                 case ERROR_NOT_READY: /* Drive exists but unavailable */
1918                 case ERROR_BAD_NET_NAME: /* Remote drive unavailable */
1919                     break;
1920                 /* Restore the error from CreateFileW(). */
1921                 default:
1922                     SetLastError(error);
1923                 }
1924 
1925                 return -1;
1926             }
1927             if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1928                 if (traverse ||
1929                     !IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
1930                     /* The stat call has to traverse but cannot, so fail. */
1931                     SetLastError(error);
1932                     return -1;
1933                 }
1934             }
1935             break;
1936 
1937         case ERROR_INVALID_PARAMETER:
1938             /* \\.\con requires read or write access. */
1939             hFile = CreateFileW(path, access | GENERIC_READ,
1940                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1941                         OPEN_EXISTING, flags, NULL);
1942             if (hFile == INVALID_HANDLE_VALUE) {
1943                 SetLastError(error);
1944                 return -1;
1945             }
1946             break;
1947 
1948         case ERROR_CANT_ACCESS_FILE:
1949             /* bpo37834: open unhandled reparse points if traverse fails. */
1950             if (traverse) {
1951                 traverse = FALSE;
1952                 isUnhandledTag = TRUE;
1953                 hFile = CreateFileW(path, access, 0, NULL, OPEN_EXISTING,
1954                             flags | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1955             }
1956             if (hFile == INVALID_HANDLE_VALUE) {
1957                 SetLastError(error);
1958                 return -1;
1959             }
1960             break;
1961 
1962         default:
1963             return -1;
1964         }
1965     }
1966 
1967     if (hFile != INVALID_HANDLE_VALUE) {
1968         /* Handle types other than files on disk. */
1969         fileType = GetFileType(hFile);
1970         if (fileType != FILE_TYPE_DISK) {
1971             if (fileType == FILE_TYPE_UNKNOWN && GetLastError() != 0) {
1972                 retval = -1;
1973                 goto cleanup;
1974             }
1975             DWORD fileAttributes = GetFileAttributesW(path);
1976             memset(result, 0, sizeof(*result));
1977             if (fileAttributes != INVALID_FILE_ATTRIBUTES &&
1978                 fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1979                 /* \\.\pipe\ or \\.\mailslot\ */
1980                 result->st_mode = _S_IFDIR;
1981             } else if (fileType == FILE_TYPE_CHAR) {
1982                 /* \\.\nul */
1983                 result->st_mode = _S_IFCHR;
1984             } else if (fileType == FILE_TYPE_PIPE) {
1985                 /* \\.\pipe\spam */
1986                 result->st_mode = _S_IFIFO;
1987             }
1988             /* FILE_TYPE_UNKNOWN, e.g. \\.\mailslot\waitfor.exe\spam */
1989             goto cleanup;
1990         }
1991 
1992         /* Query the reparse tag, and traverse a non-link. */
1993         if (!traverse) {
1994             if (!GetFileInformationByHandleEx(hFile, FileAttributeTagInfo,
1995                     &tagInfo, sizeof(tagInfo))) {
1996                 /* Allow devices that do not support FileAttributeTagInfo. */
1997                 switch (GetLastError()) {
1998                 case ERROR_INVALID_PARAMETER:
1999                 case ERROR_INVALID_FUNCTION:
2000                 case ERROR_NOT_SUPPORTED:
2001                     tagInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
2002                     tagInfo.ReparseTag = 0;
2003                     break;
2004                 default:
2005                     retval = -1;
2006                     goto cleanup;
2007                 }
2008             } else if (tagInfo.FileAttributes &
2009                          FILE_ATTRIBUTE_REPARSE_POINT) {
2010                 if (IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
2011                     if (isUnhandledTag) {
2012                         /* Traversing previously failed for either this link
2013                            or its target. */
2014                         SetLastError(ERROR_CANT_ACCESS_FILE);
2015                         retval = -1;
2016                         goto cleanup;
2017                     }
2018                 /* Traverse a non-link, but not if traversing already failed
2019                    for an unhandled tag. */
2020                 } else if (!isUnhandledTag) {
2021                     CloseHandle(hFile);
2022                     return win32_xstat_impl(path, result, TRUE);
2023                 }
2024             }
2025         }
2026 
2027         if (!GetFileInformationByHandle(hFile, &fileInfo)) {
2028             switch (GetLastError()) {
2029             case ERROR_INVALID_PARAMETER:
2030             case ERROR_INVALID_FUNCTION:
2031             case ERROR_NOT_SUPPORTED:
2032                 /* Volumes and physical disks are block devices, e.g.
2033                    \\.\C: and \\.\PhysicalDrive0. */
2034                 memset(result, 0, sizeof(*result));
2035                 result->st_mode = 0x6000; /* S_IFBLK */
2036                 goto cleanup;
2037             }
2038             retval = -1;
2039             goto cleanup;
2040         }
2041     }
2042 
2043     _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, result);
2044 
2045     if (!(fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
2046         /* Fix the file execute permissions. This hack sets S_IEXEC if
2047            the filename has an extension that is commonly used by files
2048            that CreateProcessW can execute. A real implementation calls
2049            GetSecurityInfo, OpenThreadToken/OpenProcessToken, and
2050            AccessCheck to check for generic read, write, and execute
2051            access. */
2052         const wchar_t *fileExtension = wcsrchr(path, '.');
2053         if (fileExtension) {
2054             if (_wcsicmp(fileExtension, L".exe") == 0 ||
2055                 _wcsicmp(fileExtension, L".bat") == 0 ||
2056                 _wcsicmp(fileExtension, L".cmd") == 0 ||
2057                 _wcsicmp(fileExtension, L".com") == 0) {
2058                 result->st_mode |= 0111;
2059             }
2060         }
2061     }
2062 
2063 cleanup:
2064     if (hFile != INVALID_HANDLE_VALUE) {
2065         /* Preserve last error if we are failing */
2066         error = retval ? GetLastError() : 0;
2067         if (!CloseHandle(hFile)) {
2068             retval = -1;
2069         } else if (retval) {
2070             /* Restore last error */
2071             SetLastError(error);
2072         }
2073     }
2074 
2075     return retval;
2076 }
2077 
2078 static int
win32_xstat(const wchar_t * path,struct _Py_stat_struct * result,BOOL traverse)2079 win32_xstat(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse)
2080 {
2081     /* Protocol violation: we explicitly clear errno, instead of
2082        setting it to a POSIX error. Callers should use GetLastError. */
2083     int code = win32_xstat_impl(path, result, traverse);
2084     errno = 0;
2085     return code;
2086 }
2087 /* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
2088 
2089    In Posix, stat automatically traverses symlinks and returns the stat
2090    structure for the target.  In Windows, the equivalent GetFileAttributes by
2091    default does not traverse symlinks and instead returns attributes for
2092    the symlink.
2093 
2094    Instead, we will open the file (which *does* traverse symlinks by default)
2095    and GetFileInformationByHandle(). */
2096 
2097 static int
win32_lstat(const wchar_t * path,struct _Py_stat_struct * result)2098 win32_lstat(const wchar_t* path, struct _Py_stat_struct *result)
2099 {
2100     return win32_xstat(path, result, FALSE);
2101 }
2102 
2103 static int
win32_stat(const wchar_t * path,struct _Py_stat_struct * result)2104 win32_stat(const wchar_t* path, struct _Py_stat_struct *result)
2105 {
2106     return win32_xstat(path, result, TRUE);
2107 }
2108 
2109 #endif /* MS_WINDOWS */
2110 
2111 PyDoc_STRVAR(stat_result__doc__,
2112 "stat_result: Result from stat, fstat, or lstat.\n\n\
2113 This object may be accessed either as a tuple of\n\
2114   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
2115 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
2116 \n\
2117 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
2118 or st_flags, they are available as attributes only.\n\
2119 \n\
2120 See os.stat for more information.");
2121 
2122 static PyStructSequence_Field stat_result_fields[] = {
2123     {"st_mode",    "protection bits"},
2124     {"st_ino",     "inode"},
2125     {"st_dev",     "device"},
2126     {"st_nlink",   "number of hard links"},
2127     {"st_uid",     "user ID of owner"},
2128     {"st_gid",     "group ID of owner"},
2129     {"st_size",    "total size, in bytes"},
2130     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
2131     {NULL,   "integer time of last access"},
2132     {NULL,   "integer time of last modification"},
2133     {NULL,   "integer time of last change"},
2134     {"st_atime",   "time of last access"},
2135     {"st_mtime",   "time of last modification"},
2136     {"st_ctime",   "time of last change"},
2137     {"st_atime_ns",   "time of last access in nanoseconds"},
2138     {"st_mtime_ns",   "time of last modification in nanoseconds"},
2139     {"st_ctime_ns",   "time of last change in nanoseconds"},
2140 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2141     {"st_blksize", "blocksize for filesystem I/O"},
2142 #endif
2143 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2144     {"st_blocks",  "number of blocks allocated"},
2145 #endif
2146 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2147     {"st_rdev",    "device type (if inode device)"},
2148 #endif
2149 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2150     {"st_flags",   "user defined flags for file"},
2151 #endif
2152 #ifdef HAVE_STRUCT_STAT_ST_GEN
2153     {"st_gen",    "generation number"},
2154 #endif
2155 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2156     {"st_birthtime",   "time of creation"},
2157 #endif
2158 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2159     {"st_file_attributes", "Windows file attribute bits"},
2160 #endif
2161 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2162     {"st_fstype",  "Type of filesystem"},
2163 #endif
2164 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2165     {"st_reparse_tag", "Windows reparse tag"},
2166 #endif
2167     {0}
2168 };
2169 
2170 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2171 #define ST_BLKSIZE_IDX 16
2172 #else
2173 #define ST_BLKSIZE_IDX 15
2174 #endif
2175 
2176 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2177 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
2178 #else
2179 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
2180 #endif
2181 
2182 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2183 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
2184 #else
2185 #define ST_RDEV_IDX ST_BLOCKS_IDX
2186 #endif
2187 
2188 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2189 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
2190 #else
2191 #define ST_FLAGS_IDX ST_RDEV_IDX
2192 #endif
2193 
2194 #ifdef HAVE_STRUCT_STAT_ST_GEN
2195 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
2196 #else
2197 #define ST_GEN_IDX ST_FLAGS_IDX
2198 #endif
2199 
2200 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2201 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
2202 #else
2203 #define ST_BIRTHTIME_IDX ST_GEN_IDX
2204 #endif
2205 
2206 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2207 #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1)
2208 #else
2209 #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX
2210 #endif
2211 
2212 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2213 #define ST_FSTYPE_IDX (ST_FILE_ATTRIBUTES_IDX+1)
2214 #else
2215 #define ST_FSTYPE_IDX ST_FILE_ATTRIBUTES_IDX
2216 #endif
2217 
2218 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2219 #define ST_REPARSE_TAG_IDX (ST_FSTYPE_IDX+1)
2220 #else
2221 #define ST_REPARSE_TAG_IDX ST_FSTYPE_IDX
2222 #endif
2223 
2224 static PyStructSequence_Desc stat_result_desc = {
2225     "stat_result", /* name */
2226     stat_result__doc__, /* doc */
2227     stat_result_fields,
2228     10
2229 };
2230 
2231 PyDoc_STRVAR(statvfs_result__doc__,
2232 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
2233 This object may be accessed either as a tuple of\n\
2234   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
2235 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
2236 \n\
2237 See os.statvfs for more information.");
2238 
2239 static PyStructSequence_Field statvfs_result_fields[] = {
2240     {"f_bsize",  },
2241     {"f_frsize", },
2242     {"f_blocks", },
2243     {"f_bfree",  },
2244     {"f_bavail", },
2245     {"f_files",  },
2246     {"f_ffree",  },
2247     {"f_favail", },
2248     {"f_flag",   },
2249     {"f_namemax",},
2250     {"f_fsid",   },
2251     {0}
2252 };
2253 
2254 static PyStructSequence_Desc statvfs_result_desc = {
2255     "statvfs_result", /* name */
2256     statvfs_result__doc__, /* doc */
2257     statvfs_result_fields,
2258     10
2259 };
2260 
2261 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2262 PyDoc_STRVAR(waitid_result__doc__,
2263 "waitid_result: Result from waitid.\n\n\
2264 This object may be accessed either as a tuple of\n\
2265   (si_pid, si_uid, si_signo, si_status, si_code),\n\
2266 or via the attributes si_pid, si_uid, and so on.\n\
2267 \n\
2268 See os.waitid for more information.");
2269 
2270 static PyStructSequence_Field waitid_result_fields[] = {
2271     {"si_pid",  },
2272     {"si_uid", },
2273     {"si_signo", },
2274     {"si_status",  },
2275     {"si_code", },
2276     {0}
2277 };
2278 
2279 static PyStructSequence_Desc waitid_result_desc = {
2280     "waitid_result", /* name */
2281     waitid_result__doc__, /* doc */
2282     waitid_result_fields,
2283     5
2284 };
2285 #endif
2286 static newfunc structseq_new;
2287 
2288 static PyObject *
statresult_new(PyTypeObject * type,PyObject * args,PyObject * kwds)2289 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2290 {
2291     PyStructSequence *result;
2292     int i;
2293 
2294     result = (PyStructSequence*)structseq_new(type, args, kwds);
2295     if (!result)
2296         return NULL;
2297     /* If we have been initialized from a tuple,
2298        st_?time might be set to None. Initialize it
2299        from the int slots.  */
2300     for (i = 7; i <= 9; i++) {
2301         if (result->ob_item[i+3] == Py_None) {
2302             Py_DECREF(Py_None);
2303             Py_INCREF(result->ob_item[i]);
2304             result->ob_item[i+3] = result->ob_item[i];
2305         }
2306     }
2307     return (PyObject*)result;
2308 }
2309 
2310 static int
_posix_clear(PyObject * module)2311 _posix_clear(PyObject *module)
2312 {
2313     _posixstate *state = get_posix_state(module);
2314     Py_CLEAR(state->billion);
2315     Py_CLEAR(state->DirEntryType);
2316     Py_CLEAR(state->ScandirIteratorType);
2317 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2318     Py_CLEAR(state->SchedParamType);
2319 #endif
2320     Py_CLEAR(state->StatResultType);
2321     Py_CLEAR(state->StatVFSResultType);
2322     Py_CLEAR(state->TerminalSizeType);
2323     Py_CLEAR(state->TimesResultType);
2324     Py_CLEAR(state->UnameResultType);
2325 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2326     Py_CLEAR(state->WaitidResultType);
2327 #endif
2328 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2329     Py_CLEAR(state->struct_rusage);
2330 #endif
2331     Py_CLEAR(state->st_mode);
2332     return 0;
2333 }
2334 
2335 static int
_posix_traverse(PyObject * module,visitproc visit,void * arg)2336 _posix_traverse(PyObject *module, visitproc visit, void *arg)
2337 {
2338     _posixstate *state = get_posix_state(module);
2339     Py_VISIT(state->billion);
2340     Py_VISIT(state->DirEntryType);
2341     Py_VISIT(state->ScandirIteratorType);
2342 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
2343     Py_VISIT(state->SchedParamType);
2344 #endif
2345     Py_VISIT(state->StatResultType);
2346     Py_VISIT(state->StatVFSResultType);
2347     Py_VISIT(state->TerminalSizeType);
2348     Py_VISIT(state->TimesResultType);
2349     Py_VISIT(state->UnameResultType);
2350 #if defined(HAVE_WAITID) && !defined(__APPLE__)
2351     Py_VISIT(state->WaitidResultType);
2352 #endif
2353 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
2354     Py_VISIT(state->struct_rusage);
2355 #endif
2356     Py_VISIT(state->st_mode);
2357     return 0;
2358 }
2359 
2360 static void
_posix_free(void * module)2361 _posix_free(void *module)
2362 {
2363    _posix_clear((PyObject *)module);
2364 }
2365 
2366 static void
fill_time(PyObject * module,PyObject * v,int index,time_t sec,unsigned long nsec)2367 fill_time(PyObject *module, PyObject *v, int index, time_t sec, unsigned long nsec)
2368 {
2369     PyObject *s = _PyLong_FromTime_t(sec);
2370     PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec);
2371     PyObject *s_in_ns = NULL;
2372     PyObject *ns_total = NULL;
2373     PyObject *float_s = NULL;
2374 
2375     if (!(s && ns_fractional))
2376         goto exit;
2377 
2378     s_in_ns = PyNumber_Multiply(s, get_posix_state(module)->billion);
2379     if (!s_in_ns)
2380         goto exit;
2381 
2382     ns_total = PyNumber_Add(s_in_ns, ns_fractional);
2383     if (!ns_total)
2384         goto exit;
2385 
2386     float_s = PyFloat_FromDouble(sec + 1e-9*nsec);
2387     if (!float_s) {
2388         goto exit;
2389     }
2390 
2391     PyStructSequence_SET_ITEM(v, index, s);
2392     PyStructSequence_SET_ITEM(v, index+3, float_s);
2393     PyStructSequence_SET_ITEM(v, index+6, ns_total);
2394     s = NULL;
2395     float_s = NULL;
2396     ns_total = NULL;
2397 exit:
2398     Py_XDECREF(s);
2399     Py_XDECREF(ns_fractional);
2400     Py_XDECREF(s_in_ns);
2401     Py_XDECREF(ns_total);
2402     Py_XDECREF(float_s);
2403 }
2404 
2405 /* pack a system stat C structure into the Python stat tuple
2406    (used by posix_stat() and posix_fstat()) */
2407 static PyObject*
_pystat_fromstructstat(PyObject * module,STRUCT_STAT * st)2408 _pystat_fromstructstat(PyObject *module, STRUCT_STAT *st)
2409 {
2410     unsigned long ansec, mnsec, cnsec;
2411     PyObject *StatResultType = get_posix_state(module)->StatResultType;
2412     PyObject *v = PyStructSequence_New((PyTypeObject *)StatResultType);
2413     if (v == NULL)
2414         return NULL;
2415 
2416     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
2417     static_assert(sizeof(unsigned long long) >= sizeof(st->st_ino),
2418                   "stat.st_ino is larger than unsigned long long");
2419     PyStructSequence_SET_ITEM(v, 1, PyLong_FromUnsignedLongLong(st->st_ino));
2420 #ifdef MS_WINDOWS
2421     PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev));
2422 #else
2423     PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev));
2424 #endif
2425     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
2426 #if defined(MS_WINDOWS)
2427     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0));
2428     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0));
2429 #else
2430     PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid));
2431     PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid));
2432 #endif
2433     static_assert(sizeof(long long) >= sizeof(st->st_size),
2434                   "stat.st_size is larger than long long");
2435     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLongLong(st->st_size));
2436 
2437 #if defined(HAVE_STAT_TV_NSEC)
2438     ansec = st->st_atim.tv_nsec;
2439     mnsec = st->st_mtim.tv_nsec;
2440     cnsec = st->st_ctim.tv_nsec;
2441 #elif defined(HAVE_STAT_TV_NSEC2)
2442     ansec = st->st_atimespec.tv_nsec;
2443     mnsec = st->st_mtimespec.tv_nsec;
2444     cnsec = st->st_ctimespec.tv_nsec;
2445 #elif defined(HAVE_STAT_NSEC)
2446     ansec = st->st_atime_nsec;
2447     mnsec = st->st_mtime_nsec;
2448     cnsec = st->st_ctime_nsec;
2449 #else
2450     ansec = mnsec = cnsec = 0;
2451 #endif
2452     fill_time(module, v, 7, st->st_atime, ansec);
2453     fill_time(module, v, 8, st->st_mtime, mnsec);
2454     fill_time(module, v, 9, st->st_ctime, cnsec);
2455 
2456 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
2457     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
2458                               PyLong_FromLong((long)st->st_blksize));
2459 #endif
2460 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
2461     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
2462                               PyLong_FromLong((long)st->st_blocks));
2463 #endif
2464 #ifdef HAVE_STRUCT_STAT_ST_RDEV
2465     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
2466                               PyLong_FromLong((long)st->st_rdev));
2467 #endif
2468 #ifdef HAVE_STRUCT_STAT_ST_GEN
2469     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
2470                               PyLong_FromLong((long)st->st_gen));
2471 #endif
2472 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
2473     {
2474       PyObject *val;
2475       unsigned long bsec,bnsec;
2476       bsec = (long)st->st_birthtime;
2477 #ifdef HAVE_STAT_TV_NSEC2
2478       bnsec = st->st_birthtimespec.tv_nsec;
2479 #else
2480       bnsec = 0;
2481 #endif
2482       val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
2483       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
2484                                 val);
2485     }
2486 #endif
2487 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
2488     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
2489                               PyLong_FromLong((long)st->st_flags));
2490 #endif
2491 #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES
2492     PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX,
2493                               PyLong_FromUnsignedLong(st->st_file_attributes));
2494 #endif
2495 #ifdef HAVE_STRUCT_STAT_ST_FSTYPE
2496    PyStructSequence_SET_ITEM(v, ST_FSTYPE_IDX,
2497                               PyUnicode_FromString(st->st_fstype));
2498 #endif
2499 #ifdef HAVE_STRUCT_STAT_ST_REPARSE_TAG
2500     PyStructSequence_SET_ITEM(v, ST_REPARSE_TAG_IDX,
2501                               PyLong_FromUnsignedLong(st->st_reparse_tag));
2502 #endif
2503 
2504     if (PyErr_Occurred()) {
2505         Py_DECREF(v);
2506         return NULL;
2507     }
2508 
2509     return v;
2510 }
2511 
2512 /* POSIX methods */
2513 
2514 
2515 static PyObject *
posix_do_stat(PyObject * module,const char * function_name,path_t * path,int dir_fd,int follow_symlinks)2516 posix_do_stat(PyObject *module, const char *function_name, path_t *path,
2517               int dir_fd, int follow_symlinks)
2518 {
2519     STRUCT_STAT st;
2520     int result;
2521 
2522 #ifdef HAVE_FSTATAT
2523     int fstatat_unavailable = 0;
2524 #endif
2525 
2526 #if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT)
2527     if (follow_symlinks_specified(function_name, follow_symlinks))
2528         return NULL;
2529 #endif
2530 
2531     if (path_and_dir_fd_invalid("stat", path, dir_fd) ||
2532         dir_fd_and_fd_invalid("stat", dir_fd, path->fd) ||
2533         fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks))
2534         return NULL;
2535 
2536     Py_BEGIN_ALLOW_THREADS
2537     if (path->fd != -1)
2538         result = FSTAT(path->fd, &st);
2539 #ifdef MS_WINDOWS
2540     else if (follow_symlinks)
2541         result = win32_stat(path->wide, &st);
2542     else
2543         result = win32_lstat(path->wide, &st);
2544 #else
2545     else
2546 #if defined(HAVE_LSTAT)
2547     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
2548         result = LSTAT(path->narrow, &st);
2549     else
2550 #endif /* HAVE_LSTAT */
2551 #ifdef HAVE_FSTATAT
2552     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
2553         if (HAVE_FSTATAT_RUNTIME) {
2554             result = fstatat(dir_fd, path->narrow, &st,
2555                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
2556 
2557         } else {
2558             fstatat_unavailable = 1;
2559         }
2560     } else
2561 #endif /* HAVE_FSTATAT */
2562         result = STAT(path->narrow, &st);
2563 #endif /* MS_WINDOWS */
2564     Py_END_ALLOW_THREADS
2565 
2566 #ifdef HAVE_FSTATAT
2567     if (fstatat_unavailable) {
2568         argument_unavailable_error("stat", "dir_fd");
2569         return NULL;
2570     }
2571 #endif
2572 
2573     if (result != 0) {
2574         return path_error(path);
2575     }
2576 
2577     return _pystat_fromstructstat(module, &st);
2578 }
2579 
2580 /*[python input]
2581 
2582 for s in """
2583 
2584 FACCESSAT
2585 FCHMODAT
2586 FCHOWNAT
2587 FSTATAT
2588 LINKAT
2589 MKDIRAT
2590 MKFIFOAT
2591 MKNODAT
2592 OPENAT
2593 READLINKAT
2594 SYMLINKAT
2595 UNLINKAT
2596 
2597 """.strip().split():
2598     s = s.strip()
2599     print("""
2600 #ifdef HAVE_{s}
2601     #define {s}_DIR_FD_CONVERTER dir_fd_converter
2602 #else
2603     #define {s}_DIR_FD_CONVERTER dir_fd_unavailable
2604 #endif
2605 """.rstrip().format(s=s))
2606 
2607 for s in """
2608 
2609 FCHDIR
2610 FCHMOD
2611 FCHOWN
2612 FDOPENDIR
2613 FEXECVE
2614 FPATHCONF
2615 FSTATVFS
2616 FTRUNCATE
2617 
2618 """.strip().split():
2619     s = s.strip()
2620     print("""
2621 #ifdef HAVE_{s}
2622     #define PATH_HAVE_{s} 1
2623 #else
2624     #define PATH_HAVE_{s} 0
2625 #endif
2626 
2627 """.rstrip().format(s=s))
2628 [python start generated code]*/
2629 
2630 #ifdef HAVE_FACCESSAT
2631     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter
2632 #else
2633     #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable
2634 #endif
2635 
2636 #ifdef HAVE_FCHMODAT
2637     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter
2638 #else
2639     #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable
2640 #endif
2641 
2642 #ifdef HAVE_FCHOWNAT
2643     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter
2644 #else
2645     #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable
2646 #endif
2647 
2648 #ifdef HAVE_FSTATAT
2649     #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter
2650 #else
2651     #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable
2652 #endif
2653 
2654 #ifdef HAVE_LINKAT
2655     #define LINKAT_DIR_FD_CONVERTER dir_fd_converter
2656 #else
2657     #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2658 #endif
2659 
2660 #ifdef HAVE_MKDIRAT
2661     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter
2662 #else
2663     #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable
2664 #endif
2665 
2666 #ifdef HAVE_MKFIFOAT
2667     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter
2668 #else
2669     #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable
2670 #endif
2671 
2672 #ifdef HAVE_MKNODAT
2673     #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter
2674 #else
2675     #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable
2676 #endif
2677 
2678 #ifdef HAVE_OPENAT
2679     #define OPENAT_DIR_FD_CONVERTER dir_fd_converter
2680 #else
2681     #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable
2682 #endif
2683 
2684 #ifdef HAVE_READLINKAT
2685     #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter
2686 #else
2687     #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2688 #endif
2689 
2690 #ifdef HAVE_SYMLINKAT
2691     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter
2692 #else
2693     #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2694 #endif
2695 
2696 #ifdef HAVE_UNLINKAT
2697     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter
2698 #else
2699     #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable
2700 #endif
2701 
2702 #ifdef HAVE_FCHDIR
2703     #define PATH_HAVE_FCHDIR 1
2704 #else
2705     #define PATH_HAVE_FCHDIR 0
2706 #endif
2707 
2708 #ifdef HAVE_FCHMOD
2709     #define PATH_HAVE_FCHMOD 1
2710 #else
2711     #define PATH_HAVE_FCHMOD 0
2712 #endif
2713 
2714 #ifdef HAVE_FCHOWN
2715     #define PATH_HAVE_FCHOWN 1
2716 #else
2717     #define PATH_HAVE_FCHOWN 0
2718 #endif
2719 
2720 #ifdef HAVE_FDOPENDIR
2721     #define PATH_HAVE_FDOPENDIR 1
2722 #else
2723     #define PATH_HAVE_FDOPENDIR 0
2724 #endif
2725 
2726 #ifdef HAVE_FEXECVE
2727     #define PATH_HAVE_FEXECVE 1
2728 #else
2729     #define PATH_HAVE_FEXECVE 0
2730 #endif
2731 
2732 #ifdef HAVE_FPATHCONF
2733     #define PATH_HAVE_FPATHCONF 1
2734 #else
2735     #define PATH_HAVE_FPATHCONF 0
2736 #endif
2737 
2738 #ifdef HAVE_FSTATVFS
2739     #define PATH_HAVE_FSTATVFS 1
2740 #else
2741     #define PATH_HAVE_FSTATVFS 0
2742 #endif
2743 
2744 #ifdef HAVE_FTRUNCATE
2745     #define PATH_HAVE_FTRUNCATE 1
2746 #else
2747     #define PATH_HAVE_FTRUNCATE 0
2748 #endif
2749 /*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/
2750 
2751 #ifdef MS_WINDOWS
2752     #undef PATH_HAVE_FTRUNCATE
2753     #define PATH_HAVE_FTRUNCATE 1
2754 #endif
2755 
2756 /*[python input]
2757 
2758 class path_t_converter(CConverter):
2759 
2760     type = "path_t"
2761     impl_by_reference = True
2762     parse_by_reference = True
2763 
2764     converter = 'path_converter'
2765 
2766     def converter_init(self, *, allow_fd=False, nullable=False):
2767         # right now path_t doesn't support default values.
2768         # to support a default value, you'll need to override initialize().
2769         if self.default not in (unspecified, None):
2770             fail("Can't specify a default to the path_t converter!")
2771 
2772         if self.c_default not in (None, 'Py_None'):
2773             raise RuntimeError("Can't specify a c_default to the path_t converter!")
2774 
2775         self.nullable = nullable
2776         self.allow_fd = allow_fd
2777 
2778     def pre_render(self):
2779         def strify(value):
2780             if isinstance(value, str):
2781                 return value
2782             return str(int(bool(value)))
2783 
2784         # add self.py_name here when merging with posixmodule conversion
2785         self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format(
2786             self.function.name,
2787             self.name,
2788             strify(self.nullable),
2789             strify(self.allow_fd),
2790             )
2791 
2792     def cleanup(self):
2793         return "path_cleanup(&" + self.name + ");\n"
2794 
2795 
2796 class dir_fd_converter(CConverter):
2797     type = 'int'
2798 
2799     def converter_init(self, requires=None):
2800         if self.default in (unspecified, None):
2801             self.c_default = 'DEFAULT_DIR_FD'
2802         if isinstance(requires, str):
2803             self.converter = requires.upper() + '_DIR_FD_CONVERTER'
2804         else:
2805             self.converter = 'dir_fd_converter'
2806 
2807 class uid_t_converter(CConverter):
2808     type = "uid_t"
2809     converter = '_Py_Uid_Converter'
2810 
2811 class gid_t_converter(CConverter):
2812     type = "gid_t"
2813     converter = '_Py_Gid_Converter'
2814 
2815 class dev_t_converter(CConverter):
2816     type = 'dev_t'
2817     converter = '_Py_Dev_Converter'
2818 
2819 class dev_t_return_converter(unsigned_long_return_converter):
2820     type = 'dev_t'
2821     conversion_fn = '_PyLong_FromDev'
2822     unsigned_cast = '(dev_t)'
2823 
2824 class FSConverter_converter(CConverter):
2825     type = 'PyObject *'
2826     converter = 'PyUnicode_FSConverter'
2827     def converter_init(self):
2828         if self.default is not unspecified:
2829             fail("FSConverter_converter does not support default values")
2830         self.c_default = 'NULL'
2831 
2832     def cleanup(self):
2833         return "Py_XDECREF(" + self.name + ");\n"
2834 
2835 class pid_t_converter(CConverter):
2836     type = 'pid_t'
2837     format_unit = '" _Py_PARSE_PID "'
2838 
2839 class idtype_t_converter(int_converter):
2840     type = 'idtype_t'
2841 
2842 class id_t_converter(CConverter):
2843     type = 'id_t'
2844     format_unit = '" _Py_PARSE_PID "'
2845 
2846 class intptr_t_converter(CConverter):
2847     type = 'intptr_t'
2848     format_unit = '" _Py_PARSE_INTPTR "'
2849 
2850 class Py_off_t_converter(CConverter):
2851     type = 'Py_off_t'
2852     converter = 'Py_off_t_converter'
2853 
2854 class Py_off_t_return_converter(long_return_converter):
2855     type = 'Py_off_t'
2856     conversion_fn = 'PyLong_FromPy_off_t'
2857 
2858 class path_confname_converter(CConverter):
2859     type="int"
2860     converter="conv_path_confname"
2861 
2862 class confstr_confname_converter(path_confname_converter):
2863     converter='conv_confstr_confname'
2864 
2865 class sysconf_confname_converter(path_confname_converter):
2866     converter="conv_sysconf_confname"
2867 
2868 [python start generated code]*/
2869 /*[python end generated code: output=da39a3ee5e6b4b0d input=3338733161aa7879]*/
2870 
2871 /*[clinic input]
2872 
2873 os.stat
2874 
2875     path : path_t(allow_fd=True)
2876         Path to be examined; can be string, bytes, a path-like object or
2877         open-file-descriptor int.
2878 
2879     *
2880 
2881     dir_fd : dir_fd(requires='fstatat') = None
2882         If not None, it should be a file descriptor open to a directory,
2883         and path should be a relative string; path will then be relative to
2884         that directory.
2885 
2886     follow_symlinks: bool = True
2887         If False, and the last element of the path is a symbolic link,
2888         stat will examine the symbolic link itself instead of the file
2889         the link points to.
2890 
2891 Perform a stat system call on the given path.
2892 
2893 dir_fd and follow_symlinks may not be implemented
2894   on your platform.  If they are unavailable, using them will raise a
2895   NotImplementedError.
2896 
2897 It's an error to use dir_fd or follow_symlinks when specifying path as
2898   an open file descriptor.
2899 
2900 [clinic start generated code]*/
2901 
2902 static PyObject *
os_stat_impl(PyObject * module,path_t * path,int dir_fd,int follow_symlinks)2903 os_stat_impl(PyObject *module, path_t *path, int dir_fd, int follow_symlinks)
2904 /*[clinic end generated code: output=7d4976e6f18a59c5 input=01d362ebcc06996b]*/
2905 {
2906     return posix_do_stat(module, "stat", path, dir_fd, follow_symlinks);
2907 }
2908 
2909 
2910 /*[clinic input]
2911 os.lstat
2912 
2913     path : path_t
2914 
2915     *
2916 
2917     dir_fd : dir_fd(requires='fstatat') = None
2918 
2919 Perform a stat system call on the given path, without following symbolic links.
2920 
2921 Like stat(), but do not follow symbolic links.
2922 Equivalent to stat(path, follow_symlinks=False).
2923 [clinic start generated code]*/
2924 
2925 static PyObject *
os_lstat_impl(PyObject * module,path_t * path,int dir_fd)2926 os_lstat_impl(PyObject *module, path_t *path, int dir_fd)
2927 /*[clinic end generated code: output=ef82a5d35ce8ab37 input=0b7474765927b925]*/
2928 {
2929     int follow_symlinks = 0;
2930     return posix_do_stat(module, "lstat", path, dir_fd, follow_symlinks);
2931 }
2932 
2933 
2934 /*[clinic input]
2935 os.access -> bool
2936 
2937     path: path_t
2938         Path to be tested; can be string, bytes, or a path-like object.
2939 
2940     mode: int
2941         Operating-system mode bitfield.  Can be F_OK to test existence,
2942         or the inclusive-OR of R_OK, W_OK, and X_OK.
2943 
2944     *
2945 
2946     dir_fd : dir_fd(requires='faccessat') = None
2947         If not None, it should be a file descriptor open to a directory,
2948         and path should be relative; path will then be relative to that
2949         directory.
2950 
2951     effective_ids: bool = False
2952         If True, access will use the effective uid/gid instead of
2953         the real uid/gid.
2954 
2955     follow_symlinks: bool = True
2956         If False, and the last element of the path is a symbolic link,
2957         access will examine the symbolic link itself instead of the file
2958         the link points to.
2959 
2960 Use the real uid/gid to test for access to a path.
2961 
2962 {parameters}
2963 dir_fd, effective_ids, and follow_symlinks may not be implemented
2964   on your platform.  If they are unavailable, using them will raise a
2965   NotImplementedError.
2966 
2967 Note that most operations will use the effective uid/gid, therefore this
2968   routine can be used in a suid/sgid environment to test if the invoking user
2969   has the specified access to the path.
2970 
2971 [clinic start generated code]*/
2972 
2973 static int
os_access_impl(PyObject * module,path_t * path,int mode,int dir_fd,int effective_ids,int follow_symlinks)2974 os_access_impl(PyObject *module, path_t *path, int mode, int dir_fd,
2975                int effective_ids, int follow_symlinks)
2976 /*[clinic end generated code: output=cf84158bc90b1a77 input=3ffe4e650ee3bf20]*/
2977 {
2978     int return_value;
2979 
2980 #ifdef MS_WINDOWS
2981     DWORD attr;
2982 #else
2983     int result;
2984 #endif
2985 
2986 #ifdef HAVE_FACCESSAT
2987     int faccessat_unavailable = 0;
2988 #endif
2989 
2990 #ifndef HAVE_FACCESSAT
2991     if (follow_symlinks_specified("access", follow_symlinks))
2992         return -1;
2993 
2994     if (effective_ids) {
2995         argument_unavailable_error("access", "effective_ids");
2996         return -1;
2997     }
2998 #endif
2999 
3000 #ifdef MS_WINDOWS
3001     Py_BEGIN_ALLOW_THREADS
3002     attr = GetFileAttributesW(path->wide);
3003     Py_END_ALLOW_THREADS
3004 
3005     /*
3006      * Access is possible if
3007      *   * we didn't get a -1, and
3008      *     * write access wasn't requested,
3009      *     * or the file isn't read-only,
3010      *     * or it's a directory.
3011      * (Directories cannot be read-only on Windows.)
3012     */
3013     return_value = (attr != INVALID_FILE_ATTRIBUTES) &&
3014             (!(mode & 2) ||
3015             !(attr & FILE_ATTRIBUTE_READONLY) ||
3016             (attr & FILE_ATTRIBUTE_DIRECTORY));
3017 #else
3018 
3019     Py_BEGIN_ALLOW_THREADS
3020 #ifdef HAVE_FACCESSAT
3021     if ((dir_fd != DEFAULT_DIR_FD) ||
3022         effective_ids ||
3023         !follow_symlinks) {
3024 
3025         if (HAVE_FACCESSAT_RUNTIME) {
3026             int flags = 0;
3027             if (!follow_symlinks)
3028                 flags |= AT_SYMLINK_NOFOLLOW;
3029             if (effective_ids)
3030                 flags |= AT_EACCESS;
3031             result = faccessat(dir_fd, path->narrow, mode, flags);
3032         } else {
3033             faccessat_unavailable = 1;
3034         }
3035     }
3036     else
3037 #endif
3038         result = access(path->narrow, mode);
3039     Py_END_ALLOW_THREADS
3040 
3041 #ifdef HAVE_FACCESSAT
3042     if (faccessat_unavailable) {
3043         if (dir_fd != DEFAULT_DIR_FD) {
3044             argument_unavailable_error("access", "dir_fd");
3045             return -1;
3046         }
3047         if (follow_symlinks_specified("access", follow_symlinks))
3048             return -1;
3049 
3050         if (effective_ids) {
3051             argument_unavailable_error("access", "effective_ids");
3052             return -1;
3053         }
3054         /* should be unreachable */
3055         return -1;
3056     }
3057 #endif
3058     return_value = !result;
3059 #endif
3060 
3061     return return_value;
3062 }
3063 
3064 #ifndef F_OK
3065 #define F_OK 0
3066 #endif
3067 #ifndef R_OK
3068 #define R_OK 4
3069 #endif
3070 #ifndef W_OK
3071 #define W_OK 2
3072 #endif
3073 #ifndef X_OK
3074 #define X_OK 1
3075 #endif
3076 
3077 
3078 #ifdef HAVE_TTYNAME
3079 /*[clinic input]
3080 os.ttyname
3081 
3082     fd: int
3083         Integer file descriptor handle.
3084 
3085     /
3086 
3087 Return the name of the terminal device connected to 'fd'.
3088 [clinic start generated code]*/
3089 
3090 static PyObject *
os_ttyname_impl(PyObject * module,int fd)3091 os_ttyname_impl(PyObject *module, int fd)
3092 /*[clinic end generated code: output=c424d2e9d1cd636a input=9ff5a58b08115c55]*/
3093 {
3094 
3095     long size = sysconf(_SC_TTY_NAME_MAX);
3096     if (size == -1) {
3097         return posix_error();
3098     }
3099     char *buffer = (char *)PyMem_RawMalloc(size);
3100     if (buffer == NULL) {
3101         return PyErr_NoMemory();
3102     }
3103     int ret = ttyname_r(fd, buffer, size);
3104     if (ret != 0) {
3105         PyMem_RawFree(buffer);
3106         errno = ret;
3107         return posix_error();
3108     }
3109     PyObject *res = PyUnicode_DecodeFSDefault(buffer);
3110     PyMem_RawFree(buffer);
3111     return res;
3112 }
3113 #endif
3114 
3115 #ifdef HAVE_CTERMID
3116 /*[clinic input]
3117 os.ctermid
3118 
3119 Return the name of the controlling terminal for this process.
3120 [clinic start generated code]*/
3121 
3122 static PyObject *
os_ctermid_impl(PyObject * module)3123 os_ctermid_impl(PyObject *module)
3124 /*[clinic end generated code: output=02f017e6c9e620db input=3b87fdd52556382d]*/
3125 {
3126     char *ret;
3127     char buffer[L_ctermid];
3128 
3129 #ifdef USE_CTERMID_R
3130     ret = ctermid_r(buffer);
3131 #else
3132     ret = ctermid(buffer);
3133 #endif
3134     if (ret == NULL)
3135         return posix_error();
3136     return PyUnicode_DecodeFSDefault(buffer);
3137 }
3138 #endif /* HAVE_CTERMID */
3139 
3140 
3141 /*[clinic input]
3142 os.chdir
3143 
3144     path: path_t(allow_fd='PATH_HAVE_FCHDIR')
3145 
3146 Change the current working directory to the specified path.
3147 
3148 path may always be specified as a string.
3149 On some platforms, path may also be specified as an open file descriptor.
3150   If this functionality is unavailable, using it raises an exception.
3151 [clinic start generated code]*/
3152 
3153 static PyObject *
os_chdir_impl(PyObject * module,path_t * path)3154 os_chdir_impl(PyObject *module, path_t *path)
3155 /*[clinic end generated code: output=3be6400eee26eaae input=1a4a15b4d12cb15d]*/
3156 {
3157     int result;
3158 
3159     if (PySys_Audit("os.chdir", "(O)", path->object) < 0) {
3160         return NULL;
3161     }
3162 
3163     Py_BEGIN_ALLOW_THREADS
3164 #ifdef MS_WINDOWS
3165     /* on unix, success = 0, on windows, success = !0 */
3166     result = !win32_wchdir(path->wide);
3167 #else
3168 #ifdef HAVE_FCHDIR
3169     if (path->fd != -1)
3170         result = fchdir(path->fd);
3171     else
3172 #endif
3173         result = chdir(path->narrow);
3174 #endif
3175     Py_END_ALLOW_THREADS
3176 
3177     if (result) {
3178         return path_error(path);
3179     }
3180 
3181     Py_RETURN_NONE;
3182 }
3183 
3184 
3185 #ifdef HAVE_FCHDIR
3186 /*[clinic input]
3187 os.fchdir
3188 
3189     fd: fildes
3190 
3191 Change to the directory of the given file descriptor.
3192 
3193 fd must be opened on a directory, not a file.
3194 Equivalent to os.chdir(fd).
3195 
3196 [clinic start generated code]*/
3197 
3198 static PyObject *
os_fchdir_impl(PyObject * module,int fd)3199 os_fchdir_impl(PyObject *module, int fd)
3200 /*[clinic end generated code: output=42e064ec4dc00ab0 input=18e816479a2fa985]*/
3201 {
3202     if (PySys_Audit("os.chdir", "(i)", fd) < 0) {
3203         return NULL;
3204     }
3205     return posix_fildes_fd(fd, fchdir);
3206 }
3207 #endif /* HAVE_FCHDIR */
3208 
3209 
3210 /*[clinic input]
3211 os.chmod
3212 
3213     path: path_t(allow_fd='PATH_HAVE_FCHMOD')
3214         Path to be modified.  May always be specified as a str, bytes, or a path-like object.
3215         On some platforms, path may also be specified as an open file descriptor.
3216         If this functionality is unavailable, using it raises an exception.
3217 
3218     mode: int
3219         Operating-system mode bitfield.
3220 
3221     *
3222 
3223     dir_fd : dir_fd(requires='fchmodat') = None
3224         If not None, it should be a file descriptor open to a directory,
3225         and path should be relative; path will then be relative to that
3226         directory.
3227 
3228     follow_symlinks: bool = True
3229         If False, and the last element of the path is a symbolic link,
3230         chmod will modify the symbolic link itself instead of the file
3231         the link points to.
3232 
3233 Change the access permissions of a file.
3234 
3235 It is an error to use dir_fd or follow_symlinks when specifying path as
3236   an open file descriptor.
3237 dir_fd and follow_symlinks may not be implemented on your platform.
3238   If they are unavailable, using them will raise a NotImplementedError.
3239 
3240 [clinic start generated code]*/
3241 
3242 static PyObject *
os_chmod_impl(PyObject * module,path_t * path,int mode,int dir_fd,int follow_symlinks)3243 os_chmod_impl(PyObject *module, path_t *path, int mode, int dir_fd,
3244               int follow_symlinks)
3245 /*[clinic end generated code: output=5cf6a94915cc7bff input=989081551c00293b]*/
3246 {
3247     int result;
3248 
3249 #ifdef MS_WINDOWS
3250     DWORD attr;
3251 #endif
3252 
3253 #ifdef HAVE_FCHMODAT
3254     int fchmodat_nofollow_unsupported = 0;
3255     int fchmodat_unsupported = 0;
3256 #endif
3257 
3258 #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD))
3259     if (follow_symlinks_specified("chmod", follow_symlinks))
3260         return NULL;
3261 #endif
3262 
3263     if (PySys_Audit("os.chmod", "Oii", path->object, mode,
3264                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3265         return NULL;
3266     }
3267 
3268 #ifdef MS_WINDOWS
3269     Py_BEGIN_ALLOW_THREADS
3270     attr = GetFileAttributesW(path->wide);
3271     if (attr == INVALID_FILE_ATTRIBUTES)
3272         result = 0;
3273     else {
3274         if (mode & _S_IWRITE)
3275             attr &= ~FILE_ATTRIBUTE_READONLY;
3276         else
3277             attr |= FILE_ATTRIBUTE_READONLY;
3278         result = SetFileAttributesW(path->wide, attr);
3279     }
3280     Py_END_ALLOW_THREADS
3281 
3282     if (!result) {
3283         return path_error(path);
3284     }
3285 #else /* MS_WINDOWS */
3286     Py_BEGIN_ALLOW_THREADS
3287 #ifdef HAVE_FCHMOD
3288     if (path->fd != -1)
3289         result = fchmod(path->fd, mode);
3290     else
3291 #endif /* HAVE_CHMOD */
3292 #ifdef HAVE_LCHMOD
3293     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3294         result = lchmod(path->narrow, mode);
3295     else
3296 #endif /* HAVE_LCHMOD */
3297 #ifdef HAVE_FCHMODAT
3298     if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) {
3299         if (HAVE_FCHMODAT_RUNTIME) {
3300             /*
3301              * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW!
3302              * The documentation specifically shows how to use it,
3303              * and then says it isn't implemented yet.
3304              * (true on linux with glibc 2.15, and openindiana 3.x)
3305              *
3306              * Once it is supported, os.chmod will automatically
3307              * support dir_fd and follow_symlinks=False.  (Hopefully.)
3308              * Until then, we need to be careful what exception we raise.
3309              */
3310             result = fchmodat(dir_fd, path->narrow, mode,
3311                               follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3312             /*
3313              * But wait!  We can't throw the exception without allowing threads,
3314              * and we can't do that in this nested scope.  (Macro trickery, sigh.)
3315              */
3316             fchmodat_nofollow_unsupported =
3317                              result &&
3318                              ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) &&
3319                              !follow_symlinks;
3320         } else {
3321             fchmodat_unsupported = 1;
3322             fchmodat_nofollow_unsupported = 1;
3323 
3324             result = -1;
3325         }
3326     }
3327     else
3328 #endif /* HAVE_FHCMODAT */
3329     {
3330 #ifdef HAVE_CHMOD
3331         result = chmod(path->narrow, mode);
3332 #elif defined(__wasi__)
3333         // WASI SDK 15.0 does not support chmod.
3334         // Ignore missing syscall for now.
3335         result = 0;
3336 #else
3337         result = -1;
3338         errno = ENOSYS;
3339 #endif
3340     }
3341     Py_END_ALLOW_THREADS
3342 
3343     if (result) {
3344 #ifdef HAVE_FCHMODAT
3345         if (fchmodat_unsupported) {
3346             if (dir_fd != DEFAULT_DIR_FD) {
3347                 argument_unavailable_error("chmod", "dir_fd");
3348                 return NULL;
3349             }
3350         }
3351 
3352         if (fchmodat_nofollow_unsupported) {
3353             if (dir_fd != DEFAULT_DIR_FD)
3354                 dir_fd_and_follow_symlinks_invalid("chmod",
3355                                                    dir_fd, follow_symlinks);
3356             else
3357                 follow_symlinks_specified("chmod", follow_symlinks);
3358             return NULL;
3359         }
3360         else
3361 #endif /* HAVE_FCHMODAT */
3362         return path_error(path);
3363     }
3364 #endif /* MS_WINDOWS */
3365 
3366     Py_RETURN_NONE;
3367 }
3368 
3369 
3370 #ifdef HAVE_FCHMOD
3371 /*[clinic input]
3372 os.fchmod
3373 
3374     fd: int
3375     mode: int
3376 
3377 Change the access permissions of the file given by file descriptor fd.
3378 
3379 Equivalent to os.chmod(fd, mode).
3380 [clinic start generated code]*/
3381 
3382 static PyObject *
os_fchmod_impl(PyObject * module,int fd,int mode)3383 os_fchmod_impl(PyObject *module, int fd, int mode)
3384 /*[clinic end generated code: output=afd9bc05b4e426b3 input=8ab11975ca01ee5b]*/
3385 {
3386     int res;
3387     int async_err = 0;
3388 
3389     if (PySys_Audit("os.chmod", "iii", fd, mode, -1) < 0) {
3390         return NULL;
3391     }
3392 
3393     do {
3394         Py_BEGIN_ALLOW_THREADS
3395         res = fchmod(fd, mode);
3396         Py_END_ALLOW_THREADS
3397     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3398     if (res != 0)
3399         return (!async_err) ? posix_error() : NULL;
3400 
3401     Py_RETURN_NONE;
3402 }
3403 #endif /* HAVE_FCHMOD */
3404 
3405 
3406 #ifdef HAVE_LCHMOD
3407 /*[clinic input]
3408 os.lchmod
3409 
3410     path: path_t
3411     mode: int
3412 
3413 Change the access permissions of a file, without following symbolic links.
3414 
3415 If path is a symlink, this affects the link itself rather than the target.
3416 Equivalent to chmod(path, mode, follow_symlinks=False)."
3417 [clinic start generated code]*/
3418 
3419 static PyObject *
os_lchmod_impl(PyObject * module,path_t * path,int mode)3420 os_lchmod_impl(PyObject *module, path_t *path, int mode)
3421 /*[clinic end generated code: output=082344022b51a1d5 input=90c5663c7465d24f]*/
3422 {
3423     int res;
3424     if (PySys_Audit("os.chmod", "Oii", path->object, mode, -1) < 0) {
3425         return NULL;
3426     }
3427     Py_BEGIN_ALLOW_THREADS
3428     res = lchmod(path->narrow, mode);
3429     Py_END_ALLOW_THREADS
3430     if (res < 0) {
3431         path_error(path);
3432         return NULL;
3433     }
3434     Py_RETURN_NONE;
3435 }
3436 #endif /* HAVE_LCHMOD */
3437 
3438 
3439 #ifdef HAVE_CHFLAGS
3440 /*[clinic input]
3441 os.chflags
3442 
3443     path: path_t
3444     flags: unsigned_long(bitwise=True)
3445     follow_symlinks: bool=True
3446 
3447 Set file flags.
3448 
3449 If follow_symlinks is False, and the last element of the path is a symbolic
3450   link, chflags will change flags on the symbolic link itself instead of the
3451   file the link points to.
3452 follow_symlinks may not be implemented on your platform.  If it is
3453 unavailable, using it will raise a NotImplementedError.
3454 
3455 [clinic start generated code]*/
3456 
3457 static PyObject *
os_chflags_impl(PyObject * module,path_t * path,unsigned long flags,int follow_symlinks)3458 os_chflags_impl(PyObject *module, path_t *path, unsigned long flags,
3459                 int follow_symlinks)
3460 /*[clinic end generated code: output=85571c6737661ce9 input=0327e29feb876236]*/
3461 {
3462     int result;
3463 
3464 #ifndef HAVE_LCHFLAGS
3465     if (follow_symlinks_specified("chflags", follow_symlinks))
3466         return NULL;
3467 #endif
3468 
3469     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3470         return NULL;
3471     }
3472 
3473     Py_BEGIN_ALLOW_THREADS
3474 #ifdef HAVE_LCHFLAGS
3475     if (!follow_symlinks)
3476         result = lchflags(path->narrow, flags);
3477     else
3478 #endif
3479         result = chflags(path->narrow, flags);
3480     Py_END_ALLOW_THREADS
3481 
3482     if (result)
3483         return path_error(path);
3484 
3485     Py_RETURN_NONE;
3486 }
3487 #endif /* HAVE_CHFLAGS */
3488 
3489 
3490 #ifdef HAVE_LCHFLAGS
3491 /*[clinic input]
3492 os.lchflags
3493 
3494     path: path_t
3495     flags: unsigned_long(bitwise=True)
3496 
3497 Set file flags.
3498 
3499 This function will not follow symbolic links.
3500 Equivalent to chflags(path, flags, follow_symlinks=False).
3501 [clinic start generated code]*/
3502 
3503 static PyObject *
os_lchflags_impl(PyObject * module,path_t * path,unsigned long flags)3504 os_lchflags_impl(PyObject *module, path_t *path, unsigned long flags)
3505 /*[clinic end generated code: output=30ae958695c07316 input=f9f82ea8b585ca9d]*/
3506 {
3507     int res;
3508     if (PySys_Audit("os.chflags", "Ok", path->object, flags) < 0) {
3509         return NULL;
3510     }
3511     Py_BEGIN_ALLOW_THREADS
3512     res = lchflags(path->narrow, flags);
3513     Py_END_ALLOW_THREADS
3514     if (res < 0) {
3515         return path_error(path);
3516     }
3517     Py_RETURN_NONE;
3518 }
3519 #endif /* HAVE_LCHFLAGS */
3520 
3521 
3522 #ifdef HAVE_CHROOT
3523 /*[clinic input]
3524 os.chroot
3525     path: path_t
3526 
3527 Change root directory to path.
3528 
3529 [clinic start generated code]*/
3530 
3531 static PyObject *
os_chroot_impl(PyObject * module,path_t * path)3532 os_chroot_impl(PyObject *module, path_t *path)
3533 /*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
3534 {
3535     int res;
3536     Py_BEGIN_ALLOW_THREADS
3537     res = chroot(path->narrow);
3538     Py_END_ALLOW_THREADS
3539     if (res < 0)
3540         return path_error(path);
3541     Py_RETURN_NONE;
3542 }
3543 #endif /* HAVE_CHROOT */
3544 
3545 
3546 #ifdef HAVE_FSYNC
3547 /*[clinic input]
3548 os.fsync
3549 
3550     fd: fildes
3551 
3552 Force write of fd to disk.
3553 [clinic start generated code]*/
3554 
3555 static PyObject *
os_fsync_impl(PyObject * module,int fd)3556 os_fsync_impl(PyObject *module, int fd)
3557 /*[clinic end generated code: output=4a10d773f52b3584 input=21c3645c056967f2]*/
3558 {
3559     return posix_fildes_fd(fd, fsync);
3560 }
3561 #endif /* HAVE_FSYNC */
3562 
3563 
3564 #ifdef HAVE_SYNC
3565 /*[clinic input]
3566 os.sync
3567 
3568 Force write of everything to disk.
3569 [clinic start generated code]*/
3570 
3571 static PyObject *
os_sync_impl(PyObject * module)3572 os_sync_impl(PyObject *module)
3573 /*[clinic end generated code: output=2796b1f0818cd71c input=84749fe5e9b404ff]*/
3574 {
3575     Py_BEGIN_ALLOW_THREADS
3576     sync();
3577     Py_END_ALLOW_THREADS
3578     Py_RETURN_NONE;
3579 }
3580 #endif /* HAVE_SYNC */
3581 
3582 
3583 #ifdef HAVE_FDATASYNC
3584 #ifdef __hpux
3585 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
3586 #endif
3587 
3588 /*[clinic input]
3589 os.fdatasync
3590 
3591     fd: fildes
3592 
3593 Force write of fd to disk without forcing update of metadata.
3594 [clinic start generated code]*/
3595 
3596 static PyObject *
os_fdatasync_impl(PyObject * module,int fd)3597 os_fdatasync_impl(PyObject *module, int fd)
3598 /*[clinic end generated code: output=b4b9698b5d7e26dd input=bc74791ee54dd291]*/
3599 {
3600     return posix_fildes_fd(fd, fdatasync);
3601 }
3602 #endif /* HAVE_FDATASYNC */
3603 
3604 
3605 #ifdef HAVE_CHOWN
3606 /*[clinic input]
3607 os.chown
3608 
3609     path : path_t(allow_fd='PATH_HAVE_FCHOWN')
3610         Path to be examined; can be string, bytes, a path-like object, or open-file-descriptor int.
3611 
3612     uid: uid_t
3613 
3614     gid: gid_t
3615 
3616     *
3617 
3618     dir_fd : dir_fd(requires='fchownat') = None
3619         If not None, it should be a file descriptor open to a directory,
3620         and path should be relative; path will then be relative to that
3621         directory.
3622 
3623     follow_symlinks: bool = True
3624         If False, and the last element of the path is a symbolic link,
3625         stat will examine the symbolic link itself instead of the file
3626         the link points to.
3627 
3628 Change the owner and group id of path to the numeric uid and gid.\
3629 
3630 path may always be specified as a string.
3631 On some platforms, path may also be specified as an open file descriptor.
3632   If this functionality is unavailable, using it raises an exception.
3633 If dir_fd is not None, it should be a file descriptor open to a directory,
3634   and path should be relative; path will then be relative to that directory.
3635 If follow_symlinks is False, and the last element of the path is a symbolic
3636   link, chown will modify the symbolic link itself instead of the file the
3637   link points to.
3638 It is an error to use dir_fd or follow_symlinks when specifying path as
3639   an open file descriptor.
3640 dir_fd and follow_symlinks may not be implemented on your platform.
3641   If they are unavailable, using them will raise a NotImplementedError.
3642 
3643 [clinic start generated code]*/
3644 
3645 static PyObject *
os_chown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid,int dir_fd,int follow_symlinks)3646 os_chown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid,
3647               int dir_fd, int follow_symlinks)
3648 /*[clinic end generated code: output=4beadab0db5f70cd input=b08c5ec67996a97d]*/
3649 {
3650     int result;
3651 
3652 #if defined(HAVE_FCHOWNAT)
3653     int fchownat_unsupported = 0;
3654 #endif
3655 
3656 #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT))
3657     if (follow_symlinks_specified("chown", follow_symlinks))
3658         return NULL;
3659 #endif
3660     if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) ||
3661         fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks))
3662         return NULL;
3663 
3664     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid,
3665                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
3666         return NULL;
3667     }
3668 
3669     Py_BEGIN_ALLOW_THREADS
3670 #ifdef HAVE_FCHOWN
3671     if (path->fd != -1)
3672         result = fchown(path->fd, uid, gid);
3673     else
3674 #endif
3675 #ifdef HAVE_LCHOWN
3676     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
3677         result = lchown(path->narrow, uid, gid);
3678     else
3679 #endif
3680 #ifdef HAVE_FCHOWNAT
3681     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
3682       if (HAVE_FCHOWNAT_RUNTIME) {
3683         result = fchownat(dir_fd, path->narrow, uid, gid,
3684                           follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
3685       } else {
3686          fchownat_unsupported = 1;
3687       }
3688     } else
3689 #endif
3690         result = chown(path->narrow, uid, gid);
3691     Py_END_ALLOW_THREADS
3692 
3693 #ifdef HAVE_FCHOWNAT
3694     if (fchownat_unsupported) {
3695         /* This would be incorrect if the current platform
3696          * doesn't support lchown.
3697          */
3698         argument_unavailable_error(NULL, "dir_fd");
3699         return NULL;
3700     }
3701 #endif
3702 
3703     if (result)
3704         return path_error(path);
3705 
3706     Py_RETURN_NONE;
3707 }
3708 #endif /* HAVE_CHOWN */
3709 
3710 
3711 #ifdef HAVE_FCHOWN
3712 /*[clinic input]
3713 os.fchown
3714 
3715     fd: int
3716     uid: uid_t
3717     gid: gid_t
3718 
3719 Change the owner and group id of the file specified by file descriptor.
3720 
3721 Equivalent to os.chown(fd, uid, gid).
3722 
3723 [clinic start generated code]*/
3724 
3725 static PyObject *
os_fchown_impl(PyObject * module,int fd,uid_t uid,gid_t gid)3726 os_fchown_impl(PyObject *module, int fd, uid_t uid, gid_t gid)
3727 /*[clinic end generated code: output=97d21cbd5a4350a6 input=3af544ba1b13a0d7]*/
3728 {
3729     int res;
3730     int async_err = 0;
3731 
3732     if (PySys_Audit("os.chown", "iIIi", fd, uid, gid, -1) < 0) {
3733         return NULL;
3734     }
3735 
3736     do {
3737         Py_BEGIN_ALLOW_THREADS
3738         res = fchown(fd, uid, gid);
3739         Py_END_ALLOW_THREADS
3740     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
3741     if (res != 0)
3742         return (!async_err) ? posix_error() : NULL;
3743 
3744     Py_RETURN_NONE;
3745 }
3746 #endif /* HAVE_FCHOWN */
3747 
3748 
3749 #ifdef HAVE_LCHOWN
3750 /*[clinic input]
3751 os.lchown
3752 
3753     path : path_t
3754     uid: uid_t
3755     gid: gid_t
3756 
3757 Change the owner and group id of path to the numeric uid and gid.
3758 
3759 This function will not follow symbolic links.
3760 Equivalent to os.chown(path, uid, gid, follow_symlinks=False).
3761 [clinic start generated code]*/
3762 
3763 static PyObject *
os_lchown_impl(PyObject * module,path_t * path,uid_t uid,gid_t gid)3764 os_lchown_impl(PyObject *module, path_t *path, uid_t uid, gid_t gid)
3765 /*[clinic end generated code: output=25eaf6af412fdf2f input=b1c6014d563a7161]*/
3766 {
3767     int res;
3768     if (PySys_Audit("os.chown", "OIIi", path->object, uid, gid, -1) < 0) {
3769         return NULL;
3770     }
3771     Py_BEGIN_ALLOW_THREADS
3772     res = lchown(path->narrow, uid, gid);
3773     Py_END_ALLOW_THREADS
3774     if (res < 0) {
3775         return path_error(path);
3776     }
3777     Py_RETURN_NONE;
3778 }
3779 #endif /* HAVE_LCHOWN */
3780 
3781 
3782 static PyObject *
posix_getcwd(int use_bytes)3783 posix_getcwd(int use_bytes)
3784 {
3785 #ifdef MS_WINDOWS
3786     wchar_t wbuf[MAXPATHLEN];
3787     wchar_t *wbuf2 = wbuf;
3788     DWORD len;
3789 
3790     Py_BEGIN_ALLOW_THREADS
3791     len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf);
3792     /* If the buffer is large enough, len does not include the
3793        terminating \0. If the buffer is too small, len includes
3794        the space needed for the terminator. */
3795     if (len >= Py_ARRAY_LENGTH(wbuf)) {
3796         if (len <= PY_SSIZE_T_MAX / sizeof(wchar_t)) {
3797             wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t));
3798         }
3799         else {
3800             wbuf2 = NULL;
3801         }
3802         if (wbuf2) {
3803             len = GetCurrentDirectoryW(len, wbuf2);
3804         }
3805     }
3806     Py_END_ALLOW_THREADS
3807 
3808     if (!wbuf2) {
3809         PyErr_NoMemory();
3810         return NULL;
3811     }
3812     if (!len) {
3813         if (wbuf2 != wbuf)
3814             PyMem_RawFree(wbuf2);
3815         return PyErr_SetFromWindowsErr(0);
3816     }
3817 
3818     PyObject *resobj = PyUnicode_FromWideChar(wbuf2, len);
3819     if (wbuf2 != wbuf) {
3820         PyMem_RawFree(wbuf2);
3821     }
3822 
3823     if (use_bytes) {
3824         if (resobj == NULL) {
3825             return NULL;
3826         }
3827         Py_SETREF(resobj, PyUnicode_EncodeFSDefault(resobj));
3828     }
3829 
3830     return resobj;
3831 #else
3832     const size_t chunk = 1024;
3833 
3834     char *buf = NULL;
3835     char *cwd = NULL;
3836     size_t buflen = 0;
3837 
3838     Py_BEGIN_ALLOW_THREADS
3839     do {
3840         char *newbuf;
3841         if (buflen <= PY_SSIZE_T_MAX - chunk) {
3842             buflen += chunk;
3843             newbuf = PyMem_RawRealloc(buf, buflen);
3844         }
3845         else {
3846             newbuf = NULL;
3847         }
3848         if (newbuf == NULL) {
3849             PyMem_RawFree(buf);
3850             buf = NULL;
3851             break;
3852         }
3853         buf = newbuf;
3854 
3855         cwd = getcwd(buf, buflen);
3856     } while (cwd == NULL && errno == ERANGE);
3857     Py_END_ALLOW_THREADS
3858 
3859     if (buf == NULL) {
3860         return PyErr_NoMemory();
3861     }
3862     if (cwd == NULL) {
3863         PyMem_RawFree(buf);
3864         return posix_error();
3865     }
3866 
3867     PyObject *obj;
3868     if (use_bytes) {
3869         obj = PyBytes_FromStringAndSize(buf, strlen(buf));
3870     }
3871     else {
3872         obj = PyUnicode_DecodeFSDefault(buf);
3873     }
3874     PyMem_RawFree(buf);
3875 
3876     return obj;
3877 #endif   /* !MS_WINDOWS */
3878 }
3879 
3880 
3881 /*[clinic input]
3882 os.getcwd
3883 
3884 Return a unicode string representing the current working directory.
3885 [clinic start generated code]*/
3886 
3887 static PyObject *
os_getcwd_impl(PyObject * module)3888 os_getcwd_impl(PyObject *module)
3889 /*[clinic end generated code: output=21badfae2ea99ddc input=f069211bb70e3d39]*/
3890 {
3891     return posix_getcwd(0);
3892 }
3893 
3894 
3895 /*[clinic input]
3896 os.getcwdb
3897 
3898 Return a bytes string representing the current working directory.
3899 [clinic start generated code]*/
3900 
3901 static PyObject *
os_getcwdb_impl(PyObject * module)3902 os_getcwdb_impl(PyObject *module)
3903 /*[clinic end generated code: output=3dd47909480e4824 input=f6f6a378dad3d9cb]*/
3904 {
3905     return posix_getcwd(1);
3906 }
3907 
3908 
3909 #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS))
3910 #define HAVE_LINK 1
3911 #endif
3912 
3913 #ifdef HAVE_LINK
3914 /*[clinic input]
3915 
3916 os.link
3917 
3918     src : path_t
3919     dst : path_t
3920     *
3921     src_dir_fd : dir_fd = None
3922     dst_dir_fd : dir_fd = None
3923     follow_symlinks: bool = True
3924 
3925 Create a hard link to a file.
3926 
3927 If either src_dir_fd or dst_dir_fd is not None, it should be a file
3928   descriptor open to a directory, and the respective path string (src or dst)
3929   should be relative; the path will then be relative to that directory.
3930 If follow_symlinks is False, and the last element of src is a symbolic
3931   link, link will create a link to the symbolic link itself instead of the
3932   file the link points to.
3933 src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your
3934   platform.  If they are unavailable, using them will raise a
3935   NotImplementedError.
3936 [clinic start generated code]*/
3937 
3938 static PyObject *
os_link_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int follow_symlinks)3939 os_link_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
3940              int dst_dir_fd, int follow_symlinks)
3941 /*[clinic end generated code: output=7f00f6007fd5269a input=b0095ebbcbaa7e04]*/
3942 {
3943 #ifdef MS_WINDOWS
3944     BOOL result = FALSE;
3945 #else
3946     int result;
3947 #endif
3948 #if defined(HAVE_LINKAT)
3949     int linkat_unavailable = 0;
3950 #endif
3951 
3952 #ifndef HAVE_LINKAT
3953     if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) {
3954         argument_unavailable_error("link", "src_dir_fd and dst_dir_fd");
3955         return NULL;
3956     }
3957 #endif
3958 
3959 #ifndef MS_WINDOWS
3960     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
3961         PyErr_SetString(PyExc_NotImplementedError,
3962                         "link: src and dst must be the same type");
3963         return NULL;
3964     }
3965 #endif
3966 
3967     if (PySys_Audit("os.link", "OOii", src->object, dst->object,
3968                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
3969                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
3970         return NULL;
3971     }
3972 
3973 #ifdef MS_WINDOWS
3974     Py_BEGIN_ALLOW_THREADS
3975     result = CreateHardLinkW(dst->wide, src->wide, NULL);
3976     Py_END_ALLOW_THREADS
3977 
3978     if (!result)
3979         return path_error2(src, dst);
3980 #else
3981     Py_BEGIN_ALLOW_THREADS
3982 #ifdef HAVE_LINKAT
3983     if ((src_dir_fd != DEFAULT_DIR_FD) ||
3984         (dst_dir_fd != DEFAULT_DIR_FD) ||
3985         (!follow_symlinks)) {
3986 
3987         if (HAVE_LINKAT_RUNTIME) {
3988 
3989             result = linkat(src_dir_fd, src->narrow,
3990                 dst_dir_fd, dst->narrow,
3991                 follow_symlinks ? AT_SYMLINK_FOLLOW : 0);
3992 
3993         }
3994 #ifdef __APPLE__
3995         else {
3996             if (src_dir_fd == DEFAULT_DIR_FD && dst_dir_fd == DEFAULT_DIR_FD) {
3997                 /* See issue 41355: This matches the behaviour of !HAVE_LINKAT */
3998                 result = link(src->narrow, dst->narrow);
3999             } else {
4000                 linkat_unavailable = 1;
4001             }
4002         }
4003 #endif
4004     }
4005     else
4006 #endif /* HAVE_LINKAT */
4007         result = link(src->narrow, dst->narrow);
4008     Py_END_ALLOW_THREADS
4009 
4010 #ifdef HAVE_LINKAT
4011     if (linkat_unavailable) {
4012         /* Either or both dir_fd arguments were specified */
4013         if (src_dir_fd  != DEFAULT_DIR_FD) {
4014             argument_unavailable_error("link", "src_dir_fd");
4015         } else {
4016             argument_unavailable_error("link", "dst_dir_fd");
4017         }
4018         return NULL;
4019     }
4020 #endif
4021 
4022     if (result)
4023         return path_error2(src, dst);
4024 #endif /* MS_WINDOWS */
4025 
4026     Py_RETURN_NONE;
4027 }
4028 #endif
4029 
4030 
4031 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4032 static PyObject *
_listdir_windows_no_opendir(path_t * path,PyObject * list)4033 _listdir_windows_no_opendir(path_t *path, PyObject *list)
4034 {
4035     PyObject *v;
4036     HANDLE hFindFile = INVALID_HANDLE_VALUE;
4037     BOOL result;
4038     wchar_t namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */
4039     /* only claim to have space for MAX_PATH */
4040     Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4;
4041     wchar_t *wnamebuf = NULL;
4042 
4043     WIN32_FIND_DATAW wFileData;
4044     const wchar_t *po_wchars;
4045 
4046     if (!path->wide) { /* Default arg: "." */
4047         po_wchars = L".";
4048         len = 1;
4049     } else {
4050         po_wchars = path->wide;
4051         len = wcslen(path->wide);
4052     }
4053     /* The +5 is so we can append "\\*.*\0" */
4054     wnamebuf = PyMem_New(wchar_t, len + 5);
4055     if (!wnamebuf) {
4056         PyErr_NoMemory();
4057         goto exit;
4058     }
4059     wcscpy(wnamebuf, po_wchars);
4060     if (len > 0) {
4061         wchar_t wch = wnamebuf[len-1];
4062         if (wch != SEP && wch != ALTSEP && wch != L':')
4063             wnamebuf[len++] = SEP;
4064         wcscpy(wnamebuf + len, L"*.*");
4065     }
4066     if ((list = PyList_New(0)) == NULL) {
4067         goto exit;
4068     }
4069     Py_BEGIN_ALLOW_THREADS
4070     hFindFile = FindFirstFileW(wnamebuf, &wFileData);
4071     Py_END_ALLOW_THREADS
4072     if (hFindFile == INVALID_HANDLE_VALUE) {
4073         int error = GetLastError();
4074         if (error == ERROR_FILE_NOT_FOUND)
4075             goto exit;
4076         Py_DECREF(list);
4077         list = path_error(path);
4078         goto exit;
4079     }
4080     do {
4081         /* Skip over . and .. */
4082         if (wcscmp(wFileData.cFileName, L".") != 0 &&
4083             wcscmp(wFileData.cFileName, L"..") != 0) {
4084             v = PyUnicode_FromWideChar(wFileData.cFileName,
4085                                        wcslen(wFileData.cFileName));
4086             if (path->narrow && v) {
4087                 Py_SETREF(v, PyUnicode_EncodeFSDefault(v));
4088             }
4089             if (v == NULL) {
4090                 Py_DECREF(list);
4091                 list = NULL;
4092                 break;
4093             }
4094             if (PyList_Append(list, v) != 0) {
4095                 Py_DECREF(v);
4096                 Py_DECREF(list);
4097                 list = NULL;
4098                 break;
4099             }
4100             Py_DECREF(v);
4101         }
4102         Py_BEGIN_ALLOW_THREADS
4103         result = FindNextFileW(hFindFile, &wFileData);
4104         Py_END_ALLOW_THREADS
4105         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
4106            it got to the end of the directory. */
4107         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
4108             Py_DECREF(list);
4109             list = path_error(path);
4110             goto exit;
4111         }
4112     } while (result == TRUE);
4113 
4114 exit:
4115     if (hFindFile != INVALID_HANDLE_VALUE) {
4116         if (FindClose(hFindFile) == FALSE) {
4117             if (list != NULL) {
4118                 Py_DECREF(list);
4119                 list = path_error(path);
4120             }
4121         }
4122     }
4123     PyMem_Free(wnamebuf);
4124 
4125     return list;
4126 }  /* end of _listdir_windows_no_opendir */
4127 
4128 #else  /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */
4129 
4130 static PyObject *
_posix_listdir(path_t * path,PyObject * list)4131 _posix_listdir(path_t *path, PyObject *list)
4132 {
4133     PyObject *v;
4134     DIR *dirp = NULL;
4135     struct dirent *ep;
4136     int return_str; /* if false, return bytes */
4137 #ifdef HAVE_FDOPENDIR
4138     int fd = -1;
4139 #endif
4140 
4141     errno = 0;
4142 #ifdef HAVE_FDOPENDIR
4143     if (path->fd != -1) {
4144       if (HAVE_FDOPENDIR_RUNTIME) {
4145         /* closedir() closes the FD, so we duplicate it */
4146         fd = _Py_dup(path->fd);
4147         if (fd == -1)
4148             return NULL;
4149 
4150         return_str = 1;
4151 
4152         Py_BEGIN_ALLOW_THREADS
4153         dirp = fdopendir(fd);
4154         Py_END_ALLOW_THREADS
4155       } else {
4156         PyErr_SetString(PyExc_TypeError,
4157             "listdir: path should be string, bytes, os.PathLike or None, not int");
4158         return NULL;
4159       }
4160     }
4161     else
4162 #endif
4163     {
4164         const char *name;
4165         if (path->narrow) {
4166             name = path->narrow;
4167             /* only return bytes if they specified a bytes-like object */
4168             return_str = !PyObject_CheckBuffer(path->object);
4169         }
4170         else {
4171             name = ".";
4172             return_str = 1;
4173         }
4174 
4175         Py_BEGIN_ALLOW_THREADS
4176         dirp = opendir(name);
4177         Py_END_ALLOW_THREADS
4178     }
4179 
4180     if (dirp == NULL) {
4181         list = path_error(path);
4182 #ifdef HAVE_FDOPENDIR
4183         if (fd != -1) {
4184             Py_BEGIN_ALLOW_THREADS
4185             close(fd);
4186             Py_END_ALLOW_THREADS
4187         }
4188 #endif
4189         goto exit;
4190     }
4191     if ((list = PyList_New(0)) == NULL) {
4192         goto exit;
4193     }
4194     for (;;) {
4195         errno = 0;
4196         Py_BEGIN_ALLOW_THREADS
4197         ep = readdir(dirp);
4198         Py_END_ALLOW_THREADS
4199         if (ep == NULL) {
4200             if (errno == 0) {
4201                 break;
4202             } else {
4203                 Py_DECREF(list);
4204                 list = path_error(path);
4205                 goto exit;
4206             }
4207         }
4208         if (ep->d_name[0] == '.' &&
4209             (NAMLEN(ep) == 1 ||
4210              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
4211             continue;
4212         if (return_str)
4213             v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
4214         else
4215             v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
4216         if (v == NULL) {
4217             Py_CLEAR(list);
4218             break;
4219         }
4220         if (PyList_Append(list, v) != 0) {
4221             Py_DECREF(v);
4222             Py_CLEAR(list);
4223             break;
4224         }
4225         Py_DECREF(v);
4226     }
4227 
4228 exit:
4229     if (dirp != NULL) {
4230         Py_BEGIN_ALLOW_THREADS
4231 #ifdef HAVE_FDOPENDIR
4232         if (fd > -1)
4233             rewinddir(dirp);
4234 #endif
4235         closedir(dirp);
4236         Py_END_ALLOW_THREADS
4237     }
4238 
4239     return list;
4240 }  /* end of _posix_listdir */
4241 #endif  /* which OS */
4242 
4243 
4244 /*[clinic input]
4245 os.listdir
4246 
4247     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
4248 
4249 Return a list containing the names of the files in the directory.
4250 
4251 path can be specified as either str, bytes, or a path-like object.  If path is bytes,
4252   the filenames returned will also be bytes; in all other circumstances
4253   the filenames returned will be str.
4254 If path is None, uses the path='.'.
4255 On some platforms, path may also be specified as an open file descriptor;\
4256   the file descriptor must refer to a directory.
4257   If this functionality is unavailable, using it raises NotImplementedError.
4258 
4259 The list is in arbitrary order.  It does not include the special
4260 entries '.' and '..' even if they are present in the directory.
4261 
4262 
4263 [clinic start generated code]*/
4264 
4265 static PyObject *
os_listdir_impl(PyObject * module,path_t * path)4266 os_listdir_impl(PyObject *module, path_t *path)
4267 /*[clinic end generated code: output=293045673fcd1a75 input=e3f58030f538295d]*/
4268 {
4269     if (PySys_Audit("os.listdir", "O",
4270                     path->object ? path->object : Py_None) < 0) {
4271         return NULL;
4272     }
4273 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
4274     return _listdir_windows_no_opendir(path, NULL);
4275 #else
4276     return _posix_listdir(path, NULL);
4277 #endif
4278 }
4279 
4280 #ifdef MS_WINDOWS
4281 int
_PyOS_getfullpathname(const wchar_t * path,wchar_t ** abspath_p)4282 _PyOS_getfullpathname(const wchar_t *path, wchar_t **abspath_p)
4283 {
4284     wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf;
4285     DWORD result;
4286 
4287     result = GetFullPathNameW(path,
4288                               Py_ARRAY_LENGTH(woutbuf), woutbuf,
4289                               NULL);
4290     if (!result) {
4291         return -1;
4292     }
4293 
4294     if (result >= Py_ARRAY_LENGTH(woutbuf)) {
4295         if ((size_t)result <= (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
4296             woutbufp = PyMem_RawMalloc((size_t)result * sizeof(wchar_t));
4297         }
4298         else {
4299             woutbufp = NULL;
4300         }
4301         if (!woutbufp) {
4302             *abspath_p = NULL;
4303             return 0;
4304         }
4305 
4306         result = GetFullPathNameW(path, result, woutbufp, NULL);
4307         if (!result) {
4308             PyMem_RawFree(woutbufp);
4309             return -1;
4310         }
4311     }
4312 
4313     if (woutbufp != woutbuf) {
4314         *abspath_p = woutbufp;
4315         return 0;
4316     }
4317 
4318     *abspath_p = _PyMem_RawWcsdup(woutbufp);
4319     return 0;
4320 }
4321 
4322 
4323 /* A helper function for abspath on win32 */
4324 /*[clinic input]
4325 os._getfullpathname
4326 
4327     path: path_t
4328     /
4329 
4330 [clinic start generated code]*/
4331 
4332 static PyObject *
os__getfullpathname_impl(PyObject * module,path_t * path)4333 os__getfullpathname_impl(PyObject *module, path_t *path)
4334 /*[clinic end generated code: output=bb8679d56845bc9b input=332ed537c29d0a3e]*/
4335 {
4336     wchar_t *abspath;
4337 
4338     if (_PyOS_getfullpathname(path->wide, &abspath) < 0) {
4339         return win32_error_object("GetFullPathNameW", path->object);
4340     }
4341     if (abspath == NULL) {
4342         return PyErr_NoMemory();
4343     }
4344 
4345     PyObject *str = PyUnicode_FromWideChar(abspath, wcslen(abspath));
4346     PyMem_RawFree(abspath);
4347     if (str == NULL) {
4348         return NULL;
4349     }
4350     if (path->narrow) {
4351         Py_SETREF(str, PyUnicode_EncodeFSDefault(str));
4352     }
4353     return str;
4354 }
4355 
4356 
4357 /*[clinic input]
4358 os._getfinalpathname
4359 
4360     path: path_t
4361     /
4362 
4363 A helper function for samepath on windows.
4364 [clinic start generated code]*/
4365 
4366 static PyObject *
os__getfinalpathname_impl(PyObject * module,path_t * path)4367 os__getfinalpathname_impl(PyObject *module, path_t *path)
4368 /*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/
4369 {
4370     HANDLE hFile;
4371     wchar_t buf[MAXPATHLEN], *target_path = buf;
4372     int buf_size = Py_ARRAY_LENGTH(buf);
4373     int result_length;
4374     PyObject *result;
4375 
4376     Py_BEGIN_ALLOW_THREADS
4377     hFile = CreateFileW(
4378         path->wide,
4379         0, /* desired access */
4380         0, /* share mode */
4381         NULL, /* security attributes */
4382         OPEN_EXISTING,
4383         /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
4384         FILE_FLAG_BACKUP_SEMANTICS,
4385         NULL);
4386     Py_END_ALLOW_THREADS
4387 
4388     if (hFile == INVALID_HANDLE_VALUE) {
4389         return win32_error_object("CreateFileW", path->object);
4390     }
4391 
4392     /* We have a good handle to the target, use it to determine the
4393        target path name. */
4394     while (1) {
4395         Py_BEGIN_ALLOW_THREADS
4396         result_length = GetFinalPathNameByHandleW(hFile, target_path,
4397                                                   buf_size, VOLUME_NAME_DOS);
4398         Py_END_ALLOW_THREADS
4399 
4400         if (!result_length) {
4401             result = win32_error_object("GetFinalPathNameByHandleW",
4402                                          path->object);
4403             goto cleanup;
4404         }
4405 
4406         if (result_length < buf_size) {
4407             break;
4408         }
4409 
4410         wchar_t *tmp;
4411         tmp = PyMem_Realloc(target_path != buf ? target_path : NULL,
4412                             result_length * sizeof(*tmp));
4413         if (!tmp) {
4414             result = PyErr_NoMemory();
4415             goto cleanup;
4416         }
4417 
4418         buf_size = result_length;
4419         target_path = tmp;
4420     }
4421 
4422     result = PyUnicode_FromWideChar(target_path, result_length);
4423     if (result && path->narrow) {
4424         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4425     }
4426 
4427 cleanup:
4428     if (target_path != buf) {
4429         PyMem_Free(target_path);
4430     }
4431     CloseHandle(hFile);
4432     return result;
4433 }
4434 
4435 
4436 /*[clinic input]
4437 os._getvolumepathname
4438 
4439     path: path_t
4440 
4441 A helper function for ismount on Win32.
4442 [clinic start generated code]*/
4443 
4444 static PyObject *
os__getvolumepathname_impl(PyObject * module,path_t * path)4445 os__getvolumepathname_impl(PyObject *module, path_t *path)
4446 /*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/
4447 {
4448     PyObject *result;
4449     wchar_t *mountpath=NULL;
4450     size_t buflen;
4451     BOOL ret;
4452 
4453     /* Volume path should be shorter than entire path */
4454     buflen = Py_MAX(path->length, MAX_PATH);
4455 
4456     if (buflen > PY_DWORD_MAX) {
4457         PyErr_SetString(PyExc_OverflowError, "path too long");
4458         return NULL;
4459     }
4460 
4461     mountpath = PyMem_New(wchar_t, buflen);
4462     if (mountpath == NULL)
4463         return PyErr_NoMemory();
4464 
4465     Py_BEGIN_ALLOW_THREADS
4466     ret = GetVolumePathNameW(path->wide, mountpath,
4467                              Py_SAFE_DOWNCAST(buflen, size_t, DWORD));
4468     Py_END_ALLOW_THREADS
4469 
4470     if (!ret) {
4471         result = win32_error_object("_getvolumepathname", path->object);
4472         goto exit;
4473     }
4474     result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath));
4475     if (path->narrow)
4476         Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
4477 
4478 exit:
4479     PyMem_Free(mountpath);
4480     return result;
4481 }
4482 
4483 
4484 /*[clinic input]
4485 os._path_splitroot
4486 
4487     path: path_t
4488 
4489 Removes everything after the root on Win32.
4490 [clinic start generated code]*/
4491 
4492 static PyObject *
os__path_splitroot_impl(PyObject * module,path_t * path)4493 os__path_splitroot_impl(PyObject *module, path_t *path)
4494 /*[clinic end generated code: output=ab7f1a88b654581c input=dc93b1d3984cffb6]*/
4495 {
4496     wchar_t *buffer;
4497     wchar_t *end;
4498     PyObject *result = NULL;
4499     HRESULT ret;
4500 
4501     buffer = (wchar_t*)PyMem_Malloc(sizeof(wchar_t) * (wcslen(path->wide) + 1));
4502     if (!buffer) {
4503         return NULL;
4504     }
4505     wcscpy(buffer, path->wide);
4506     for (wchar_t *p = wcschr(buffer, L'/'); p; p = wcschr(p, L'/')) {
4507         *p = L'\\';
4508     }
4509 
4510     Py_BEGIN_ALLOW_THREADS
4511     ret = PathCchSkipRoot(buffer, &end);
4512     Py_END_ALLOW_THREADS
4513     if (FAILED(ret)) {
4514         result = Py_BuildValue("sO", "", path->object);
4515     } else if (end != buffer) {
4516         size_t rootLen = (size_t)(end - buffer);
4517         result = Py_BuildValue("NN",
4518             PyUnicode_FromWideChar(path->wide, rootLen),
4519             PyUnicode_FromWideChar(path->wide + rootLen, -1)
4520         );
4521     } else {
4522         result = Py_BuildValue("Os", path->object, "");
4523     }
4524     PyMem_Free(buffer);
4525 
4526     return result;
4527 }
4528 
4529 
4530 #endif /* MS_WINDOWS */
4531 
4532 
4533 /*[clinic input]
4534 os._path_normpath
4535 
4536     path: object
4537 
4538 Basic path normalization.
4539 [clinic start generated code]*/
4540 
4541 static PyObject *
os__path_normpath_impl(PyObject * module,PyObject * path)4542 os__path_normpath_impl(PyObject *module, PyObject *path)
4543 /*[clinic end generated code: output=b94d696d828019da input=5e90c39e12549dc0]*/
4544 {
4545     if (!PyUnicode_Check(path)) {
4546         PyErr_Format(PyExc_TypeError, "expected 'str', not '%.200s'",
4547             Py_TYPE(path)->tp_name);
4548         return NULL;
4549     }
4550     Py_ssize_t len;
4551     wchar_t *buffer = PyUnicode_AsWideCharString(path, &len);
4552     if (!buffer) {
4553         return NULL;
4554     }
4555     PyObject *result = PyUnicode_FromWideChar(_Py_normpath(buffer, len), -1);
4556     PyMem_Free(buffer);
4557     return result;
4558 }
4559 
4560 /*[clinic input]
4561 os.mkdir
4562 
4563     path : path_t
4564 
4565     mode: int = 0o777
4566 
4567     *
4568 
4569     dir_fd : dir_fd(requires='mkdirat') = None
4570 
4571 # "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\
4572 
4573 Create a directory.
4574 
4575 If dir_fd is not None, it should be a file descriptor open to a directory,
4576   and path should be relative; path will then be relative to that directory.
4577 dir_fd may not be implemented on your platform.
4578   If it is unavailable, using it will raise a NotImplementedError.
4579 
4580 The mode argument is ignored on Windows. Where it is used, the current umask
4581 value is first masked out.
4582 [clinic start generated code]*/
4583 
4584 static PyObject *
os_mkdir_impl(PyObject * module,path_t * path,int mode,int dir_fd)4585 os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
4586 /*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
4587 {
4588     int result;
4589 #ifdef HAVE_MKDIRAT
4590     int mkdirat_unavailable = 0;
4591 #endif
4592 
4593     if (PySys_Audit("os.mkdir", "Oii", path->object, mode,
4594                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4595         return NULL;
4596     }
4597 
4598 #ifdef MS_WINDOWS
4599     Py_BEGIN_ALLOW_THREADS
4600     result = CreateDirectoryW(path->wide, NULL);
4601     Py_END_ALLOW_THREADS
4602 
4603     if (!result)
4604         return path_error(path);
4605 #else
4606     Py_BEGIN_ALLOW_THREADS
4607 #if HAVE_MKDIRAT
4608     if (dir_fd != DEFAULT_DIR_FD) {
4609       if (HAVE_MKDIRAT_RUNTIME) {
4610         result = mkdirat(dir_fd, path->narrow, mode);
4611 
4612       } else {
4613         mkdirat_unavailable = 1;
4614       }
4615     } else
4616 #endif
4617 #if defined(__WATCOMC__) && !defined(__QNX__)
4618         result = mkdir(path->narrow);
4619 #else
4620         result = mkdir(path->narrow, mode);
4621 #endif
4622     Py_END_ALLOW_THREADS
4623 
4624 #if HAVE_MKDIRAT
4625     if (mkdirat_unavailable) {
4626         argument_unavailable_error(NULL, "dir_fd");
4627         return NULL;
4628     }
4629 #endif
4630 
4631     if (result < 0)
4632         return path_error(path);
4633 #endif /* MS_WINDOWS */
4634     Py_RETURN_NONE;
4635 }
4636 
4637 
4638 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
4639 #if defined(HAVE_SYS_RESOURCE_H)
4640 #include <sys/resource.h>
4641 #endif
4642 
4643 
4644 #ifdef HAVE_NICE
4645 /*[clinic input]
4646 os.nice
4647 
4648     increment: int
4649     /
4650 
4651 Add increment to the priority of process and return the new priority.
4652 [clinic start generated code]*/
4653 
4654 static PyObject *
os_nice_impl(PyObject * module,int increment)4655 os_nice_impl(PyObject *module, int increment)
4656 /*[clinic end generated code: output=9dad8a9da8109943 input=864be2d402a21da2]*/
4657 {
4658     int value;
4659 
4660     /* There are two flavours of 'nice': one that returns the new
4661        priority (as required by almost all standards out there) and the
4662        Linux/FreeBSD one, which returns '0' on success and advices
4663        the use of getpriority() to get the new priority.
4664 
4665        If we are of the nice family that returns the new priority, we
4666        need to clear errno before the call, and check if errno is filled
4667        before calling posix_error() on a returnvalue of -1, because the
4668        -1 may be the actual new priority! */
4669 
4670     errno = 0;
4671     value = nice(increment);
4672 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
4673     if (value == 0)
4674         value = getpriority(PRIO_PROCESS, 0);
4675 #endif
4676     if (value == -1 && errno != 0)
4677         /* either nice() or getpriority() returned an error */
4678         return posix_error();
4679     return PyLong_FromLong((long) value);
4680 }
4681 #endif /* HAVE_NICE */
4682 
4683 
4684 #ifdef HAVE_GETPRIORITY
4685 /*[clinic input]
4686 os.getpriority
4687 
4688     which: int
4689     who: int
4690 
4691 Return program scheduling priority.
4692 [clinic start generated code]*/
4693 
4694 static PyObject *
os_getpriority_impl(PyObject * module,int which,int who)4695 os_getpriority_impl(PyObject *module, int which, int who)
4696 /*[clinic end generated code: output=c41b7b63c7420228 input=9be615d40e2544ef]*/
4697 {
4698     int retval;
4699 
4700     errno = 0;
4701     retval = getpriority(which, who);
4702     if (errno != 0)
4703         return posix_error();
4704     return PyLong_FromLong((long)retval);
4705 }
4706 #endif /* HAVE_GETPRIORITY */
4707 
4708 
4709 #ifdef HAVE_SETPRIORITY
4710 /*[clinic input]
4711 os.setpriority
4712 
4713     which: int
4714     who: int
4715     priority: int
4716 
4717 Set program scheduling priority.
4718 [clinic start generated code]*/
4719 
4720 static PyObject *
os_setpriority_impl(PyObject * module,int which,int who,int priority)4721 os_setpriority_impl(PyObject *module, int which, int who, int priority)
4722 /*[clinic end generated code: output=3d910d95a7771eb2 input=710ccbf65b9dc513]*/
4723 {
4724     int retval;
4725 
4726     retval = setpriority(which, who, priority);
4727     if (retval == -1)
4728         return posix_error();
4729     Py_RETURN_NONE;
4730 }
4731 #endif /* HAVE_SETPRIORITY */
4732 
4733 
4734 static PyObject *
internal_rename(path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd,int is_replace)4735 internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace)
4736 {
4737     const char *function_name = is_replace ? "replace" : "rename";
4738     int dir_fd_specified;
4739 
4740 #ifdef HAVE_RENAMEAT
4741     int renameat_unavailable = 0;
4742 #endif
4743 
4744 #ifdef MS_WINDOWS
4745     BOOL result;
4746     int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0;
4747 #else
4748     int result;
4749 #endif
4750 
4751     dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) ||
4752                        (dst_dir_fd != DEFAULT_DIR_FD);
4753 #ifndef HAVE_RENAMEAT
4754     if (dir_fd_specified) {
4755         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4756         return NULL;
4757     }
4758 #endif
4759 
4760     if (PySys_Audit("os.rename", "OOii", src->object, dst->object,
4761                     src_dir_fd == DEFAULT_DIR_FD ? -1 : src_dir_fd,
4762                     dst_dir_fd == DEFAULT_DIR_FD ? -1 : dst_dir_fd) < 0) {
4763         return NULL;
4764     }
4765 
4766 #ifdef MS_WINDOWS
4767     Py_BEGIN_ALLOW_THREADS
4768     result = MoveFileExW(src->wide, dst->wide, flags);
4769     Py_END_ALLOW_THREADS
4770 
4771     if (!result)
4772         return path_error2(src, dst);
4773 
4774 #else
4775     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
4776         PyErr_Format(PyExc_ValueError,
4777                      "%s: src and dst must be the same type", function_name);
4778         return NULL;
4779     }
4780 
4781     Py_BEGIN_ALLOW_THREADS
4782 #ifdef HAVE_RENAMEAT
4783     if (dir_fd_specified) {
4784         if (HAVE_RENAMEAT_RUNTIME) {
4785             result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow);
4786         } else {
4787             renameat_unavailable = 1;
4788         }
4789     } else
4790 #endif
4791     result = rename(src->narrow, dst->narrow);
4792     Py_END_ALLOW_THREADS
4793 
4794 
4795 #ifdef HAVE_RENAMEAT
4796     if (renameat_unavailable) {
4797         argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd");
4798         return NULL;
4799     }
4800 #endif
4801 
4802     if (result)
4803         return path_error2(src, dst);
4804 #endif
4805     Py_RETURN_NONE;
4806 }
4807 
4808 
4809 /*[clinic input]
4810 os.rename
4811 
4812     src : path_t
4813     dst : path_t
4814     *
4815     src_dir_fd : dir_fd = None
4816     dst_dir_fd : dir_fd = None
4817 
4818 Rename a file or directory.
4819 
4820 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4821   descriptor open to a directory, and the respective path string (src or dst)
4822   should be relative; the path will then be relative to that directory.
4823 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4824   If they are unavailable, using them will raise a NotImplementedError.
4825 [clinic start generated code]*/
4826 
4827 static PyObject *
os_rename_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4828 os_rename_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4829                int dst_dir_fd)
4830 /*[clinic end generated code: output=59e803072cf41230 input=faa61c847912c850]*/
4831 {
4832     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0);
4833 }
4834 
4835 
4836 /*[clinic input]
4837 os.replace = os.rename
4838 
4839 Rename a file or directory, overwriting the destination.
4840 
4841 If either src_dir_fd or dst_dir_fd is not None, it should be a file
4842   descriptor open to a directory, and the respective path string (src or dst)
4843   should be relative; the path will then be relative to that directory.
4844 src_dir_fd and dst_dir_fd, may not be implemented on your platform.
4845   If they are unavailable, using them will raise a NotImplementedError.
4846 [clinic start generated code]*/
4847 
4848 static PyObject *
os_replace_impl(PyObject * module,path_t * src,path_t * dst,int src_dir_fd,int dst_dir_fd)4849 os_replace_impl(PyObject *module, path_t *src, path_t *dst, int src_dir_fd,
4850                 int dst_dir_fd)
4851 /*[clinic end generated code: output=1968c02e7857422b input=c003f0def43378ef]*/
4852 {
4853     return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1);
4854 }
4855 
4856 
4857 /*[clinic input]
4858 os.rmdir
4859 
4860     path: path_t
4861     *
4862     dir_fd: dir_fd(requires='unlinkat') = None
4863 
4864 Remove a directory.
4865 
4866 If dir_fd is not None, it should be a file descriptor open to a directory,
4867   and path should be relative; path will then be relative to that directory.
4868 dir_fd may not be implemented on your platform.
4869   If it is unavailable, using it will raise a NotImplementedError.
4870 [clinic start generated code]*/
4871 
4872 static PyObject *
os_rmdir_impl(PyObject * module,path_t * path,int dir_fd)4873 os_rmdir_impl(PyObject *module, path_t *path, int dir_fd)
4874 /*[clinic end generated code: output=080eb54f506e8301 input=38c8b375ca34a7e2]*/
4875 {
4876     int result;
4877 #ifdef HAVE_UNLINKAT
4878     int unlinkat_unavailable = 0;
4879 #endif
4880 
4881     if (PySys_Audit("os.rmdir", "Oi", path->object,
4882                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
4883         return NULL;
4884     }
4885 
4886     Py_BEGIN_ALLOW_THREADS
4887 #ifdef MS_WINDOWS
4888     /* Windows, success=1, UNIX, success=0 */
4889     result = !RemoveDirectoryW(path->wide);
4890 #else
4891 #ifdef HAVE_UNLINKAT
4892     if (dir_fd != DEFAULT_DIR_FD) {
4893       if (HAVE_UNLINKAT_RUNTIME) {
4894         result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR);
4895       } else {
4896         unlinkat_unavailable = 1;
4897         result = -1;
4898       }
4899     } else
4900 #endif
4901         result = rmdir(path->narrow);
4902 #endif
4903     Py_END_ALLOW_THREADS
4904 
4905 #ifdef HAVE_UNLINKAT
4906     if (unlinkat_unavailable) {
4907         argument_unavailable_error("rmdir", "dir_fd");
4908         return NULL;
4909     }
4910 #endif
4911 
4912     if (result)
4913         return path_error(path);
4914 
4915     Py_RETURN_NONE;
4916 }
4917 
4918 
4919 #ifdef HAVE_SYSTEM
4920 #ifdef MS_WINDOWS
4921 /*[clinic input]
4922 os.system -> long
4923 
4924     command: Py_UNICODE
4925 
4926 Execute the command in a subshell.
4927 [clinic start generated code]*/
4928 
4929 static long
os_system_impl(PyObject * module,const Py_UNICODE * command)4930 os_system_impl(PyObject *module, const Py_UNICODE *command)
4931 /*[clinic end generated code: output=5b7c3599c068ca42 input=303f5ce97df606b0]*/
4932 {
4933     long result;
4934 
4935     if (PySys_Audit("os.system", "(u)", command) < 0) {
4936         return -1;
4937     }
4938 
4939     Py_BEGIN_ALLOW_THREADS
4940     _Py_BEGIN_SUPPRESS_IPH
4941     result = _wsystem(command);
4942     _Py_END_SUPPRESS_IPH
4943     Py_END_ALLOW_THREADS
4944     return result;
4945 }
4946 #else /* MS_WINDOWS */
4947 /*[clinic input]
4948 os.system -> long
4949 
4950     command: FSConverter
4951 
4952 Execute the command in a subshell.
4953 [clinic start generated code]*/
4954 
4955 static long
os_system_impl(PyObject * module,PyObject * command)4956 os_system_impl(PyObject *module, PyObject *command)
4957 /*[clinic end generated code: output=290fc437dd4f33a0 input=86a58554ba6094af]*/
4958 {
4959     long result;
4960     const char *bytes = PyBytes_AsString(command);
4961 
4962     if (PySys_Audit("os.system", "(O)", command) < 0) {
4963         return -1;
4964     }
4965 
4966     Py_BEGIN_ALLOW_THREADS
4967     result = system(bytes);
4968     Py_END_ALLOW_THREADS
4969     return result;
4970 }
4971 #endif
4972 #endif /* HAVE_SYSTEM */
4973 
4974 
4975 #ifdef HAVE_UMASK
4976 /*[clinic input]
4977 os.umask
4978 
4979     mask: int
4980     /
4981 
4982 Set the current numeric umask and return the previous umask.
4983 [clinic start generated code]*/
4984 
4985 static PyObject *
os_umask_impl(PyObject * module,int mask)4986 os_umask_impl(PyObject *module, int mask)
4987 /*[clinic end generated code: output=a2e33ce3bc1a6e33 input=ab6bfd9b24d8a7e8]*/
4988 {
4989     int i = (int)umask(mask);
4990     if (i < 0)
4991         return posix_error();
4992     return PyLong_FromLong((long)i);
4993 }
4994 #endif
4995 
4996 #ifdef MS_WINDOWS
4997 
4998 /* override the default DeleteFileW behavior so that directory
4999 symlinks can be removed with this function, the same as with
5000 Unix symlinks */
Py_DeleteFileW(LPCWSTR lpFileName)5001 BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
5002 {
5003     WIN32_FILE_ATTRIBUTE_DATA info;
5004     WIN32_FIND_DATAW find_data;
5005     HANDLE find_data_handle;
5006     int is_directory = 0;
5007     int is_link = 0;
5008 
5009     if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
5010         is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
5011 
5012         /* Get WIN32_FIND_DATA structure for the path to determine if
5013            it is a symlink */
5014         if(is_directory &&
5015            info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
5016             find_data_handle = FindFirstFileW(lpFileName, &find_data);
5017 
5018             if(find_data_handle != INVALID_HANDLE_VALUE) {
5019                 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and
5020                    IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */
5021                 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK ||
5022                           find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT;
5023                 FindClose(find_data_handle);
5024             }
5025         }
5026     }
5027 
5028     if (is_directory && is_link)
5029         return RemoveDirectoryW(lpFileName);
5030 
5031     return DeleteFileW(lpFileName);
5032 }
5033 #endif /* MS_WINDOWS */
5034 
5035 
5036 /*[clinic input]
5037 os.unlink
5038 
5039     path: path_t
5040     *
5041     dir_fd: dir_fd(requires='unlinkat')=None
5042 
5043 Remove a file (same as remove()).
5044 
5045 If dir_fd is not None, it should be a file descriptor open to a directory,
5046   and path should be relative; path will then be relative to that directory.
5047 dir_fd may not be implemented on your platform.
5048   If it is unavailable, using it will raise a NotImplementedError.
5049 
5050 [clinic start generated code]*/
5051 
5052 static PyObject *
os_unlink_impl(PyObject * module,path_t * path,int dir_fd)5053 os_unlink_impl(PyObject *module, path_t *path, int dir_fd)
5054 /*[clinic end generated code: output=621797807b9963b1 input=d7bcde2b1b2a2552]*/
5055 {
5056     int result;
5057 #ifdef HAVE_UNLINKAT
5058     int unlinkat_unavailable = 0;
5059 #endif
5060 
5061     if (PySys_Audit("os.remove", "Oi", path->object,
5062                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5063         return NULL;
5064     }
5065 
5066     Py_BEGIN_ALLOW_THREADS
5067     _Py_BEGIN_SUPPRESS_IPH
5068 #ifdef MS_WINDOWS
5069     /* Windows, success=1, UNIX, success=0 */
5070     result = !Py_DeleteFileW(path->wide);
5071 #else
5072 #ifdef HAVE_UNLINKAT
5073     if (dir_fd != DEFAULT_DIR_FD) {
5074       if (HAVE_UNLINKAT_RUNTIME) {
5075 
5076         result = unlinkat(dir_fd, path->narrow, 0);
5077       } else {
5078         unlinkat_unavailable = 1;
5079       }
5080     } else
5081 #endif /* HAVE_UNLINKAT */
5082         result = unlink(path->narrow);
5083 #endif
5084     _Py_END_SUPPRESS_IPH
5085     Py_END_ALLOW_THREADS
5086 
5087 #ifdef HAVE_UNLINKAT
5088     if (unlinkat_unavailable) {
5089         argument_unavailable_error(NULL, "dir_fd");
5090         return NULL;
5091     }
5092 #endif
5093 
5094     if (result)
5095         return path_error(path);
5096 
5097     Py_RETURN_NONE;
5098 }
5099 
5100 
5101 /*[clinic input]
5102 os.remove = os.unlink
5103 
5104 Remove a file (same as unlink()).
5105 
5106 If dir_fd is not None, it should be a file descriptor open to a directory,
5107   and path should be relative; path will then be relative to that directory.
5108 dir_fd may not be implemented on your platform.
5109   If it is unavailable, using it will raise a NotImplementedError.
5110 [clinic start generated code]*/
5111 
5112 static PyObject *
os_remove_impl(PyObject * module,path_t * path,int dir_fd)5113 os_remove_impl(PyObject *module, path_t *path, int dir_fd)
5114 /*[clinic end generated code: output=a8535b28f0068883 input=e05c5ab55cd30983]*/
5115 {
5116     return os_unlink_impl(module, path, dir_fd);
5117 }
5118 
5119 
5120 static PyStructSequence_Field uname_result_fields[] = {
5121     {"sysname",    "operating system name"},
5122     {"nodename",   "name of machine on network (implementation-defined)"},
5123     {"release",    "operating system release"},
5124     {"version",    "operating system version"},
5125     {"machine",    "hardware identifier"},
5126     {NULL}
5127 };
5128 
5129 PyDoc_STRVAR(uname_result__doc__,
5130 "uname_result: Result from os.uname().\n\n\
5131 This object may be accessed either as a tuple of\n\
5132   (sysname, nodename, release, version, machine),\n\
5133 or via the attributes sysname, nodename, release, version, and machine.\n\
5134 \n\
5135 See os.uname for more information.");
5136 
5137 static PyStructSequence_Desc uname_result_desc = {
5138     MODNAME ".uname_result", /* name */
5139     uname_result__doc__, /* doc */
5140     uname_result_fields,
5141     5
5142 };
5143 
5144 #ifdef HAVE_UNAME
5145 /*[clinic input]
5146 os.uname
5147 
5148 Return an object identifying the current operating system.
5149 
5150 The object behaves like a named tuple with the following fields:
5151   (sysname, nodename, release, version, machine)
5152 
5153 [clinic start generated code]*/
5154 
5155 static PyObject *
os_uname_impl(PyObject * module)5156 os_uname_impl(PyObject *module)
5157 /*[clinic end generated code: output=e6a49cf1a1508a19 input=e68bd246db3043ed]*/
5158 {
5159     struct utsname u;
5160     int res;
5161     PyObject *value;
5162 
5163     Py_BEGIN_ALLOW_THREADS
5164     res = uname(&u);
5165     Py_END_ALLOW_THREADS
5166     if (res < 0)
5167         return posix_error();
5168 
5169     PyObject *UnameResultType = get_posix_state(module)->UnameResultType;
5170     value = PyStructSequence_New((PyTypeObject *)UnameResultType);
5171     if (value == NULL)
5172         return NULL;
5173 
5174 #define SET(i, field) \
5175     { \
5176     PyObject *o = PyUnicode_DecodeFSDefault(field); \
5177     if (!o) { \
5178         Py_DECREF(value); \
5179         return NULL; \
5180     } \
5181     PyStructSequence_SET_ITEM(value, i, o); \
5182     } \
5183 
5184     SET(0, u.sysname);
5185     SET(1, u.nodename);
5186     SET(2, u.release);
5187     SET(3, u.version);
5188     SET(4, u.machine);
5189 
5190 #undef SET
5191 
5192     return value;
5193 }
5194 #endif /* HAVE_UNAME */
5195 
5196 
5197 
5198 typedef struct {
5199     int    now;
5200     time_t atime_s;
5201     long   atime_ns;
5202     time_t mtime_s;
5203     long   mtime_ns;
5204 } utime_t;
5205 
5206 /*
5207  * these macros assume that "ut" is a pointer to a utime_t
5208  * they also intentionally leak the declaration of a pointer named "time"
5209  */
5210 #define UTIME_TO_TIMESPEC \
5211     struct timespec ts[2]; \
5212     struct timespec *time; \
5213     if (ut->now) \
5214         time = NULL; \
5215     else { \
5216         ts[0].tv_sec = ut->atime_s; \
5217         ts[0].tv_nsec = ut->atime_ns; \
5218         ts[1].tv_sec = ut->mtime_s; \
5219         ts[1].tv_nsec = ut->mtime_ns; \
5220         time = ts; \
5221     } \
5222 
5223 #define UTIME_TO_TIMEVAL \
5224     struct timeval tv[2]; \
5225     struct timeval *time; \
5226     if (ut->now) \
5227         time = NULL; \
5228     else { \
5229         tv[0].tv_sec = ut->atime_s; \
5230         tv[0].tv_usec = ut->atime_ns / 1000; \
5231         tv[1].tv_sec = ut->mtime_s; \
5232         tv[1].tv_usec = ut->mtime_ns / 1000; \
5233         time = tv; \
5234     } \
5235 
5236 #define UTIME_TO_UTIMBUF \
5237     struct utimbuf u; \
5238     struct utimbuf *time; \
5239     if (ut->now) \
5240         time = NULL; \
5241     else { \
5242         u.actime = ut->atime_s; \
5243         u.modtime = ut->mtime_s; \
5244         time = &u; \
5245     }
5246 
5247 #define UTIME_TO_TIME_T \
5248     time_t timet[2]; \
5249     time_t *time; \
5250     if (ut->now) \
5251         time = NULL; \
5252     else { \
5253         timet[0] = ut->atime_s; \
5254         timet[1] = ut->mtime_s; \
5255         time = timet; \
5256     } \
5257 
5258 
5259 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5260 
5261 static int
utime_dir_fd(utime_t * ut,int dir_fd,const char * path,int follow_symlinks)5262 utime_dir_fd(utime_t *ut, int dir_fd, const char *path, int follow_symlinks)
5263 {
5264 #if defined(__APPLE__) &&  defined(HAVE_UTIMENSAT)
5265     if (HAVE_UTIMENSAT_RUNTIME) {
5266         int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5267         UTIME_TO_TIMESPEC;
5268         return utimensat(dir_fd, path, time, flags);
5269     }  else {
5270         errno = ENOSYS;
5271         return -1;
5272     }
5273 #elif defined(HAVE_UTIMENSAT)
5274     int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW;
5275     UTIME_TO_TIMESPEC;
5276     return utimensat(dir_fd, path, time, flags);
5277 #elif defined(HAVE_FUTIMESAT)
5278     UTIME_TO_TIMEVAL;
5279     /*
5280      * follow_symlinks will never be false here;
5281      * we only allow !follow_symlinks and dir_fd together
5282      * if we have utimensat()
5283      */
5284     assert(follow_symlinks);
5285     return futimesat(dir_fd, path, time);
5286 #endif
5287 }
5288 
5289     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter
5290 #else
5291     #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable
5292 #endif
5293 
5294 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5295 
5296 static int
utime_fd(utime_t * ut,int fd)5297 utime_fd(utime_t *ut, int fd)
5298 {
5299 #ifdef HAVE_FUTIMENS
5300 
5301     if (HAVE_FUTIMENS_RUNTIME) {
5302 
5303     UTIME_TO_TIMESPEC;
5304     return futimens(fd, time);
5305 
5306     } else
5307 #ifndef HAVE_FUTIMES
5308     {
5309         /* Not sure if this can happen */
5310         PyErr_SetString(
5311             PyExc_RuntimeError,
5312             "neither futimens nor futimes are supported"
5313             " on this system");
5314         return -1;
5315     }
5316 #endif
5317 
5318 #endif
5319 #ifdef HAVE_FUTIMES
5320     {
5321     UTIME_TO_TIMEVAL;
5322     return futimes(fd, time);
5323     }
5324 #endif
5325 }
5326 
5327     #define PATH_UTIME_HAVE_FD 1
5328 #else
5329     #define PATH_UTIME_HAVE_FD 0
5330 #endif
5331 
5332 #if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)
5333 #  define UTIME_HAVE_NOFOLLOW_SYMLINKS
5334 #endif
5335 
5336 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5337 
5338 static int
utime_nofollow_symlinks(utime_t * ut,const char * path)5339 utime_nofollow_symlinks(utime_t *ut, const char *path)
5340 {
5341 #ifdef HAVE_UTIMENSAT
5342     if (HAVE_UTIMENSAT_RUNTIME) {
5343         UTIME_TO_TIMESPEC;
5344         return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW);
5345     } else
5346 #ifndef HAVE_LUTIMES
5347     {
5348         /* Not sure if this can happen */
5349         PyErr_SetString(
5350             PyExc_RuntimeError,
5351             "neither utimensat nor lutimes are supported"
5352             " on this system");
5353         return -1;
5354     }
5355 #endif
5356 #endif
5357 
5358 #ifdef HAVE_LUTIMES
5359     {
5360     UTIME_TO_TIMEVAL;
5361     return lutimes(path, time);
5362     }
5363 #endif
5364 }
5365 
5366 #endif
5367 
5368 #ifndef MS_WINDOWS
5369 
5370 static int
utime_default(utime_t * ut,const char * path)5371 utime_default(utime_t *ut, const char *path)
5372 {
5373 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5374     if (HAVE_UTIMENSAT_RUNTIME) {
5375         UTIME_TO_TIMESPEC;
5376         return utimensat(DEFAULT_DIR_FD, path, time, 0);
5377     } else {
5378         UTIME_TO_TIMEVAL;
5379         return utimes(path, time);
5380     }
5381 #elif defined(HAVE_UTIMENSAT)
5382     UTIME_TO_TIMESPEC;
5383     return utimensat(DEFAULT_DIR_FD, path, time, 0);
5384 #elif defined(HAVE_UTIMES)
5385     UTIME_TO_TIMEVAL;
5386     return utimes(path, time);
5387 #elif defined(HAVE_UTIME_H)
5388     UTIME_TO_UTIMBUF;
5389     return utime(path, time);
5390 #else
5391     UTIME_TO_TIME_T;
5392     return utime(path, time);
5393 #endif
5394 }
5395 
5396 #endif
5397 
5398 static int
split_py_long_to_s_and_ns(PyObject * module,PyObject * py_long,time_t * s,long * ns)5399 split_py_long_to_s_and_ns(PyObject *module, PyObject *py_long, time_t *s, long *ns)
5400 {
5401     int result = 0;
5402     PyObject *divmod;
5403     divmod = PyNumber_Divmod(py_long, get_posix_state(module)->billion);
5404     if (!divmod)
5405         goto exit;
5406     if (!PyTuple_Check(divmod) || PyTuple_GET_SIZE(divmod) != 2) {
5407         PyErr_Format(PyExc_TypeError,
5408                      "%.200s.__divmod__() must return a 2-tuple, not %.200s",
5409                      _PyType_Name(Py_TYPE(py_long)), _PyType_Name(Py_TYPE(divmod)));
5410         goto exit;
5411     }
5412     *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0));
5413     if ((*s == -1) && PyErr_Occurred())
5414         goto exit;
5415     *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1));
5416     if ((*ns == -1) && PyErr_Occurred())
5417         goto exit;
5418 
5419     result = 1;
5420 exit:
5421     Py_XDECREF(divmod);
5422     return result;
5423 }
5424 
5425 
5426 /*[clinic input]
5427 os.utime
5428 
5429     path: path_t(allow_fd='PATH_UTIME_HAVE_FD')
5430     times: object = None
5431     *
5432     ns: object = NULL
5433     dir_fd: dir_fd(requires='futimensat') = None
5434     follow_symlinks: bool=True
5435 
5436 # "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\
5437 
5438 Set the access and modified time of path.
5439 
5440 path may always be specified as a string.
5441 On some platforms, path may also be specified as an open file descriptor.
5442   If this functionality is unavailable, using it raises an exception.
5443 
5444 If times is not None, it must be a tuple (atime, mtime);
5445     atime and mtime should be expressed as float seconds since the epoch.
5446 If ns is specified, it must be a tuple (atime_ns, mtime_ns);
5447     atime_ns and mtime_ns should be expressed as integer nanoseconds
5448     since the epoch.
5449 If times is None and ns is unspecified, utime uses the current time.
5450 Specifying tuples for both times and ns is an error.
5451 
5452 If dir_fd is not None, it should be a file descriptor open to a directory,
5453   and path should be relative; path will then be relative to that directory.
5454 If follow_symlinks is False, and the last element of the path is a symbolic
5455   link, utime will modify the symbolic link itself instead of the file the
5456   link points to.
5457 It is an error to use dir_fd or follow_symlinks when specifying path
5458   as an open file descriptor.
5459 dir_fd and follow_symlinks may not be available on your platform.
5460   If they are unavailable, using them will raise a NotImplementedError.
5461 
5462 [clinic start generated code]*/
5463 
5464 static PyObject *
os_utime_impl(PyObject * module,path_t * path,PyObject * times,PyObject * ns,int dir_fd,int follow_symlinks)5465 os_utime_impl(PyObject *module, path_t *path, PyObject *times, PyObject *ns,
5466               int dir_fd, int follow_symlinks)
5467 /*[clinic end generated code: output=cfcac69d027b82cf input=2fbd62a2f228f8f4]*/
5468 {
5469 #ifdef MS_WINDOWS
5470     HANDLE hFile;
5471     FILETIME atime, mtime;
5472 #else
5473     int result;
5474 #endif
5475 
5476     utime_t utime;
5477 
5478     memset(&utime, 0, sizeof(utime_t));
5479 
5480     if (times != Py_None && ns) {
5481         PyErr_SetString(PyExc_ValueError,
5482                      "utime: you may specify either 'times'"
5483                      " or 'ns' but not both");
5484         return NULL;
5485     }
5486 
5487     if (times != Py_None) {
5488         time_t a_sec, m_sec;
5489         long a_nsec, m_nsec;
5490         if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) {
5491             PyErr_SetString(PyExc_TypeError,
5492                          "utime: 'times' must be either"
5493                          " a tuple of two ints or None");
5494             return NULL;
5495         }
5496         utime.now = 0;
5497         if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
5498                                      &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 ||
5499             _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
5500                                      &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) {
5501             return NULL;
5502         }
5503         utime.atime_s = a_sec;
5504         utime.atime_ns = a_nsec;
5505         utime.mtime_s = m_sec;
5506         utime.mtime_ns = m_nsec;
5507     }
5508     else if (ns) {
5509         if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) {
5510             PyErr_SetString(PyExc_TypeError,
5511                          "utime: 'ns' must be a tuple of two ints");
5512             return NULL;
5513         }
5514         utime.now = 0;
5515         if (!split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 0),
5516                                       &utime.atime_s, &utime.atime_ns) ||
5517             !split_py_long_to_s_and_ns(module, PyTuple_GET_ITEM(ns, 1),
5518                                        &utime.mtime_s, &utime.mtime_ns)) {
5519             return NULL;
5520         }
5521     }
5522     else {
5523         /* times and ns are both None/unspecified. use "now". */
5524         utime.now = 1;
5525     }
5526 
5527 #if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS)
5528     if (follow_symlinks_specified("utime", follow_symlinks))
5529         return NULL;
5530 #endif
5531 
5532     if (path_and_dir_fd_invalid("utime", path, dir_fd) ||
5533         dir_fd_and_fd_invalid("utime", dir_fd, path->fd) ||
5534         fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks))
5535         return NULL;
5536 
5537 #if !defined(HAVE_UTIMENSAT)
5538     if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) {
5539         PyErr_SetString(PyExc_ValueError,
5540                      "utime: cannot use dir_fd and follow_symlinks "
5541                      "together on this platform");
5542         return NULL;
5543     }
5544 #endif
5545 
5546     if (PySys_Audit("os.utime", "OOOi", path->object, times, ns ? ns : Py_None,
5547                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
5548         return NULL;
5549     }
5550 
5551 #ifdef MS_WINDOWS
5552     Py_BEGIN_ALLOW_THREADS
5553     hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0,
5554                         NULL, OPEN_EXISTING,
5555                         FILE_FLAG_BACKUP_SEMANTICS, NULL);
5556     Py_END_ALLOW_THREADS
5557     if (hFile == INVALID_HANDLE_VALUE) {
5558         path_error(path);
5559         return NULL;
5560     }
5561 
5562     if (utime.now) {
5563         GetSystemTimeAsFileTime(&mtime);
5564         atime = mtime;
5565     }
5566     else {
5567         _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime);
5568         _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime);
5569     }
5570     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
5571         /* Avoid putting the file name into the error here,
5572            as that may confuse the user into believing that
5573            something is wrong with the file, when it also
5574            could be the time stamp that gives a problem. */
5575         PyErr_SetFromWindowsErr(0);
5576         CloseHandle(hFile);
5577         return NULL;
5578     }
5579     CloseHandle(hFile);
5580 #else /* MS_WINDOWS */
5581     Py_BEGIN_ALLOW_THREADS
5582 
5583 #ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS
5584     if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD))
5585         result = utime_nofollow_symlinks(&utime, path->narrow);
5586     else
5587 #endif
5588 
5589 #if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)
5590     if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) {
5591         result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks);
5592 
5593     } else
5594 #endif
5595 
5596 #if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)
5597     if (path->fd != -1)
5598         result = utime_fd(&utime, path->fd);
5599     else
5600 #endif
5601 
5602     result = utime_default(&utime, path->narrow);
5603 
5604     Py_END_ALLOW_THREADS
5605 
5606 #if defined(__APPLE__) && defined(HAVE_UTIMENSAT)
5607     /* See utime_dir_fd implementation */
5608     if (result == -1 && errno == ENOSYS) {
5609         argument_unavailable_error(NULL, "dir_fd");
5610         return NULL;
5611     }
5612 #endif
5613 
5614     if (result < 0) {
5615         /* see previous comment about not putting filename in error here */
5616         posix_error();
5617         return NULL;
5618     }
5619 
5620 #endif /* MS_WINDOWS */
5621 
5622     Py_RETURN_NONE;
5623 }
5624 
5625 /* Process operations */
5626 
5627 
5628 /*[clinic input]
5629 os._exit
5630 
5631     status: int
5632 
5633 Exit to the system with specified status, without normal exit processing.
5634 [clinic start generated code]*/
5635 
5636 static PyObject *
os__exit_impl(PyObject * module,int status)5637 os__exit_impl(PyObject *module, int status)
5638 /*[clinic end generated code: output=116e52d9c2260d54 input=5e6d57556b0c4a62]*/
5639 {
5640     _exit(status);
5641     return NULL; /* Make gcc -Wall happy */
5642 }
5643 
5644 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5645 #define EXECV_CHAR wchar_t
5646 #else
5647 #define EXECV_CHAR char
5648 #endif
5649 
5650 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined(HAVE_RTPSPAWN)
5651 static void
free_string_array(EXECV_CHAR ** array,Py_ssize_t count)5652 free_string_array(EXECV_CHAR **array, Py_ssize_t count)
5653 {
5654     Py_ssize_t i;
5655     for (i = 0; i < count; i++)
5656         PyMem_Free(array[i]);
5657     PyMem_Free(array);
5658 }
5659 
5660 static int
fsconvert_strdup(PyObject * o,EXECV_CHAR ** out)5661 fsconvert_strdup(PyObject *o, EXECV_CHAR **out)
5662 {
5663     Py_ssize_t size;
5664     PyObject *ub;
5665     int result = 0;
5666 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5667     if (!PyUnicode_FSDecoder(o, &ub))
5668         return 0;
5669     *out = PyUnicode_AsWideCharString(ub, &size);
5670     if (*out)
5671         result = 1;
5672 #else
5673     if (!PyUnicode_FSConverter(o, &ub))
5674         return 0;
5675     size = PyBytes_GET_SIZE(ub);
5676     *out = PyMem_Malloc(size + 1);
5677     if (*out) {
5678         memcpy(*out, PyBytes_AS_STRING(ub), size + 1);
5679         result = 1;
5680     } else
5681         PyErr_NoMemory();
5682 #endif
5683     Py_DECREF(ub);
5684     return result;
5685 }
5686 #endif
5687 
5688 #if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined(HAVE_RTPSPAWN)
5689 static EXECV_CHAR**
parse_envlist(PyObject * env,Py_ssize_t * envc_ptr)5690 parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
5691 {
5692     Py_ssize_t i, pos, envc;
5693     PyObject *keys=NULL, *vals=NULL;
5694     PyObject *key, *val, *key2, *val2, *keyval;
5695     EXECV_CHAR **envlist;
5696 
5697     i = PyMapping_Size(env);
5698     if (i < 0)
5699         return NULL;
5700     envlist = PyMem_NEW(EXECV_CHAR *, i + 1);
5701     if (envlist == NULL) {
5702         PyErr_NoMemory();
5703         return NULL;
5704     }
5705     envc = 0;
5706     keys = PyMapping_Keys(env);
5707     if (!keys)
5708         goto error;
5709     vals = PyMapping_Values(env);
5710     if (!vals)
5711         goto error;
5712     if (!PyList_Check(keys) || !PyList_Check(vals)) {
5713         PyErr_Format(PyExc_TypeError,
5714                      "env.keys() or env.values() is not a list");
5715         goto error;
5716     }
5717 
5718     for (pos = 0; pos < i; pos++) {
5719         key = PyList_GetItem(keys, pos);
5720         val = PyList_GetItem(vals, pos);
5721         if (!key || !val)
5722             goto error;
5723 
5724 #if defined(HAVE_WEXECV) || defined(HAVE_WSPAWNV)
5725         if (!PyUnicode_FSDecoder(key, &key2))
5726             goto error;
5727         if (!PyUnicode_FSDecoder(val, &val2)) {
5728             Py_DECREF(key2);
5729             goto error;
5730         }
5731         /* Search from index 1 because on Windows starting '=' is allowed for
5732            defining hidden environment variables. */
5733         if (PyUnicode_GET_LENGTH(key2) == 0 ||
5734             PyUnicode_FindChar(key2, '=', 1, PyUnicode_GET_LENGTH(key2), 1) != -1)
5735         {
5736             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5737             Py_DECREF(key2);
5738             Py_DECREF(val2);
5739             goto error;
5740         }
5741         keyval = PyUnicode_FromFormat("%U=%U", key2, val2);
5742 #else
5743         if (!PyUnicode_FSConverter(key, &key2))
5744             goto error;
5745         if (!PyUnicode_FSConverter(val, &val2)) {
5746             Py_DECREF(key2);
5747             goto error;
5748         }
5749         if (PyBytes_GET_SIZE(key2) == 0 ||
5750             strchr(PyBytes_AS_STRING(key2) + 1, '=') != NULL)
5751         {
5752             PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
5753             Py_DECREF(key2);
5754             Py_DECREF(val2);
5755             goto error;
5756         }
5757         keyval = PyBytes_FromFormat("%s=%s", PyBytes_AS_STRING(key2),
5758                                              PyBytes_AS_STRING(val2));
5759 #endif
5760         Py_DECREF(key2);
5761         Py_DECREF(val2);
5762         if (!keyval)
5763             goto error;
5764 
5765         if (!fsconvert_strdup(keyval, &envlist[envc++])) {
5766             Py_DECREF(keyval);
5767             goto error;
5768         }
5769 
5770         Py_DECREF(keyval);
5771     }
5772     Py_DECREF(vals);
5773     Py_DECREF(keys);
5774 
5775     envlist[envc] = 0;
5776     *envc_ptr = envc;
5777     return envlist;
5778 
5779 error:
5780     Py_XDECREF(keys);
5781     Py_XDECREF(vals);
5782     free_string_array(envlist, envc);
5783     return NULL;
5784 }
5785 
5786 static EXECV_CHAR**
parse_arglist(PyObject * argv,Py_ssize_t * argc)5787 parse_arglist(PyObject* argv, Py_ssize_t *argc)
5788 {
5789     int i;
5790     EXECV_CHAR **argvlist = PyMem_NEW(EXECV_CHAR *, *argc+1);
5791     if (argvlist == NULL) {
5792         PyErr_NoMemory();
5793         return NULL;
5794     }
5795     for (i = 0; i < *argc; i++) {
5796         PyObject* item = PySequence_ITEM(argv, i);
5797         if (item == NULL)
5798             goto fail;
5799         if (!fsconvert_strdup(item, &argvlist[i])) {
5800             Py_DECREF(item);
5801             goto fail;
5802         }
5803         Py_DECREF(item);
5804     }
5805     argvlist[*argc] = NULL;
5806     return argvlist;
5807 fail:
5808     *argc = i;
5809     free_string_array(argvlist, *argc);
5810     return NULL;
5811 }
5812 
5813 #endif
5814 
5815 
5816 #ifdef HAVE_EXECV
5817 /*[clinic input]
5818 os.execv
5819 
5820     path: path_t
5821         Path of executable file.
5822     argv: object
5823         Tuple or list of strings.
5824     /
5825 
5826 Execute an executable path with arguments, replacing current process.
5827 [clinic start generated code]*/
5828 
5829 static PyObject *
os_execv_impl(PyObject * module,path_t * path,PyObject * argv)5830 os_execv_impl(PyObject *module, path_t *path, PyObject *argv)
5831 /*[clinic end generated code: output=3b52fec34cd0dafd input=9bac31efae07dac7]*/
5832 {
5833     EXECV_CHAR **argvlist;
5834     Py_ssize_t argc;
5835 
5836     /* execv has two arguments: (path, argv), where
5837        argv is a list or tuple of strings. */
5838 
5839     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5840         PyErr_SetString(PyExc_TypeError,
5841                         "execv() arg 2 must be a tuple or list");
5842         return NULL;
5843     }
5844     argc = PySequence_Size(argv);
5845     if (argc < 1) {
5846         PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
5847         return NULL;
5848     }
5849 
5850     argvlist = parse_arglist(argv, &argc);
5851     if (argvlist == NULL) {
5852         return NULL;
5853     }
5854     if (!argvlist[0][0]) {
5855         PyErr_SetString(PyExc_ValueError,
5856             "execv() arg 2 first element cannot be empty");
5857         free_string_array(argvlist, argc);
5858         return NULL;
5859     }
5860 
5861     if (PySys_Audit("os.exec", "OOO", path->object, argv, Py_None) < 0) {
5862         free_string_array(argvlist, argc);
5863         return NULL;
5864     }
5865 
5866     _Py_BEGIN_SUPPRESS_IPH
5867 #ifdef HAVE_WEXECV
5868     _wexecv(path->wide, argvlist);
5869 #else
5870     execv(path->narrow, argvlist);
5871 #endif
5872     _Py_END_SUPPRESS_IPH
5873 
5874     /* If we get here it's definitely an error */
5875 
5876     free_string_array(argvlist, argc);
5877     return posix_error();
5878 }
5879 
5880 
5881 /*[clinic input]
5882 os.execve
5883 
5884     path: path_t(allow_fd='PATH_HAVE_FEXECVE')
5885         Path of executable file.
5886     argv: object
5887         Tuple or list of strings.
5888     env: object
5889         Dictionary of strings mapping to strings.
5890 
5891 Execute an executable path with arguments, replacing current process.
5892 [clinic start generated code]*/
5893 
5894 static PyObject *
os_execve_impl(PyObject * module,path_t * path,PyObject * argv,PyObject * env)5895 os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env)
5896 /*[clinic end generated code: output=ff9fa8e4da8bde58 input=626804fa092606d9]*/
5897 {
5898     EXECV_CHAR **argvlist = NULL;
5899     EXECV_CHAR **envlist;
5900     Py_ssize_t argc, envc;
5901 
5902     /* execve has three arguments: (path, argv, env), where
5903        argv is a list or tuple of strings and env is a dictionary
5904        like posix.environ. */
5905 
5906     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
5907         PyErr_SetString(PyExc_TypeError,
5908                         "execve: argv must be a tuple or list");
5909         goto fail_0;
5910     }
5911     argc = PySequence_Size(argv);
5912     if (argc < 1) {
5913         PyErr_SetString(PyExc_ValueError, "execve: argv must not be empty");
5914         return NULL;
5915     }
5916 
5917     if (!PyMapping_Check(env)) {
5918         PyErr_SetString(PyExc_TypeError,
5919                         "execve: environment must be a mapping object");
5920         goto fail_0;
5921     }
5922 
5923     argvlist = parse_arglist(argv, &argc);
5924     if (argvlist == NULL) {
5925         goto fail_0;
5926     }
5927     if (!argvlist[0][0]) {
5928         PyErr_SetString(PyExc_ValueError,
5929             "execve: argv first element cannot be empty");
5930         goto fail_0;
5931     }
5932 
5933     envlist = parse_envlist(env, &envc);
5934     if (envlist == NULL)
5935         goto fail_0;
5936 
5937     if (PySys_Audit("os.exec", "OOO", path->object, argv, env) < 0) {
5938         goto fail_1;
5939     }
5940 
5941     _Py_BEGIN_SUPPRESS_IPH
5942 #ifdef HAVE_FEXECVE
5943     if (path->fd > -1)
5944         fexecve(path->fd, argvlist, envlist);
5945     else
5946 #endif
5947 #ifdef HAVE_WEXECV
5948         _wexecve(path->wide, argvlist, envlist);
5949 #else
5950         execve(path->narrow, argvlist, envlist);
5951 #endif
5952     _Py_END_SUPPRESS_IPH
5953 
5954     /* If we get here it's definitely an error */
5955 
5956     posix_path_error(path);
5957   fail_1:
5958     free_string_array(envlist, envc);
5959   fail_0:
5960     if (argvlist)
5961         free_string_array(argvlist, argc);
5962     return NULL;
5963 }
5964 
5965 #endif /* HAVE_EXECV */
5966 
5967 #ifdef HAVE_POSIX_SPAWN
5968 
5969 enum posix_spawn_file_actions_identifier {
5970     POSIX_SPAWN_OPEN,
5971     POSIX_SPAWN_CLOSE,
5972     POSIX_SPAWN_DUP2
5973 };
5974 
5975 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
5976 static int
5977 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res);
5978 #endif
5979 
5980 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)5981 parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpgroup,
5982                         int resetids, int setsid, PyObject *setsigmask,
5983                         PyObject *setsigdef, PyObject *scheduler,
5984                         posix_spawnattr_t *attrp)
5985 {
5986     long all_flags = 0;
5987 
5988     errno = posix_spawnattr_init(attrp);
5989     if (errno) {
5990         posix_error();
5991         return -1;
5992     }
5993 
5994     if (setpgroup) {
5995         pid_t pgid = PyLong_AsPid(setpgroup);
5996         if (pgid == (pid_t)-1 && PyErr_Occurred()) {
5997             goto fail;
5998         }
5999         errno = posix_spawnattr_setpgroup(attrp, pgid);
6000         if (errno) {
6001             posix_error();
6002             goto fail;
6003         }
6004         all_flags |= POSIX_SPAWN_SETPGROUP;
6005     }
6006 
6007     if (resetids) {
6008         all_flags |= POSIX_SPAWN_RESETIDS;
6009     }
6010 
6011     if (setsid) {
6012 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6013         if (HAVE_POSIX_SPAWN_SETSID_RUNTIME) {
6014 #endif
6015 #ifdef POSIX_SPAWN_SETSID
6016         all_flags |= POSIX_SPAWN_SETSID;
6017 #elif defined(POSIX_SPAWN_SETSID_NP)
6018         all_flags |= POSIX_SPAWN_SETSID_NP;
6019 #else
6020         argument_unavailable_error(func_name, "setsid");
6021         return -1;
6022 #endif
6023 
6024 #ifdef HAVE_POSIX_SPAWN_SETSID_RUNTIME
6025         } else {
6026             argument_unavailable_error(func_name, "setsid");
6027             return -1;
6028         }
6029 #endif /* HAVE_POSIX_SPAWN_SETSID_RUNTIME */
6030 
6031     }
6032 
6033 #ifdef HAVE_SIGSET_T
6034    if (setsigmask) {
6035         sigset_t set;
6036         if (!_Py_Sigset_Converter(setsigmask, &set)) {
6037             goto fail;
6038         }
6039         errno = posix_spawnattr_setsigmask(attrp, &set);
6040         if (errno) {
6041             posix_error();
6042             goto fail;
6043         }
6044         all_flags |= POSIX_SPAWN_SETSIGMASK;
6045     }
6046 
6047     if (setsigdef) {
6048         sigset_t set;
6049         if (!_Py_Sigset_Converter(setsigdef, &set)) {
6050             goto fail;
6051         }
6052         errno = posix_spawnattr_setsigdefault(attrp, &set);
6053         if (errno) {
6054             posix_error();
6055             goto fail;
6056         }
6057         all_flags |= POSIX_SPAWN_SETSIGDEF;
6058     }
6059 #else
6060     if (setsigmask || setsigdef) {
6061         PyErr_SetString(PyExc_NotImplementedError,
6062                         "sigset is not supported on this platform");
6063         goto fail;
6064     }
6065 #endif
6066 
6067     if (scheduler) {
6068 #ifdef POSIX_SPAWN_SETSCHEDULER
6069         PyObject *py_schedpolicy;
6070         PyObject *schedparam_obj;
6071         struct sched_param schedparam;
6072 
6073         if (!PyArg_ParseTuple(scheduler, "OO"
6074                         ";A scheduler tuple must have two elements",
6075                         &py_schedpolicy, &schedparam_obj)) {
6076             goto fail;
6077         }
6078         if (!convert_sched_param(module, schedparam_obj, &schedparam)) {
6079             goto fail;
6080         }
6081         if (py_schedpolicy != Py_None) {
6082             int schedpolicy = _PyLong_AsInt(py_schedpolicy);
6083 
6084             if (schedpolicy == -1 && PyErr_Occurred()) {
6085                 goto fail;
6086             }
6087             errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
6088             if (errno) {
6089                 posix_error();
6090                 goto fail;
6091             }
6092             all_flags |= POSIX_SPAWN_SETSCHEDULER;
6093         }
6094         errno = posix_spawnattr_setschedparam(attrp, &schedparam);
6095         if (errno) {
6096             posix_error();
6097             goto fail;
6098         }
6099         all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
6100 #else
6101         PyErr_SetString(PyExc_NotImplementedError,
6102                 "The scheduler option is not supported in this system.");
6103         goto fail;
6104 #endif
6105     }
6106 
6107     errno = posix_spawnattr_setflags(attrp, all_flags);
6108     if (errno) {
6109         posix_error();
6110         goto fail;
6111     }
6112 
6113     return 0;
6114 
6115 fail:
6116     (void)posix_spawnattr_destroy(attrp);
6117     return -1;
6118 }
6119 
6120 static int
parse_file_actions(PyObject * file_actions,posix_spawn_file_actions_t * file_actionsp,PyObject * temp_buffer)6121 parse_file_actions(PyObject *file_actions,
6122                    posix_spawn_file_actions_t *file_actionsp,
6123                    PyObject *temp_buffer)
6124 {
6125     PyObject *seq;
6126     PyObject *file_action = NULL;
6127     PyObject *tag_obj;
6128 
6129     seq = PySequence_Fast(file_actions,
6130                           "file_actions must be a sequence or None");
6131     if (seq == NULL) {
6132         return -1;
6133     }
6134 
6135     errno = posix_spawn_file_actions_init(file_actionsp);
6136     if (errno) {
6137         posix_error();
6138         Py_DECREF(seq);
6139         return -1;
6140     }
6141 
6142     for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) {
6143         file_action = PySequence_Fast_GET_ITEM(seq, i);
6144         Py_INCREF(file_action);
6145         if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) {
6146             PyErr_SetString(PyExc_TypeError,
6147                 "Each file_actions element must be a non-empty tuple");
6148             goto fail;
6149         }
6150         long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0));
6151         if (tag == -1 && PyErr_Occurred()) {
6152             goto fail;
6153         }
6154 
6155         /* Populate the file_actions object */
6156         switch (tag) {
6157             case POSIX_SPAWN_OPEN: {
6158                 int fd, oflag;
6159                 PyObject *path;
6160                 unsigned long mode;
6161                 if (!PyArg_ParseTuple(file_action, "OiO&ik"
6162                         ";A open file_action tuple must have 5 elements",
6163                         &tag_obj, &fd, PyUnicode_FSConverter, &path,
6164                         &oflag, &mode))
6165                 {
6166                     goto fail;
6167                 }
6168                 if (PyList_Append(temp_buffer, path)) {
6169                     Py_DECREF(path);
6170                     goto fail;
6171                 }
6172                 errno = posix_spawn_file_actions_addopen(file_actionsp,
6173                         fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
6174                 Py_DECREF(path);
6175                 if (errno) {
6176                     posix_error();
6177                     goto fail;
6178                 }
6179                 break;
6180             }
6181             case POSIX_SPAWN_CLOSE: {
6182                 int fd;
6183                 if (!PyArg_ParseTuple(file_action, "Oi"
6184                         ";A close file_action tuple must have 2 elements",
6185                         &tag_obj, &fd))
6186                 {
6187                     goto fail;
6188                 }
6189                 errno = posix_spawn_file_actions_addclose(file_actionsp, fd);
6190                 if (errno) {
6191                     posix_error();
6192                     goto fail;
6193                 }
6194                 break;
6195             }
6196             case POSIX_SPAWN_DUP2: {
6197                 int fd1, fd2;
6198                 if (!PyArg_ParseTuple(file_action, "Oii"
6199                         ";A dup2 file_action tuple must have 3 elements",
6200                         &tag_obj, &fd1, &fd2))
6201                 {
6202                     goto fail;
6203                 }
6204                 errno = posix_spawn_file_actions_adddup2(file_actionsp,
6205                                                          fd1, fd2);
6206                 if (errno) {
6207                     posix_error();
6208                     goto fail;
6209                 }
6210                 break;
6211             }
6212             default: {
6213                 PyErr_SetString(PyExc_TypeError,
6214                                 "Unknown file_actions identifier");
6215                 goto fail;
6216             }
6217         }
6218         Py_DECREF(file_action);
6219     }
6220 
6221     Py_DECREF(seq);
6222     return 0;
6223 
6224 fail:
6225     Py_DECREF(seq);
6226     Py_DECREF(file_action);
6227     (void)posix_spawn_file_actions_destroy(file_actionsp);
6228     return -1;
6229 }
6230 
6231 
6232 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)6233 py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *argv,
6234                PyObject *env, PyObject *file_actions,
6235                PyObject *setpgroup, int resetids, int setsid, PyObject *setsigmask,
6236                PyObject *setsigdef, PyObject *scheduler)
6237 {
6238     const char *func_name = use_posix_spawnp ? "posix_spawnp" : "posix_spawn";
6239     EXECV_CHAR **argvlist = NULL;
6240     EXECV_CHAR **envlist = NULL;
6241     posix_spawn_file_actions_t file_actions_buf;
6242     posix_spawn_file_actions_t *file_actionsp = NULL;
6243     posix_spawnattr_t attr;
6244     posix_spawnattr_t *attrp = NULL;
6245     Py_ssize_t argc, envc;
6246     PyObject *result = NULL;
6247     PyObject *temp_buffer = NULL;
6248     pid_t pid;
6249     int err_code;
6250 
6251     /* posix_spawn and posix_spawnp have three arguments: (path, argv, env), where
6252        argv is a list or tuple of strings and env is a dictionary
6253        like posix.environ. */
6254 
6255     if (!PyList_Check(argv) && !PyTuple_Check(argv)) {
6256         PyErr_Format(PyExc_TypeError,
6257                      "%s: argv must be a tuple or list", func_name);
6258         goto exit;
6259     }
6260     argc = PySequence_Size(argv);
6261     if (argc < 1) {
6262         PyErr_Format(PyExc_ValueError,
6263                      "%s: argv must not be empty", func_name);
6264         return NULL;
6265     }
6266 
6267     if (!PyMapping_Check(env)) {
6268         PyErr_Format(PyExc_TypeError,
6269                      "%s: environment must be a mapping object", func_name);
6270         goto exit;
6271     }
6272 
6273     argvlist = parse_arglist(argv, &argc);
6274     if (argvlist == NULL) {
6275         goto exit;
6276     }
6277     if (!argvlist[0][0]) {
6278         PyErr_Format(PyExc_ValueError,
6279                      "%s: argv first element cannot be empty", func_name);
6280         goto exit;
6281     }
6282 
6283     envlist = parse_envlist(env, &envc);
6284     if (envlist == NULL) {
6285         goto exit;
6286     }
6287 
6288     if (file_actions != NULL && file_actions != Py_None) {
6289         /* There is a bug in old versions of glibc that makes some of the
6290          * helper functions for manipulating file actions not copy the provided
6291          * buffers. The problem is that posix_spawn_file_actions_addopen does not
6292          * copy the value of path for some old versions of glibc (<2.20).
6293          * The use of temp_buffer here is a workaround that keeps the
6294          * python objects that own the buffers alive until posix_spawn gets called.
6295          * Check https://bugs.python.org/issue33630 and
6296          * https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
6297         temp_buffer = PyList_New(0);
6298         if (!temp_buffer) {
6299             goto exit;
6300         }
6301         if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
6302             goto exit;
6303         }
6304         file_actionsp = &file_actions_buf;
6305     }
6306 
6307     if (parse_posix_spawn_flags(module, func_name, setpgroup, resetids, setsid,
6308                                 setsigmask, setsigdef, scheduler, &attr)) {
6309         goto exit;
6310     }
6311     attrp = &attr;
6312 
6313     if (PySys_Audit("os.posix_spawn", "OOO", path->object, argv, env) < 0) {
6314         goto exit;
6315     }
6316 
6317     _Py_BEGIN_SUPPRESS_IPH
6318 #ifdef HAVE_POSIX_SPAWNP
6319     if (use_posix_spawnp) {
6320         err_code = posix_spawnp(&pid, path->narrow,
6321                                 file_actionsp, attrp, argvlist, envlist);
6322     }
6323     else
6324 #endif /* HAVE_POSIX_SPAWNP */
6325     {
6326         err_code = posix_spawn(&pid, path->narrow,
6327                                file_actionsp, attrp, argvlist, envlist);
6328     }
6329     _Py_END_SUPPRESS_IPH
6330 
6331     if (err_code) {
6332         errno = err_code;
6333         PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
6334         goto exit;
6335     }
6336 #ifdef _Py_MEMORY_SANITIZER
6337     __msan_unpoison(&pid, sizeof(pid));
6338 #endif
6339     result = PyLong_FromPid(pid);
6340 
6341 exit:
6342     if (file_actionsp) {
6343         (void)posix_spawn_file_actions_destroy(file_actionsp);
6344     }
6345     if (attrp) {
6346         (void)posix_spawnattr_destroy(attrp);
6347     }
6348     if (envlist) {
6349         free_string_array(envlist, envc);
6350     }
6351     if (argvlist) {
6352         free_string_array(argvlist, argc);
6353     }
6354     Py_XDECREF(temp_buffer);
6355     return result;
6356 }
6357 
6358 
6359 /*[clinic input]
6360 
6361 os.posix_spawn
6362     path: path_t
6363         Path of executable file.
6364     argv: object
6365         Tuple or list of strings.
6366     env: object
6367         Dictionary of strings mapping to strings.
6368     /
6369     *
6370     file_actions: object(c_default='NULL') = ()
6371         A sequence of file action tuples.
6372     setpgroup: object = NULL
6373         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6374     resetids: bool(accept={int}) = False
6375         If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
6376     setsid: bool(accept={int}) = False
6377         If the value is `true` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6378     setsigmask: object(c_default='NULL') = ()
6379         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6380     setsigdef: object(c_default='NULL') = ()
6381         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6382     scheduler: object = NULL
6383         A tuple with the scheduler policy (optional) and parameters.
6384 
6385 Execute the program specified by path in a new process.
6386 [clinic start generated code]*/
6387 
6388 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)6389 os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
6390                     PyObject *env, PyObject *file_actions,
6391                     PyObject *setpgroup, int resetids, int setsid,
6392                     PyObject *setsigmask, PyObject *setsigdef,
6393                     PyObject *scheduler)
6394 /*[clinic end generated code: output=14a1098c566bc675 input=8c6305619a00ad04]*/
6395 {
6396     return py_posix_spawn(0, module, path, argv, env, file_actions,
6397                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6398                           scheduler);
6399 }
6400  #endif /* HAVE_POSIX_SPAWN */
6401 
6402 
6403 
6404 #ifdef HAVE_POSIX_SPAWNP
6405 /*[clinic input]
6406 
6407 os.posix_spawnp
6408     path: path_t
6409         Path of executable file.
6410     argv: object
6411         Tuple or list of strings.
6412     env: object
6413         Dictionary of strings mapping to strings.
6414     /
6415     *
6416     file_actions: object(c_default='NULL') = ()
6417         A sequence of file action tuples.
6418     setpgroup: object = NULL
6419         The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
6420     resetids: bool(accept={int}) = False
6421         If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
6422     setsid: bool(accept={int}) = False
6423         If the value is `True` the POSIX_SPAWN_SETSID or POSIX_SPAWN_SETSID_NP will be activated.
6424     setsigmask: object(c_default='NULL') = ()
6425         The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
6426     setsigdef: object(c_default='NULL') = ()
6427         The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
6428     scheduler: object = NULL
6429         A tuple with the scheduler policy (optional) and parameters.
6430 
6431 Execute the program specified by path in a new process.
6432 [clinic start generated code]*/
6433 
6434 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)6435 os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
6436                      PyObject *env, PyObject *file_actions,
6437                      PyObject *setpgroup, int resetids, int setsid,
6438                      PyObject *setsigmask, PyObject *setsigdef,
6439                      PyObject *scheduler)
6440 /*[clinic end generated code: output=7b9aaefe3031238d input=c1911043a22028da]*/
6441 {
6442     return py_posix_spawn(1, module, path, argv, env, file_actions,
6443                           setpgroup, resetids, setsid, setsigmask, setsigdef,
6444                           scheduler);
6445 }
6446 #endif /* HAVE_POSIX_SPAWNP */
6447 
6448 #ifdef HAVE_RTPSPAWN
6449 static intptr_t
_rtp_spawn(int mode,const char * rtpFileName,const char * argv[],const char * envp[])6450 _rtp_spawn(int mode, const char *rtpFileName, const char *argv[],
6451                const char  *envp[])
6452 {
6453      RTP_ID rtpid;
6454      int status;
6455      pid_t res;
6456      int async_err = 0;
6457 
6458      /* Set priority=100 and uStackSize=16 MiB (0x1000000) for new processes.
6459         uStackSize=0 cannot be used, the default stack size is too small for
6460         Python. */
6461      if (envp) {
6462          rtpid = rtpSpawn(rtpFileName, argv, envp,
6463                           100, 0x1000000, 0, VX_FP_TASK);
6464      }
6465      else {
6466          rtpid = rtpSpawn(rtpFileName, argv, (const char **)environ,
6467                           100, 0x1000000, 0, VX_FP_TASK);
6468      }
6469      if ((rtpid != RTP_ID_ERROR) && (mode == _P_WAIT)) {
6470          do {
6471              res = waitpid((pid_t)rtpid, &status, 0);
6472          } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
6473 
6474          if (res < 0)
6475              return RTP_ID_ERROR;
6476          return ((intptr_t)status);
6477      }
6478      return ((intptr_t)rtpid);
6479 }
6480 #endif
6481 
6482 #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)
6483 /*[clinic input]
6484 os.spawnv
6485 
6486     mode: int
6487         Mode of process creation.
6488     path: path_t
6489         Path of executable file.
6490     argv: object
6491         Tuple or list of strings.
6492     /
6493 
6494 Execute the program specified by path in a new process.
6495 [clinic start generated code]*/
6496 
6497 static PyObject *
os_spawnv_impl(PyObject * module,int mode,path_t * path,PyObject * argv)6498 os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv)
6499 /*[clinic end generated code: output=71cd037a9d96b816 input=43224242303291be]*/
6500 {
6501     EXECV_CHAR **argvlist;
6502     int i;
6503     Py_ssize_t argc;
6504     intptr_t spawnval;
6505     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6506 
6507     /* spawnv has three arguments: (mode, path, argv), where
6508        argv is a list or tuple of strings. */
6509 
6510     if (PyList_Check(argv)) {
6511         argc = PyList_Size(argv);
6512         getitem = PyList_GetItem;
6513     }
6514     else if (PyTuple_Check(argv)) {
6515         argc = PyTuple_Size(argv);
6516         getitem = PyTuple_GetItem;
6517     }
6518     else {
6519         PyErr_SetString(PyExc_TypeError,
6520                         "spawnv() arg 2 must be a tuple or list");
6521         return NULL;
6522     }
6523     if (argc == 0) {
6524         PyErr_SetString(PyExc_ValueError,
6525             "spawnv() arg 2 cannot be empty");
6526         return NULL;
6527     }
6528 
6529     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6530     if (argvlist == NULL) {
6531         return PyErr_NoMemory();
6532     }
6533     for (i = 0; i < argc; i++) {
6534         if (!fsconvert_strdup((*getitem)(argv, i),
6535                               &argvlist[i])) {
6536             free_string_array(argvlist, i);
6537             PyErr_SetString(
6538                 PyExc_TypeError,
6539                 "spawnv() arg 2 must contain only strings");
6540             return NULL;
6541         }
6542         if (i == 0 && !argvlist[0][0]) {
6543             free_string_array(argvlist, i + 1);
6544             PyErr_SetString(
6545                 PyExc_ValueError,
6546                 "spawnv() arg 2 first element cannot be empty");
6547             return NULL;
6548         }
6549     }
6550     argvlist[argc] = NULL;
6551 
6552 #if !defined(HAVE_RTPSPAWN)
6553     if (mode == _OLD_P_OVERLAY)
6554         mode = _P_OVERLAY;
6555 #endif
6556 
6557     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv,
6558                     Py_None) < 0) {
6559         free_string_array(argvlist, argc);
6560         return NULL;
6561     }
6562 
6563     Py_BEGIN_ALLOW_THREADS
6564     _Py_BEGIN_SUPPRESS_IPH
6565 #ifdef HAVE_WSPAWNV
6566     spawnval = _wspawnv(mode, path->wide, argvlist);
6567 #elif defined(HAVE_RTPSPAWN)
6568     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist, NULL);
6569 #else
6570     spawnval = _spawnv(mode, path->narrow, argvlist);
6571 #endif
6572     _Py_END_SUPPRESS_IPH
6573     Py_END_ALLOW_THREADS
6574 
6575     free_string_array(argvlist, argc);
6576 
6577     if (spawnval == -1)
6578         return posix_error();
6579     else
6580         return Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6581 }
6582 
6583 /*[clinic input]
6584 os.spawnve
6585 
6586     mode: int
6587         Mode of process creation.
6588     path: path_t
6589         Path of executable file.
6590     argv: object
6591         Tuple or list of strings.
6592     env: object
6593         Dictionary of strings mapping to strings.
6594     /
6595 
6596 Execute the program specified by path in a new process.
6597 [clinic start generated code]*/
6598 
6599 static PyObject *
os_spawnve_impl(PyObject * module,int mode,path_t * path,PyObject * argv,PyObject * env)6600 os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
6601                 PyObject *env)
6602 /*[clinic end generated code: output=30fe85be56fe37ad input=3e40803ee7c4c586]*/
6603 {
6604     EXECV_CHAR **argvlist;
6605     EXECV_CHAR **envlist;
6606     PyObject *res = NULL;
6607     Py_ssize_t argc, i, envc;
6608     intptr_t spawnval;
6609     PyObject *(*getitem)(PyObject *, Py_ssize_t);
6610     Py_ssize_t lastarg = 0;
6611 
6612     /* spawnve has four arguments: (mode, path, argv, env), where
6613        argv is a list or tuple of strings and env is a dictionary
6614        like posix.environ. */
6615 
6616     if (PyList_Check(argv)) {
6617         argc = PyList_Size(argv);
6618         getitem = PyList_GetItem;
6619     }
6620     else if (PyTuple_Check(argv)) {
6621         argc = PyTuple_Size(argv);
6622         getitem = PyTuple_GetItem;
6623     }
6624     else {
6625         PyErr_SetString(PyExc_TypeError,
6626                         "spawnve() arg 2 must be a tuple or list");
6627         goto fail_0;
6628     }
6629     if (argc == 0) {
6630         PyErr_SetString(PyExc_ValueError,
6631             "spawnve() arg 2 cannot be empty");
6632         goto fail_0;
6633     }
6634     if (!PyMapping_Check(env)) {
6635         PyErr_SetString(PyExc_TypeError,
6636                         "spawnve() arg 3 must be a mapping object");
6637         goto fail_0;
6638     }
6639 
6640     argvlist = PyMem_NEW(EXECV_CHAR *, argc+1);
6641     if (argvlist == NULL) {
6642         PyErr_NoMemory();
6643         goto fail_0;
6644     }
6645     for (i = 0; i < argc; i++) {
6646         if (!fsconvert_strdup((*getitem)(argv, i),
6647                               &argvlist[i]))
6648         {
6649             lastarg = i;
6650             goto fail_1;
6651         }
6652         if (i == 0 && !argvlist[0][0]) {
6653             lastarg = i + 1;
6654             PyErr_SetString(
6655                 PyExc_ValueError,
6656                 "spawnv() arg 2 first element cannot be empty");
6657             goto fail_1;
6658         }
6659     }
6660     lastarg = argc;
6661     argvlist[argc] = NULL;
6662 
6663     envlist = parse_envlist(env, &envc);
6664     if (envlist == NULL)
6665         goto fail_1;
6666 
6667 #if !defined(HAVE_RTPSPAWN)
6668     if (mode == _OLD_P_OVERLAY)
6669         mode = _P_OVERLAY;
6670 #endif
6671 
6672     if (PySys_Audit("os.spawn", "iOOO", mode, path->object, argv, env) < 0) {
6673         goto fail_2;
6674     }
6675 
6676     Py_BEGIN_ALLOW_THREADS
6677     _Py_BEGIN_SUPPRESS_IPH
6678 #ifdef HAVE_WSPAWNV
6679     spawnval = _wspawnve(mode, path->wide, argvlist, envlist);
6680 #elif defined(HAVE_RTPSPAWN)
6681     spawnval = _rtp_spawn(mode, path->narrow, (const char **)argvlist,
6682                            (const char **)envlist);
6683 #else
6684     spawnval = _spawnve(mode, path->narrow, argvlist, envlist);
6685 #endif
6686     _Py_END_SUPPRESS_IPH
6687     Py_END_ALLOW_THREADS
6688 
6689     if (spawnval == -1)
6690         (void) posix_error();
6691     else
6692         res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval);
6693 
6694   fail_2:
6695     while (--envc >= 0) {
6696         PyMem_Free(envlist[envc]);
6697     }
6698     PyMem_Free(envlist);
6699   fail_1:
6700     free_string_array(argvlist, lastarg);
6701   fail_0:
6702     return res;
6703 }
6704 
6705 #endif /* HAVE_SPAWNV */
6706 
6707 #ifdef HAVE_FORK
6708 
6709 /* Helper function to validate arguments.
6710    Returns 0 on success.  non-zero on failure with a TypeError raised.
6711    If obj is non-NULL it must be callable.  */
6712 static int
check_null_or_callable(PyObject * obj,const char * obj_name)6713 check_null_or_callable(PyObject *obj, const char* obj_name)
6714 {
6715     if (obj && !PyCallable_Check(obj)) {
6716         PyErr_Format(PyExc_TypeError, "'%s' must be callable, not %s",
6717                      obj_name, _PyType_Name(Py_TYPE(obj)));
6718         return -1;
6719     }
6720     return 0;
6721 }
6722 
6723 /*[clinic input]
6724 os.register_at_fork
6725 
6726     *
6727     before: object=NULL
6728         A callable to be called in the parent before the fork() syscall.
6729     after_in_child: object=NULL
6730         A callable to be called in the child after fork().
6731     after_in_parent: object=NULL
6732         A callable to be called in the parent after fork().
6733 
6734 Register callables to be called when forking a new process.
6735 
6736 'before' callbacks are called in reverse order.
6737 'after_in_child' and 'after_in_parent' callbacks are called in order.
6738 
6739 [clinic start generated code]*/
6740 
6741 static PyObject *
os_register_at_fork_impl(PyObject * module,PyObject * before,PyObject * after_in_child,PyObject * after_in_parent)6742 os_register_at_fork_impl(PyObject *module, PyObject *before,
6743                          PyObject *after_in_child, PyObject *after_in_parent)
6744 /*[clinic end generated code: output=5398ac75e8e97625 input=cd1187aa85d2312e]*/
6745 {
6746     PyInterpreterState *interp;
6747 
6748     if (!before && !after_in_child && !after_in_parent) {
6749         PyErr_SetString(PyExc_TypeError, "At least one argument is required.");
6750         return NULL;
6751     }
6752     if (check_null_or_callable(before, "before") ||
6753         check_null_or_callable(after_in_child, "after_in_child") ||
6754         check_null_or_callable(after_in_parent, "after_in_parent")) {
6755         return NULL;
6756     }
6757     interp = _PyInterpreterState_GET();
6758 
6759     if (register_at_forker(&interp->before_forkers, before)) {
6760         return NULL;
6761     }
6762     if (register_at_forker(&interp->after_forkers_child, after_in_child)) {
6763         return NULL;
6764     }
6765     if (register_at_forker(&interp->after_forkers_parent, after_in_parent)) {
6766         return NULL;
6767     }
6768     Py_RETURN_NONE;
6769 }
6770 #endif /* HAVE_FORK */
6771 
6772 
6773 #ifdef HAVE_FORK1
6774 /*[clinic input]
6775 os.fork1
6776 
6777 Fork a child process with a single multiplexed (i.e., not bound) thread.
6778 
6779 Return 0 to child process and PID of child to parent process.
6780 [clinic start generated code]*/
6781 
6782 static PyObject *
os_fork1_impl(PyObject * module)6783 os_fork1_impl(PyObject *module)
6784 /*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
6785 {
6786     pid_t pid;
6787 
6788     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
6789         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
6790         return NULL;
6791     }
6792     PyOS_BeforeFork();
6793     pid = fork1();
6794     if (pid == 0) {
6795         /* child: this clobbers and resets the import lock. */
6796         PyOS_AfterFork_Child();
6797     } else {
6798         /* parent: release the import lock. */
6799         PyOS_AfterFork_Parent();
6800     }
6801     if (pid == -1)
6802         return posix_error();
6803     return PyLong_FromPid(pid);
6804 }
6805 #endif /* HAVE_FORK1 */
6806 
6807 
6808 #ifdef HAVE_FORK
6809 /*[clinic input]
6810 os.fork
6811 
6812 Fork a child process.
6813 
6814 Return 0 to child process and PID of child to parent process.
6815 [clinic start generated code]*/
6816 
6817 static PyObject *
os_fork_impl(PyObject * module)6818 os_fork_impl(PyObject *module)
6819 /*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
6820 {
6821     pid_t pid;
6822     PyInterpreterState *interp = _PyInterpreterState_GET();
6823     if (interp->config._isolated_interpreter) {
6824         PyErr_SetString(PyExc_RuntimeError,
6825                         "fork not supported for isolated subinterpreters");
6826         return NULL;
6827     }
6828     if (PySys_Audit("os.fork", NULL) < 0) {
6829         return NULL;
6830     }
6831     PyOS_BeforeFork();
6832     pid = fork();
6833     if (pid == 0) {
6834         /* child: this clobbers and resets the import lock. */
6835         PyOS_AfterFork_Child();
6836     } else {
6837         /* parent: release the import lock. */
6838         PyOS_AfterFork_Parent();
6839     }
6840     if (pid == -1)
6841         return posix_error();
6842     return PyLong_FromPid(pid);
6843 }
6844 #endif /* HAVE_FORK */
6845 
6846 
6847 #ifdef HAVE_SCHED_H
6848 #ifdef HAVE_SCHED_GET_PRIORITY_MAX
6849 /*[clinic input]
6850 os.sched_get_priority_max
6851 
6852     policy: int
6853 
6854 Get the maximum scheduling priority for policy.
6855 [clinic start generated code]*/
6856 
6857 static PyObject *
os_sched_get_priority_max_impl(PyObject * module,int policy)6858 os_sched_get_priority_max_impl(PyObject *module, int policy)
6859 /*[clinic end generated code: output=9e465c6e43130521 input=2097b7998eca6874]*/
6860 {
6861     int max;
6862 
6863     max = sched_get_priority_max(policy);
6864     if (max < 0)
6865         return posix_error();
6866     return PyLong_FromLong(max);
6867 }
6868 
6869 
6870 /*[clinic input]
6871 os.sched_get_priority_min
6872 
6873     policy: int
6874 
6875 Get the minimum scheduling priority for policy.
6876 [clinic start generated code]*/
6877 
6878 static PyObject *
os_sched_get_priority_min_impl(PyObject * module,int policy)6879 os_sched_get_priority_min_impl(PyObject *module, int policy)
6880 /*[clinic end generated code: output=7595c1138cc47a6d input=21bc8fa0d70983bf]*/
6881 {
6882     int min = sched_get_priority_min(policy);
6883     if (min < 0)
6884         return posix_error();
6885     return PyLong_FromLong(min);
6886 }
6887 #endif /* HAVE_SCHED_GET_PRIORITY_MAX */
6888 
6889 
6890 #ifdef HAVE_SCHED_SETSCHEDULER
6891 /*[clinic input]
6892 os.sched_getscheduler
6893     pid: pid_t
6894     /
6895 
6896 Get the scheduling policy for the process identified by pid.
6897 
6898 Passing 0 for pid returns the scheduling policy for the calling process.
6899 [clinic start generated code]*/
6900 
6901 static PyObject *
os_sched_getscheduler_impl(PyObject * module,pid_t pid)6902 os_sched_getscheduler_impl(PyObject *module, pid_t pid)
6903 /*[clinic end generated code: output=dce4c0bd3f1b34c8 input=8d99dac505485ac8]*/
6904 {
6905     int policy;
6906 
6907     policy = sched_getscheduler(pid);
6908     if (policy < 0)
6909         return posix_error();
6910     return PyLong_FromLong(policy);
6911 }
6912 #endif /* HAVE_SCHED_SETSCHEDULER */
6913 
6914 
6915 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
6916 /*[clinic input]
6917 class os.sched_param "PyObject *" "SchedParamType"
6918 
6919 @classmethod
6920 os.sched_param.__new__
6921 
6922     sched_priority: object
6923         A scheduling parameter.
6924 
6925 Currently has only one field: sched_priority
6926 [clinic start generated code]*/
6927 
6928 static PyObject *
os_sched_param_impl(PyTypeObject * type,PyObject * sched_priority)6929 os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority)
6930 /*[clinic end generated code: output=48f4067d60f48c13 input=eb42909a2c0e3e6c]*/
6931 {
6932     PyObject *res;
6933 
6934     res = PyStructSequence_New(type);
6935     if (!res)
6936         return NULL;
6937     Py_INCREF(sched_priority);
6938     PyStructSequence_SET_ITEM(res, 0, sched_priority);
6939     return res;
6940 }
6941 
6942 PyDoc_VAR(os_sched_param__doc__);
6943 
6944 static PyStructSequence_Field sched_param_fields[] = {
6945     {"sched_priority", "the scheduling priority"},
6946     {0}
6947 };
6948 
6949 static PyStructSequence_Desc sched_param_desc = {
6950     "sched_param", /* name */
6951     os_sched_param__doc__, /* doc */
6952     sched_param_fields,
6953     1
6954 };
6955 
6956 static int
convert_sched_param(PyObject * module,PyObject * param,struct sched_param * res)6957 convert_sched_param(PyObject *module, PyObject *param, struct sched_param *res)
6958 {
6959     long priority;
6960 
6961     if (!Py_IS_TYPE(param, (PyTypeObject *)get_posix_state(module)->SchedParamType)) {
6962         PyErr_SetString(PyExc_TypeError, "must have a sched_param object");
6963         return 0;
6964     }
6965     priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0));
6966     if (priority == -1 && PyErr_Occurred())
6967         return 0;
6968     if (priority > INT_MAX || priority < INT_MIN) {
6969         PyErr_SetString(PyExc_OverflowError, "sched_priority out of range");
6970         return 0;
6971     }
6972     res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int);
6973     return 1;
6974 }
6975 #endif /* defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) */
6976 
6977 
6978 #ifdef HAVE_SCHED_SETSCHEDULER
6979 /*[clinic input]
6980 os.sched_setscheduler
6981 
6982     pid: pid_t
6983     policy: int
6984     param as param_obj: object
6985     /
6986 
6987 Set the scheduling policy for the process identified by pid.
6988 
6989 If pid is 0, the calling process is changed.
6990 param is an instance of sched_param.
6991 [clinic start generated code]*/
6992 
6993 static PyObject *
os_sched_setscheduler_impl(PyObject * module,pid_t pid,int policy,PyObject * param_obj)6994 os_sched_setscheduler_impl(PyObject *module, pid_t pid, int policy,
6995                            PyObject *param_obj)
6996 /*[clinic end generated code: output=cde27faa55dc993e input=73013d731bd8fbe9]*/
6997 {
6998     struct sched_param param;
6999     if (!convert_sched_param(module, param_obj, &param)) {
7000         return NULL;
7001     }
7002 
7003     /*
7004     ** sched_setscheduler() returns 0 in Linux, but the previous
7005     ** scheduling policy under Solaris/Illumos, and others.
7006     ** On error, -1 is returned in all Operating Systems.
7007     */
7008     if (sched_setscheduler(pid, policy, &param) == -1)
7009         return posix_error();
7010     Py_RETURN_NONE;
7011 }
7012 #endif  /* HAVE_SCHED_SETSCHEDULER*/
7013 
7014 
7015 #ifdef HAVE_SCHED_SETPARAM
7016 /*[clinic input]
7017 os.sched_getparam
7018     pid: pid_t
7019     /
7020 
7021 Returns scheduling parameters for the process identified by pid.
7022 
7023 If pid is 0, returns parameters for the calling process.
7024 Return value is an instance of sched_param.
7025 [clinic start generated code]*/
7026 
7027 static PyObject *
os_sched_getparam_impl(PyObject * module,pid_t pid)7028 os_sched_getparam_impl(PyObject *module, pid_t pid)
7029 /*[clinic end generated code: output=b194e8708dcf2db8 input=18a1ef9c2efae296]*/
7030 {
7031     struct sched_param param;
7032     PyObject *result;
7033     PyObject *priority;
7034 
7035     if (sched_getparam(pid, &param))
7036         return posix_error();
7037     PyObject *SchedParamType = get_posix_state(module)->SchedParamType;
7038     result = PyStructSequence_New((PyTypeObject *)SchedParamType);
7039     if (!result)
7040         return NULL;
7041     priority = PyLong_FromLong(param.sched_priority);
7042     if (!priority) {
7043         Py_DECREF(result);
7044         return NULL;
7045     }
7046     PyStructSequence_SET_ITEM(result, 0, priority);
7047     return result;
7048 }
7049 
7050 
7051 /*[clinic input]
7052 os.sched_setparam
7053     pid: pid_t
7054     param as param_obj: object
7055     /
7056 
7057 Set scheduling parameters for the process identified by pid.
7058 
7059 If pid is 0, sets parameters for the calling process.
7060 param should be an instance of sched_param.
7061 [clinic start generated code]*/
7062 
7063 static PyObject *
os_sched_setparam_impl(PyObject * module,pid_t pid,PyObject * param_obj)7064 os_sched_setparam_impl(PyObject *module, pid_t pid, PyObject *param_obj)
7065 /*[clinic end generated code: output=f19fe020a53741c1 input=27b98337c8b2dcc7]*/
7066 {
7067     struct sched_param param;
7068     if (!convert_sched_param(module, param_obj, &param)) {
7069         return NULL;
7070     }
7071 
7072     if (sched_setparam(pid, &param))
7073         return posix_error();
7074     Py_RETURN_NONE;
7075 }
7076 #endif /* HAVE_SCHED_SETPARAM */
7077 
7078 
7079 #ifdef HAVE_SCHED_RR_GET_INTERVAL
7080 /*[clinic input]
7081 os.sched_rr_get_interval -> double
7082     pid: pid_t
7083     /
7084 
7085 Return the round-robin quantum for the process identified by pid, in seconds.
7086 
7087 Value returned is a float.
7088 [clinic start generated code]*/
7089 
7090 static double
os_sched_rr_get_interval_impl(PyObject * module,pid_t pid)7091 os_sched_rr_get_interval_impl(PyObject *module, pid_t pid)
7092 /*[clinic end generated code: output=7e2d935833ab47dc input=2a973da15cca6fae]*/
7093 {
7094     struct timespec interval;
7095     if (sched_rr_get_interval(pid, &interval)) {
7096         posix_error();
7097         return -1.0;
7098     }
7099 #ifdef _Py_MEMORY_SANITIZER
7100     __msan_unpoison(&interval, sizeof(interval));
7101 #endif
7102     return (double)interval.tv_sec + 1e-9*interval.tv_nsec;
7103 }
7104 #endif /* HAVE_SCHED_RR_GET_INTERVAL */
7105 
7106 
7107 /*[clinic input]
7108 os.sched_yield
7109 
7110 Voluntarily relinquish the CPU.
7111 [clinic start generated code]*/
7112 
7113 static PyObject *
os_sched_yield_impl(PyObject * module)7114 os_sched_yield_impl(PyObject *module)
7115 /*[clinic end generated code: output=902323500f222cac input=e54d6f98189391d4]*/
7116 {
7117     int result;
7118     Py_BEGIN_ALLOW_THREADS
7119     result = sched_yield();
7120     Py_END_ALLOW_THREADS
7121     if (result < 0) {
7122         return posix_error();
7123     }
7124     Py_RETURN_NONE;
7125 }
7126 
7127 #ifdef HAVE_SCHED_SETAFFINITY
7128 /* The minimum number of CPUs allocated in a cpu_set_t */
7129 static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
7130 
7131 /*[clinic input]
7132 os.sched_setaffinity
7133     pid: pid_t
7134     mask : object
7135     /
7136 
7137 Set the CPU affinity of the process identified by pid to mask.
7138 
7139 mask should be an iterable of integers identifying CPUs.
7140 [clinic start generated code]*/
7141 
7142 static PyObject *
os_sched_setaffinity_impl(PyObject * module,pid_t pid,PyObject * mask)7143 os_sched_setaffinity_impl(PyObject *module, pid_t pid, PyObject *mask)
7144 /*[clinic end generated code: output=882d7dd9a229335b input=a0791a597c7085ba]*/
7145 {
7146     int ncpus;
7147     size_t setsize;
7148     cpu_set_t *cpu_set = NULL;
7149     PyObject *iterator = NULL, *item;
7150 
7151     iterator = PyObject_GetIter(mask);
7152     if (iterator == NULL)
7153         return NULL;
7154 
7155     ncpus = NCPUS_START;
7156     setsize = CPU_ALLOC_SIZE(ncpus);
7157     cpu_set = CPU_ALLOC(ncpus);
7158     if (cpu_set == NULL) {
7159         PyErr_NoMemory();
7160         goto error;
7161     }
7162     CPU_ZERO_S(setsize, cpu_set);
7163 
7164     while ((item = PyIter_Next(iterator))) {
7165         long cpu;
7166         if (!PyLong_Check(item)) {
7167             PyErr_Format(PyExc_TypeError,
7168                         "expected an iterator of ints, "
7169                         "but iterator yielded %R",
7170                         Py_TYPE(item));
7171             Py_DECREF(item);
7172             goto error;
7173         }
7174         cpu = PyLong_AsLong(item);
7175         Py_DECREF(item);
7176         if (cpu < 0) {
7177             if (!PyErr_Occurred())
7178                 PyErr_SetString(PyExc_ValueError, "negative CPU number");
7179             goto error;
7180         }
7181         if (cpu > INT_MAX - 1) {
7182             PyErr_SetString(PyExc_OverflowError, "CPU number too large");
7183             goto error;
7184         }
7185         if (cpu >= ncpus) {
7186             /* Grow CPU mask to fit the CPU number */
7187             int newncpus = ncpus;
7188             cpu_set_t *newmask;
7189             size_t newsetsize;
7190             while (newncpus <= cpu) {
7191                 if (newncpus > INT_MAX / 2)
7192                     newncpus = cpu + 1;
7193                 else
7194                     newncpus = newncpus * 2;
7195             }
7196             newmask = CPU_ALLOC(newncpus);
7197             if (newmask == NULL) {
7198                 PyErr_NoMemory();
7199                 goto error;
7200             }
7201             newsetsize = CPU_ALLOC_SIZE(newncpus);
7202             CPU_ZERO_S(newsetsize, newmask);
7203             memcpy(newmask, cpu_set, setsize);
7204             CPU_FREE(cpu_set);
7205             setsize = newsetsize;
7206             cpu_set = newmask;
7207             ncpus = newncpus;
7208         }
7209         CPU_SET_S(cpu, setsize, cpu_set);
7210     }
7211     if (PyErr_Occurred()) {
7212         goto error;
7213     }
7214     Py_CLEAR(iterator);
7215 
7216     if (sched_setaffinity(pid, setsize, cpu_set)) {
7217         posix_error();
7218         goto error;
7219     }
7220     CPU_FREE(cpu_set);
7221     Py_RETURN_NONE;
7222 
7223 error:
7224     if (cpu_set)
7225         CPU_FREE(cpu_set);
7226     Py_XDECREF(iterator);
7227     return NULL;
7228 }
7229 
7230 
7231 /*[clinic input]
7232 os.sched_getaffinity
7233     pid: pid_t
7234     /
7235 
7236 Return the affinity of the process identified by pid (or the current process if zero).
7237 
7238 The affinity is returned as a set of CPU identifiers.
7239 [clinic start generated code]*/
7240 
7241 static PyObject *
os_sched_getaffinity_impl(PyObject * module,pid_t pid)7242 os_sched_getaffinity_impl(PyObject *module, pid_t pid)
7243 /*[clinic end generated code: output=f726f2c193c17a4f input=983ce7cb4a565980]*/
7244 {
7245     int cpu, ncpus, count;
7246     size_t setsize;
7247     cpu_set_t *mask = NULL;
7248     PyObject *res = NULL;
7249 
7250     ncpus = NCPUS_START;
7251     while (1) {
7252         setsize = CPU_ALLOC_SIZE(ncpus);
7253         mask = CPU_ALLOC(ncpus);
7254         if (mask == NULL)
7255             return PyErr_NoMemory();
7256         if (sched_getaffinity(pid, setsize, mask) == 0)
7257             break;
7258         CPU_FREE(mask);
7259         if (errno != EINVAL)
7260             return posix_error();
7261         if (ncpus > INT_MAX / 2) {
7262             PyErr_SetString(PyExc_OverflowError, "could not allocate "
7263                             "a large enough CPU set");
7264             return NULL;
7265         }
7266         ncpus = ncpus * 2;
7267     }
7268 
7269     res = PySet_New(NULL);
7270     if (res == NULL)
7271         goto error;
7272     for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) {
7273         if (CPU_ISSET_S(cpu, setsize, mask)) {
7274             PyObject *cpu_num = PyLong_FromLong(cpu);
7275             --count;
7276             if (cpu_num == NULL)
7277                 goto error;
7278             if (PySet_Add(res, cpu_num)) {
7279                 Py_DECREF(cpu_num);
7280                 goto error;
7281             }
7282             Py_DECREF(cpu_num);
7283         }
7284     }
7285     CPU_FREE(mask);
7286     return res;
7287 
7288 error:
7289     if (mask)
7290         CPU_FREE(mask);
7291     Py_XDECREF(res);
7292     return NULL;
7293 }
7294 
7295 #endif /* HAVE_SCHED_SETAFFINITY */
7296 
7297 #endif /* HAVE_SCHED_H */
7298 
7299 
7300 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
7301 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
7302 #  define DEV_PTY_FILE "/dev/ptc"
7303 #  define HAVE_DEV_PTMX
7304 #else
7305 #  define DEV_PTY_FILE "/dev/ptmx"
7306 #endif
7307 
7308 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX)
7309 #ifdef HAVE_PTY_H
7310 #include <pty.h>
7311 #ifdef HAVE_UTMP_H
7312 #include <utmp.h>
7313 #endif /* HAVE_UTMP_H */
7314 #elif defined(HAVE_LIBUTIL_H)
7315 #include <libutil.h>
7316 #elif defined(HAVE_UTIL_H)
7317 #include <util.h>
7318 #endif /* HAVE_PTY_H */
7319 #ifdef HAVE_STROPTS_H
7320 #include <stropts.h>
7321 #endif
7322 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_LOGIN_TTY) || defined(HAVE_DEV_PTMX) */
7323 
7324 
7325 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7326 /*[clinic input]
7327 os.openpty
7328 
7329 Open a pseudo-terminal.
7330 
7331 Return a tuple of (master_fd, slave_fd) containing open file descriptors
7332 for both the master and slave ends.
7333 [clinic start generated code]*/
7334 
7335 static PyObject *
os_openpty_impl(PyObject * module)7336 os_openpty_impl(PyObject *module)
7337 /*[clinic end generated code: output=98841ce5ec9cef3c input=f3d99fd99e762907]*/
7338 {
7339     int master_fd = -1, slave_fd = -1;
7340 #ifndef HAVE_OPENPTY
7341     char * slave_name;
7342 #endif
7343 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
7344     PyOS_sighandler_t sig_saved;
7345 #if defined(__sun) && defined(__SVR4)
7346     extern char *ptsname(int fildes);
7347 #endif
7348 #endif
7349 
7350 #ifdef HAVE_OPENPTY
7351     if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
7352         goto posix_error;
7353 
7354     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7355         goto error;
7356     if (_Py_set_inheritable(slave_fd, 0, NULL) < 0)
7357         goto error;
7358 
7359 #elif defined(HAVE__GETPTY)
7360     slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
7361     if (slave_name == NULL)
7362         goto posix_error;
7363     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7364         goto error;
7365 
7366     slave_fd = _Py_open(slave_name, O_RDWR);
7367     if (slave_fd < 0)
7368         goto error;
7369 
7370 #else
7371     master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
7372     if (master_fd < 0)
7373         goto posix_error;
7374 
7375     sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
7376 
7377     /* change permission of slave */
7378     if (grantpt(master_fd) < 0) {
7379         PyOS_setsig(SIGCHLD, sig_saved);
7380         goto posix_error;
7381     }
7382 
7383     /* unlock slave */
7384     if (unlockpt(master_fd) < 0) {
7385         PyOS_setsig(SIGCHLD, sig_saved);
7386         goto posix_error;
7387     }
7388 
7389     PyOS_setsig(SIGCHLD, sig_saved);
7390 
7391     slave_name = ptsname(master_fd); /* get name of slave */
7392     if (slave_name == NULL)
7393         goto posix_error;
7394 
7395     slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
7396     if (slave_fd == -1)
7397         goto error;
7398 
7399     if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
7400         goto posix_error;
7401 
7402 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
7403     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
7404     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
7405 #ifndef __hpux
7406     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
7407 #endif /* __hpux */
7408 #endif /* HAVE_CYGWIN */
7409 #endif /* HAVE_OPENPTY */
7410 
7411     return Py_BuildValue("(ii)", master_fd, slave_fd);
7412 
7413 posix_error:
7414     posix_error();
7415 error:
7416     if (master_fd != -1)
7417         close(master_fd);
7418     if (slave_fd != -1)
7419         close(slave_fd);
7420     return NULL;
7421 }
7422 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
7423 
7424 
7425 #if defined(HAVE_SETSID) && defined(TIOCSCTTY)
7426 #define HAVE_FALLBACK_LOGIN_TTY 1
7427 #endif /* defined(HAVE_SETSID) && defined(TIOCSCTTY) */
7428 
7429 #if defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY)
7430 /*[clinic input]
7431 os.login_tty
7432 
7433     fd: fildes
7434     /
7435 
7436 Prepare the tty of which fd is a file descriptor for a new login session.
7437 
7438 Make the calling process a session leader; make the tty the
7439 controlling tty, the stdin, the stdout, and the stderr of the
7440 calling process; close fd.
7441 [clinic start generated code]*/
7442 
7443 static PyObject *
os_login_tty_impl(PyObject * module,int fd)7444 os_login_tty_impl(PyObject *module, int fd)
7445 /*[clinic end generated code: output=495a79911b4cc1bc input=5f298565099903a2]*/
7446 {
7447 #ifdef HAVE_LOGIN_TTY
7448     if (login_tty(fd) == -1) {
7449         return posix_error();
7450     }
7451 #else /* defined(HAVE_FALLBACK_LOGIN_TTY) */
7452     /* Establish a new session. */
7453     if (setsid() == -1) {
7454         return posix_error();
7455     }
7456 
7457     /* The tty becomes the controlling terminal. */
7458     if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) {
7459         return posix_error();
7460     }
7461 
7462     /* The tty becomes stdin/stdout/stderr */
7463     if (dup2(fd, 0) == -1 || dup2(fd, 1) == -1 || dup2(fd, 2) == -1) {
7464         return posix_error();
7465     }
7466     if (fd > 2) {
7467         close(fd);
7468     }
7469 #endif /* HAVE_LOGIN_TTY */
7470     Py_RETURN_NONE;
7471 }
7472 #endif /* defined(HAVE_LOGIN_TTY) || defined(HAVE_FALLBACK_LOGIN_TTY) */
7473 
7474 
7475 #ifdef HAVE_FORKPTY
7476 /*[clinic input]
7477 os.forkpty
7478 
7479 Fork a new process with a new pseudo-terminal as controlling tty.
7480 
7481 Returns a tuple of (pid, master_fd).
7482 Like fork(), return pid of 0 to the child process,
7483 and pid of child to the parent process.
7484 To both, return fd of newly opened pseudo-terminal.
7485 [clinic start generated code]*/
7486 
7487 static PyObject *
os_forkpty_impl(PyObject * module)7488 os_forkpty_impl(PyObject *module)
7489 /*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
7490 {
7491     int master_fd = -1;
7492     pid_t pid;
7493 
7494     if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) {
7495         PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
7496         return NULL;
7497     }
7498     if (PySys_Audit("os.forkpty", NULL) < 0) {
7499         return NULL;
7500     }
7501     PyOS_BeforeFork();
7502     pid = forkpty(&master_fd, NULL, NULL, NULL);
7503     if (pid == 0) {
7504         /* child: this clobbers and resets the import lock. */
7505         PyOS_AfterFork_Child();
7506     } else {
7507         /* parent: release the import lock. */
7508         PyOS_AfterFork_Parent();
7509     }
7510     if (pid == -1) {
7511         return posix_error();
7512     }
7513     return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
7514 }
7515 #endif /* HAVE_FORKPTY */
7516 
7517 
7518 #ifdef HAVE_GETEGID
7519 /*[clinic input]
7520 os.getegid
7521 
7522 Return the current process's effective group id.
7523 [clinic start generated code]*/
7524 
7525 static PyObject *
os_getegid_impl(PyObject * module)7526 os_getegid_impl(PyObject *module)
7527 /*[clinic end generated code: output=67d9be7ac68898a2 input=1596f79ad1107d5d]*/
7528 {
7529     return _PyLong_FromGid(getegid());
7530 }
7531 #endif /* HAVE_GETEGID */
7532 
7533 
7534 #ifdef HAVE_GETEUID
7535 /*[clinic input]
7536 os.geteuid
7537 
7538 Return the current process's effective user id.
7539 [clinic start generated code]*/
7540 
7541 static PyObject *
os_geteuid_impl(PyObject * module)7542 os_geteuid_impl(PyObject *module)
7543 /*[clinic end generated code: output=ea1b60f0d6abb66e input=4644c662d3bd9f19]*/
7544 {
7545     return _PyLong_FromUid(geteuid());
7546 }
7547 #endif /* HAVE_GETEUID */
7548 
7549 
7550 #ifdef HAVE_GETGID
7551 /*[clinic input]
7552 os.getgid
7553 
7554 Return the current process's group id.
7555 [clinic start generated code]*/
7556 
7557 static PyObject *
os_getgid_impl(PyObject * module)7558 os_getgid_impl(PyObject *module)
7559 /*[clinic end generated code: output=4f28ebc9d3e5dfcf input=58796344cd87c0f6]*/
7560 {
7561     return _PyLong_FromGid(getgid());
7562 }
7563 #endif /* HAVE_GETGID */
7564 
7565 
7566 #ifdef HAVE_GETPID
7567 /*[clinic input]
7568 os.getpid
7569 
7570 Return the current process id.
7571 [clinic start generated code]*/
7572 
7573 static PyObject *
os_getpid_impl(PyObject * module)7574 os_getpid_impl(PyObject *module)
7575 /*[clinic end generated code: output=9ea6fdac01ed2b3c input=5a9a00f0ab68aa00]*/
7576 {
7577     return PyLong_FromPid(getpid());
7578 }
7579 #endif /* HAVE_GETPID */
7580 
7581 #ifdef NGROUPS_MAX
7582 #define MAX_GROUPS NGROUPS_MAX
7583 #else
7584     /* defined to be 16 on Solaris7, so this should be a small number */
7585 #define MAX_GROUPS 64
7586 #endif
7587 
7588 #ifdef HAVE_GETGROUPLIST
7589 
7590 #ifdef __APPLE__
7591 /*[clinic input]
7592 os.getgrouplist
7593 
7594     user: str
7595         username to lookup
7596     group as basegid: int
7597         base group id of the user
7598     /
7599 
7600 Returns a list of groups to which a user belongs.
7601 [clinic start generated code]*/
7602 
7603 static PyObject *
os_getgrouplist_impl(PyObject * module,const char * user,int basegid)7604 os_getgrouplist_impl(PyObject *module, const char *user, int basegid)
7605 /*[clinic end generated code: output=6e734697b8c26de0 input=f8d870374b09a490]*/
7606 #else
7607 /*[clinic input]
7608 os.getgrouplist
7609 
7610     user: str
7611         username to lookup
7612     group as basegid: gid_t
7613         base group id of the user
7614     /
7615 
7616 Returns a list of groups to which a user belongs.
7617 [clinic start generated code]*/
7618 
7619 static PyObject *
7620 os_getgrouplist_impl(PyObject *module, const char *user, gid_t basegid)
7621 /*[clinic end generated code: output=0ebd7fb70115575b input=cc61d5c20b08958d]*/
7622 #endif
7623 {
7624     int i, ngroups;
7625     PyObject *list;
7626 #ifdef __APPLE__
7627     int *groups;
7628 #else
7629     gid_t *groups;
7630 #endif
7631 
7632     /*
7633      * NGROUPS_MAX is defined by POSIX.1 as the maximum
7634      * number of supplimental groups a users can belong to.
7635      * We have to increment it by one because
7636      * getgrouplist() returns both the supplemental groups
7637      * and the primary group, i.e. all of the groups the
7638      * user belongs to.
7639      */
7640     ngroups = 1 + MAX_GROUPS;
7641 
7642     while (1) {
7643 #ifdef __APPLE__
7644         groups = PyMem_New(int, ngroups);
7645 #else
7646         groups = PyMem_New(gid_t, ngroups);
7647 #endif
7648         if (groups == NULL) {
7649             return PyErr_NoMemory();
7650         }
7651 
7652         int old_ngroups = ngroups;
7653         if (getgrouplist(user, basegid, groups, &ngroups) != -1) {
7654             /* Success */
7655             break;
7656         }
7657 
7658         /* getgrouplist() fails if the group list is too small */
7659         PyMem_Free(groups);
7660 
7661         if (ngroups > old_ngroups) {
7662             /* If the group list is too small, the glibc implementation of
7663                getgrouplist() sets ngroups to the total number of groups and
7664                returns -1. */
7665         }
7666         else {
7667             /* Double the group list size */
7668             if (ngroups > INT_MAX / 2) {
7669                 return PyErr_NoMemory();
7670             }
7671             ngroups *= 2;
7672         }
7673 
7674         /* Retry getgrouplist() with a larger group list */
7675     }
7676 
7677 #ifdef _Py_MEMORY_SANITIZER
7678     /* Clang memory sanitizer libc intercepts don't know getgrouplist. */
7679     __msan_unpoison(&ngroups, sizeof(ngroups));
7680     __msan_unpoison(groups, ngroups*sizeof(*groups));
7681 #endif
7682 
7683     list = PyList_New(ngroups);
7684     if (list == NULL) {
7685         PyMem_Free(groups);
7686         return NULL;
7687     }
7688 
7689     for (i = 0; i < ngroups; i++) {
7690 #ifdef __APPLE__
7691         PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]);
7692 #else
7693         PyObject *o = _PyLong_FromGid(groups[i]);
7694 #endif
7695         if (o == NULL) {
7696             Py_DECREF(list);
7697             PyMem_Free(groups);
7698             return NULL;
7699         }
7700         PyList_SET_ITEM(list, i, o);
7701     }
7702 
7703     PyMem_Free(groups);
7704 
7705     return list;
7706 }
7707 #endif /* HAVE_GETGROUPLIST */
7708 
7709 
7710 #ifdef HAVE_GETGROUPS
7711 /*[clinic input]
7712 os.getgroups
7713 
7714 Return list of supplemental group IDs for the process.
7715 [clinic start generated code]*/
7716 
7717 static PyObject *
os_getgroups_impl(PyObject * module)7718 os_getgroups_impl(PyObject *module)
7719 /*[clinic end generated code: output=42b0c17758561b56 input=d3f109412e6a155c]*/
7720 {
7721     // Call getgroups with length 0 to get the actual number of groups
7722     int n = getgroups(0, NULL);
7723     if (n < 0) {
7724         return posix_error();
7725     }
7726 
7727     if (n == 0) {
7728         return PyList_New(0);
7729     }
7730 
7731     gid_t *grouplist = PyMem_New(gid_t, n);
7732     if (grouplist == NULL) {
7733         return PyErr_NoMemory();
7734     }
7735 
7736     n = getgroups(n, grouplist);
7737     if (n == -1) {
7738         PyMem_Free(grouplist);
7739         return posix_error();
7740     }
7741 
7742     PyObject *result = PyList_New(n);
7743     if (result == NULL) {
7744         goto error;
7745     }
7746 
7747     for (int i = 0; i < n; ++i) {
7748         PyObject *group = _PyLong_FromGid(grouplist[i]);
7749         if (group == NULL) {
7750             goto error;
7751         }
7752         PyList_SET_ITEM(result, i, group);
7753     }
7754     PyMem_Free(grouplist);
7755 
7756     return result;
7757 
7758 error:
7759     PyMem_Free(grouplist);
7760     Py_XDECREF(result);
7761     return NULL;
7762 }
7763 #endif /* HAVE_GETGROUPS */
7764 
7765 #ifdef HAVE_INITGROUPS
7766 #ifdef __APPLE__
7767 /*[clinic input]
7768 os.initgroups
7769 
7770     username as oname: FSConverter
7771     gid: int
7772     /
7773 
7774 Initialize the group access list.
7775 
7776 Call the system initgroups() to initialize the group access list with all of
7777 the groups of which the specified username is a member, plus the specified
7778 group id.
7779 [clinic start generated code]*/
7780 
7781 static PyObject *
os_initgroups_impl(PyObject * module,PyObject * oname,int gid)7782 os_initgroups_impl(PyObject *module, PyObject *oname, int gid)
7783 /*[clinic end generated code: output=7f074d30a425fd3a input=df3d54331b0af204]*/
7784 #else
7785 /*[clinic input]
7786 os.initgroups
7787 
7788     username as oname: FSConverter
7789     gid: gid_t
7790     /
7791 
7792 Initialize the group access list.
7793 
7794 Call the system initgroups() to initialize the group access list with all of
7795 the groups of which the specified username is a member, plus the specified
7796 group id.
7797 [clinic start generated code]*/
7798 
7799 static PyObject *
7800 os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
7801 /*[clinic end generated code: output=59341244521a9e3f input=0cb91bdc59a4c564]*/
7802 #endif
7803 {
7804     const char *username = PyBytes_AS_STRING(oname);
7805 
7806     if (initgroups(username, gid) == -1)
7807         return PyErr_SetFromErrno(PyExc_OSError);
7808 
7809     Py_RETURN_NONE;
7810 }
7811 #endif /* HAVE_INITGROUPS */
7812 
7813 
7814 #ifdef HAVE_GETPGID
7815 /*[clinic input]
7816 os.getpgid
7817 
7818     pid: pid_t
7819 
7820 Call the system call getpgid(), and return the result.
7821 [clinic start generated code]*/
7822 
7823 static PyObject *
os_getpgid_impl(PyObject * module,pid_t pid)7824 os_getpgid_impl(PyObject *module, pid_t pid)
7825 /*[clinic end generated code: output=1db95a97be205d18 input=39d710ae3baaf1c7]*/
7826 {
7827     pid_t pgid = getpgid(pid);
7828     if (pgid < 0)
7829         return posix_error();
7830     return PyLong_FromPid(pgid);
7831 }
7832 #endif /* HAVE_GETPGID */
7833 
7834 
7835 #ifdef HAVE_GETPGRP
7836 /*[clinic input]
7837 os.getpgrp
7838 
7839 Return the current process group id.
7840 [clinic start generated code]*/
7841 
7842 static PyObject *
os_getpgrp_impl(PyObject * module)7843 os_getpgrp_impl(PyObject *module)
7844 /*[clinic end generated code: output=c4fc381e51103cf3 input=6846fb2bb9a3705e]*/
7845 {
7846 #ifdef GETPGRP_HAVE_ARG
7847     return PyLong_FromPid(getpgrp(0));
7848 #else /* GETPGRP_HAVE_ARG */
7849     return PyLong_FromPid(getpgrp());
7850 #endif /* GETPGRP_HAVE_ARG */
7851 }
7852 #endif /* HAVE_GETPGRP */
7853 
7854 
7855 #ifdef HAVE_SETPGRP
7856 /*[clinic input]
7857 os.setpgrp
7858 
7859 Make the current process the leader of its process group.
7860 [clinic start generated code]*/
7861 
7862 static PyObject *
os_setpgrp_impl(PyObject * module)7863 os_setpgrp_impl(PyObject *module)
7864 /*[clinic end generated code: output=2554735b0a60f0a0 input=1f0619fcb5731e7e]*/
7865 {
7866 #ifdef SETPGRP_HAVE_ARG
7867     if (setpgrp(0, 0) < 0)
7868 #else /* SETPGRP_HAVE_ARG */
7869     if (setpgrp() < 0)
7870 #endif /* SETPGRP_HAVE_ARG */
7871         return posix_error();
7872     Py_RETURN_NONE;
7873 }
7874 #endif /* HAVE_SETPGRP */
7875 
7876 #ifdef HAVE_GETPPID
7877 
7878 #ifdef MS_WINDOWS
7879 #include <tlhelp32.h>
7880 
7881 static PyObject*
win32_getppid()7882 win32_getppid()
7883 {
7884     HANDLE snapshot;
7885     pid_t mypid;
7886     PyObject* result = NULL;
7887     BOOL have_record;
7888     PROCESSENTRY32 pe;
7889 
7890     mypid = getpid(); /* This function never fails */
7891 
7892     snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
7893     if (snapshot == INVALID_HANDLE_VALUE)
7894         return PyErr_SetFromWindowsErr(GetLastError());
7895 
7896     pe.dwSize = sizeof(pe);
7897     have_record = Process32First(snapshot, &pe);
7898     while (have_record) {
7899         if (mypid == (pid_t)pe.th32ProcessID) {
7900             /* We could cache the ulong value in a static variable. */
7901             result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
7902             break;
7903         }
7904 
7905         have_record = Process32Next(snapshot, &pe);
7906     }
7907 
7908     /* If our loop exits and our pid was not found (result will be NULL)
7909      * then GetLastError will return ERROR_NO_MORE_FILES. This is an
7910      * error anyway, so let's raise it. */
7911     if (!result)
7912         result = PyErr_SetFromWindowsErr(GetLastError());
7913 
7914     CloseHandle(snapshot);
7915 
7916     return result;
7917 }
7918 #endif /*MS_WINDOWS*/
7919 
7920 
7921 /*[clinic input]
7922 os.getppid
7923 
7924 Return the parent's process id.
7925 
7926 If the parent process has already exited, Windows machines will still
7927 return its id; others systems will return the id of the 'init' process (1).
7928 [clinic start generated code]*/
7929 
7930 static PyObject *
os_getppid_impl(PyObject * module)7931 os_getppid_impl(PyObject *module)
7932 /*[clinic end generated code: output=43b2a946a8c603b4 input=e637cb87539c030e]*/
7933 {
7934 #ifdef MS_WINDOWS
7935     return win32_getppid();
7936 #else
7937     return PyLong_FromPid(getppid());
7938 #endif
7939 }
7940 #endif /* HAVE_GETPPID */
7941 
7942 
7943 #ifdef HAVE_GETLOGIN
7944 /*[clinic input]
7945 os.getlogin
7946 
7947 Return the actual login name.
7948 [clinic start generated code]*/
7949 
7950 static PyObject *
os_getlogin_impl(PyObject * module)7951 os_getlogin_impl(PyObject *module)
7952 /*[clinic end generated code: output=a32e66a7e5715dac input=2a21ab1e917163df]*/
7953 {
7954     PyObject *result = NULL;
7955 #ifdef MS_WINDOWS
7956     wchar_t user_name[UNLEN + 1];
7957     DWORD num_chars = Py_ARRAY_LENGTH(user_name);
7958 
7959     if (GetUserNameW(user_name, &num_chars)) {
7960         /* num_chars is the number of unicode chars plus null terminator */
7961         result = PyUnicode_FromWideChar(user_name, num_chars - 1);
7962     }
7963     else
7964         result = PyErr_SetFromWindowsErr(GetLastError());
7965 #else
7966     char *name;
7967     int old_errno = errno;
7968 
7969     errno = 0;
7970     name = getlogin();
7971     if (name == NULL) {
7972         if (errno)
7973             posix_error();
7974         else
7975             PyErr_SetString(PyExc_OSError, "unable to determine login name");
7976     }
7977     else
7978         result = PyUnicode_DecodeFSDefault(name);
7979     errno = old_errno;
7980 #endif
7981     return result;
7982 }
7983 #endif /* HAVE_GETLOGIN */
7984 
7985 
7986 #ifdef HAVE_GETUID
7987 /*[clinic input]
7988 os.getuid
7989 
7990 Return the current process's user id.
7991 [clinic start generated code]*/
7992 
7993 static PyObject *
os_getuid_impl(PyObject * module)7994 os_getuid_impl(PyObject *module)
7995 /*[clinic end generated code: output=415c0b401ebed11a input=b53c8b35f110a516]*/
7996 {
7997     return _PyLong_FromUid(getuid());
7998 }
7999 #endif /* HAVE_GETUID */
8000 
8001 
8002 #ifdef MS_WINDOWS
8003 #define HAVE_KILL
8004 #endif /* MS_WINDOWS */
8005 
8006 #ifdef HAVE_KILL
8007 /*[clinic input]
8008 os.kill
8009 
8010     pid: pid_t
8011     signal: Py_ssize_t
8012     /
8013 
8014 Kill a process with a signal.
8015 [clinic start generated code]*/
8016 
8017 static PyObject *
os_kill_impl(PyObject * module,pid_t pid,Py_ssize_t signal)8018 os_kill_impl(PyObject *module, pid_t pid, Py_ssize_t signal)
8019 /*[clinic end generated code: output=8e346a6701c88568 input=61a36b86ca275ab9]*/
8020 {
8021     if (PySys_Audit("os.kill", "in", pid, signal) < 0) {
8022         return NULL;
8023     }
8024 #ifndef MS_WINDOWS
8025     if (kill(pid, (int)signal) == -1) {
8026         return posix_error();
8027     }
8028 
8029     // Check immediately if the signal was sent to the current process.
8030     // Don't micro-optimize pid == getpid(), since PyErr_SetString() check
8031     // is cheap.
8032     if (PyErr_CheckSignals()) {
8033         return NULL;
8034     }
8035 
8036     Py_RETURN_NONE;
8037 #else /* !MS_WINDOWS */
8038     PyObject *result;
8039     DWORD sig = (DWORD)signal;
8040     DWORD err;
8041     HANDLE handle;
8042 
8043     /* Console processes which share a common console can be sent CTRL+C or
8044        CTRL+BREAK events, provided they handle said events. */
8045     if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
8046         if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) {
8047             err = GetLastError();
8048             PyErr_SetFromWindowsErr(err);
8049         }
8050         else
8051             Py_RETURN_NONE;
8052     }
8053 
8054     /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
8055        attempt to open and terminate the process. */
8056     handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
8057     if (handle == NULL) {
8058         err = GetLastError();
8059         return PyErr_SetFromWindowsErr(err);
8060     }
8061 
8062     if (TerminateProcess(handle, sig) == 0) {
8063         err = GetLastError();
8064         result = PyErr_SetFromWindowsErr(err);
8065     } else {
8066         Py_INCREF(Py_None);
8067         result = Py_None;
8068     }
8069 
8070     CloseHandle(handle);
8071     return result;
8072 #endif /* !MS_WINDOWS */
8073 }
8074 #endif /* HAVE_KILL */
8075 
8076 
8077 #ifdef HAVE_KILLPG
8078 /*[clinic input]
8079 os.killpg
8080 
8081     pgid: pid_t
8082     signal: int
8083     /
8084 
8085 Kill a process group with a signal.
8086 [clinic start generated code]*/
8087 
8088 static PyObject *
os_killpg_impl(PyObject * module,pid_t pgid,int signal)8089 os_killpg_impl(PyObject *module, pid_t pgid, int signal)
8090 /*[clinic end generated code: output=6dbcd2f1fdf5fdba input=38b5449eb8faec19]*/
8091 {
8092     if (PySys_Audit("os.killpg", "ii", pgid, signal) < 0) {
8093         return NULL;
8094     }
8095     /* XXX some man pages make the `pgid` parameter an int, others
8096        a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
8097        take the same type. Moreover, pid_t is always at least as wide as
8098        int (else compilation of this module fails), which is safe. */
8099     if (killpg(pgid, signal) == -1)
8100         return posix_error();
8101     Py_RETURN_NONE;
8102 }
8103 #endif /* HAVE_KILLPG */
8104 
8105 
8106 #ifdef HAVE_PLOCK
8107 #ifdef HAVE_SYS_LOCK_H
8108 #include <sys/lock.h>
8109 #endif
8110 
8111 /*[clinic input]
8112 os.plock
8113     op: int
8114     /
8115 
8116 Lock program segments into memory.");
8117 [clinic start generated code]*/
8118 
8119 static PyObject *
os_plock_impl(PyObject * module,int op)8120 os_plock_impl(PyObject *module, int op)
8121 /*[clinic end generated code: output=81424167033b168e input=e6e5e348e1525f60]*/
8122 {
8123     if (plock(op) == -1)
8124         return posix_error();
8125     Py_RETURN_NONE;
8126 }
8127 #endif /* HAVE_PLOCK */
8128 
8129 
8130 #ifdef HAVE_SETUID
8131 /*[clinic input]
8132 os.setuid
8133 
8134     uid: uid_t
8135     /
8136 
8137 Set the current process's user id.
8138 [clinic start generated code]*/
8139 
8140 static PyObject *
os_setuid_impl(PyObject * module,uid_t uid)8141 os_setuid_impl(PyObject *module, uid_t uid)
8142 /*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
8143 {
8144     if (setuid(uid) < 0)
8145         return posix_error();
8146     Py_RETURN_NONE;
8147 }
8148 #endif /* HAVE_SETUID */
8149 
8150 
8151 #ifdef HAVE_SETEUID
8152 /*[clinic input]
8153 os.seteuid
8154 
8155     euid: uid_t
8156     /
8157 
8158 Set the current process's effective user id.
8159 [clinic start generated code]*/
8160 
8161 static PyObject *
os_seteuid_impl(PyObject * module,uid_t euid)8162 os_seteuid_impl(PyObject *module, uid_t euid)
8163 /*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
8164 {
8165     if (seteuid(euid) < 0)
8166         return posix_error();
8167     Py_RETURN_NONE;
8168 }
8169 #endif /* HAVE_SETEUID */
8170 
8171 
8172 #ifdef HAVE_SETEGID
8173 /*[clinic input]
8174 os.setegid
8175 
8176     egid: gid_t
8177     /
8178 
8179 Set the current process's effective group id.
8180 [clinic start generated code]*/
8181 
8182 static PyObject *
os_setegid_impl(PyObject * module,gid_t egid)8183 os_setegid_impl(PyObject *module, gid_t egid)
8184 /*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
8185 {
8186     if (setegid(egid) < 0)
8187         return posix_error();
8188     Py_RETURN_NONE;
8189 }
8190 #endif /* HAVE_SETEGID */
8191 
8192 
8193 #ifdef HAVE_SETREUID
8194 /*[clinic input]
8195 os.setreuid
8196 
8197     ruid: uid_t
8198     euid: uid_t
8199     /
8200 
8201 Set the current process's real and effective user ids.
8202 [clinic start generated code]*/
8203 
8204 static PyObject *
os_setreuid_impl(PyObject * module,uid_t ruid,uid_t euid)8205 os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
8206 /*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
8207 {
8208     if (setreuid(ruid, euid) < 0) {
8209         return posix_error();
8210     } else {
8211         Py_RETURN_NONE;
8212     }
8213 }
8214 #endif /* HAVE_SETREUID */
8215 
8216 
8217 #ifdef HAVE_SETREGID
8218 /*[clinic input]
8219 os.setregid
8220 
8221     rgid: gid_t
8222     egid: gid_t
8223     /
8224 
8225 Set the current process's real and effective group ids.
8226 [clinic start generated code]*/
8227 
8228 static PyObject *
os_setregid_impl(PyObject * module,gid_t rgid,gid_t egid)8229 os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
8230 /*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
8231 {
8232     if (setregid(rgid, egid) < 0)
8233         return posix_error();
8234     Py_RETURN_NONE;
8235 }
8236 #endif /* HAVE_SETREGID */
8237 
8238 
8239 #ifdef HAVE_SETGID
8240 /*[clinic input]
8241 os.setgid
8242     gid: gid_t
8243     /
8244 
8245 Set the current process's group id.
8246 [clinic start generated code]*/
8247 
8248 static PyObject *
os_setgid_impl(PyObject * module,gid_t gid)8249 os_setgid_impl(PyObject *module, gid_t gid)
8250 /*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
8251 {
8252     if (setgid(gid) < 0)
8253         return posix_error();
8254     Py_RETURN_NONE;
8255 }
8256 #endif /* HAVE_SETGID */
8257 
8258 
8259 #ifdef HAVE_SETGROUPS
8260 /*[clinic input]
8261 os.setgroups
8262 
8263     groups: object
8264     /
8265 
8266 Set the groups of the current process to list.
8267 [clinic start generated code]*/
8268 
8269 static PyObject *
os_setgroups(PyObject * module,PyObject * groups)8270 os_setgroups(PyObject *module, PyObject *groups)
8271 /*[clinic end generated code: output=3fcb32aad58c5ecd input=fa742ca3daf85a7e]*/
8272 {
8273     if (!PySequence_Check(groups)) {
8274         PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
8275         return NULL;
8276     }
8277     Py_ssize_t len = PySequence_Size(groups);
8278     if (len < 0) {
8279         return NULL;
8280     }
8281     if (len > MAX_GROUPS) {
8282         PyErr_SetString(PyExc_ValueError, "too many groups");
8283         return NULL;
8284     }
8285 
8286     gid_t *grouplist = PyMem_New(gid_t, len);
8287     for (Py_ssize_t i = 0; i < len; i++) {
8288         PyObject *elem;
8289         elem = PySequence_GetItem(groups, i);
8290         if (!elem) {
8291             PyMem_Free(grouplist);
8292             return NULL;
8293         }
8294         if (!PyLong_Check(elem)) {
8295             PyErr_SetString(PyExc_TypeError,
8296                             "groups must be integers");
8297             Py_DECREF(elem);
8298             PyMem_Free(grouplist);
8299             return NULL;
8300         } else {
8301             if (!_Py_Gid_Converter(elem, &grouplist[i])) {
8302                 Py_DECREF(elem);
8303                 PyMem_Free(grouplist);
8304                 return NULL;
8305             }
8306         }
8307         Py_DECREF(elem);
8308     }
8309 
8310     if (setgroups(len, grouplist) < 0) {
8311         PyMem_Free(grouplist);
8312         return posix_error();
8313     }
8314     PyMem_Free(grouplist);
8315     Py_RETURN_NONE;
8316 }
8317 #endif /* HAVE_SETGROUPS */
8318 
8319 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
8320 static PyObject *
wait_helper(PyObject * module,pid_t pid,int status,struct rusage * ru)8321 wait_helper(PyObject *module, pid_t pid, int status, struct rusage *ru)
8322 {
8323     PyObject *result;
8324     PyObject *struct_rusage;
8325 
8326     if (pid == -1)
8327         return posix_error();
8328 
8329     // If wait succeeded but no child was ready to report status, ru will not
8330     // have been populated.
8331     if (pid == 0) {
8332         memset(ru, 0, sizeof(*ru));
8333     }
8334 
8335     PyObject *m = PyImport_ImportModule("resource");
8336     if (m == NULL)
8337         return NULL;
8338     struct_rusage = PyObject_GetAttr(m, get_posix_state(module)->struct_rusage);
8339     Py_DECREF(m);
8340     if (struct_rusage == NULL)
8341         return NULL;
8342 
8343     /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
8344     result = PyStructSequence_New((PyTypeObject*) struct_rusage);
8345     Py_DECREF(struct_rusage);
8346     if (!result)
8347         return NULL;
8348 
8349 #ifndef doubletime
8350 #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
8351 #endif
8352 
8353     PyStructSequence_SET_ITEM(result, 0,
8354                               PyFloat_FromDouble(doubletime(ru->ru_utime)));
8355     PyStructSequence_SET_ITEM(result, 1,
8356                               PyFloat_FromDouble(doubletime(ru->ru_stime)));
8357 #define SET_INT(result, index, value)\
8358         PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
8359     SET_INT(result, 2, ru->ru_maxrss);
8360     SET_INT(result, 3, ru->ru_ixrss);
8361     SET_INT(result, 4, ru->ru_idrss);
8362     SET_INT(result, 5, ru->ru_isrss);
8363     SET_INT(result, 6, ru->ru_minflt);
8364     SET_INT(result, 7, ru->ru_majflt);
8365     SET_INT(result, 8, ru->ru_nswap);
8366     SET_INT(result, 9, ru->ru_inblock);
8367     SET_INT(result, 10, ru->ru_oublock);
8368     SET_INT(result, 11, ru->ru_msgsnd);
8369     SET_INT(result, 12, ru->ru_msgrcv);
8370     SET_INT(result, 13, ru->ru_nsignals);
8371     SET_INT(result, 14, ru->ru_nvcsw);
8372     SET_INT(result, 15, ru->ru_nivcsw);
8373 #undef SET_INT
8374 
8375     if (PyErr_Occurred()) {
8376         Py_DECREF(result);
8377         return NULL;
8378     }
8379 
8380     return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
8381 }
8382 #endif /* HAVE_WAIT3 || HAVE_WAIT4 */
8383 
8384 
8385 #ifdef HAVE_WAIT3
8386 /*[clinic input]
8387 os.wait3
8388 
8389     options: int
8390 Wait for completion of a child process.
8391 
8392 Returns a tuple of information about the child process:
8393   (pid, status, rusage)
8394 [clinic start generated code]*/
8395 
8396 static PyObject *
os_wait3_impl(PyObject * module,int options)8397 os_wait3_impl(PyObject *module, int options)
8398 /*[clinic end generated code: output=92c3224e6f28217a input=8ac4c56956b61710]*/
8399 {
8400     pid_t pid;
8401     struct rusage ru;
8402     int async_err = 0;
8403     WAIT_TYPE status;
8404     WAIT_STATUS_INT(status) = 0;
8405 
8406     do {
8407         Py_BEGIN_ALLOW_THREADS
8408         pid = wait3(&status, options, &ru);
8409         Py_END_ALLOW_THREADS
8410     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8411     if (pid < 0)
8412         return (!async_err) ? posix_error() : NULL;
8413 
8414     return wait_helper(module, pid, WAIT_STATUS_INT(status), &ru);
8415 }
8416 #endif /* HAVE_WAIT3 */
8417 
8418 
8419 #ifdef HAVE_WAIT4
8420 /*[clinic input]
8421 
8422 os.wait4
8423 
8424     pid: pid_t
8425     options: int
8426 
8427 Wait for completion of a specific child process.
8428 
8429 Returns a tuple of information about the child process:
8430   (pid, status, rusage)
8431 [clinic start generated code]*/
8432 
8433 static PyObject *
os_wait4_impl(PyObject * module,pid_t pid,int options)8434 os_wait4_impl(PyObject *module, pid_t pid, int options)
8435 /*[clinic end generated code: output=66195aa507b35f70 input=d11deed0750600ba]*/
8436 {
8437     pid_t res;
8438     struct rusage ru;
8439     int async_err = 0;
8440     WAIT_TYPE status;
8441     WAIT_STATUS_INT(status) = 0;
8442 
8443     do {
8444         Py_BEGIN_ALLOW_THREADS
8445         res = wait4(pid, &status, options, &ru);
8446         Py_END_ALLOW_THREADS
8447     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8448     if (res < 0)
8449         return (!async_err) ? posix_error() : NULL;
8450 
8451     return wait_helper(module, res, WAIT_STATUS_INT(status), &ru);
8452 }
8453 #endif /* HAVE_WAIT4 */
8454 
8455 
8456 #if defined(HAVE_WAITID) && !defined(__APPLE__)
8457 /*[clinic input]
8458 os.waitid
8459 
8460     idtype: idtype_t
8461         Must be one of be P_PID, P_PGID or P_ALL.
8462     id: id_t
8463         The id to wait on.
8464     options: int
8465         Constructed from the ORing of one or more of WEXITED, WSTOPPED
8466         or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.
8467     /
8468 
8469 Returns the result of waiting for a process or processes.
8470 
8471 Returns either waitid_result or None if WNOHANG is specified and there are
8472 no children in a waitable state.
8473 [clinic start generated code]*/
8474 
8475 static PyObject *
os_waitid_impl(PyObject * module,idtype_t idtype,id_t id,int options)8476 os_waitid_impl(PyObject *module, idtype_t idtype, id_t id, int options)
8477 /*[clinic end generated code: output=5d2e1c0bde61f4d8 input=d8e7f76e052b7920]*/
8478 {
8479     PyObject *result;
8480     int res;
8481     int async_err = 0;
8482     siginfo_t si;
8483     si.si_pid = 0;
8484 
8485     do {
8486         Py_BEGIN_ALLOW_THREADS
8487         res = waitid(idtype, id, &si, options);
8488         Py_END_ALLOW_THREADS
8489     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8490     if (res < 0)
8491         return (!async_err) ? posix_error() : NULL;
8492 
8493     if (si.si_pid == 0)
8494         Py_RETURN_NONE;
8495 
8496     PyObject *WaitidResultType = get_posix_state(module)->WaitidResultType;
8497     result = PyStructSequence_New((PyTypeObject *)WaitidResultType);
8498     if (!result)
8499         return NULL;
8500 
8501     PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid));
8502     PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid));
8503     PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo)));
8504     PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status)));
8505     PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code)));
8506     if (PyErr_Occurred()) {
8507         Py_DECREF(result);
8508         return NULL;
8509     }
8510 
8511     return result;
8512 }
8513 #endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */
8514 
8515 
8516 #if defined(HAVE_WAITPID)
8517 /*[clinic input]
8518 os.waitpid
8519     pid: pid_t
8520     options: int
8521     /
8522 
8523 Wait for completion of a given child process.
8524 
8525 Returns a tuple of information regarding the child process:
8526     (pid, status)
8527 
8528 The options argument is ignored on Windows.
8529 [clinic start generated code]*/
8530 
8531 static PyObject *
os_waitpid_impl(PyObject * module,pid_t pid,int options)8532 os_waitpid_impl(PyObject *module, pid_t pid, int options)
8533 /*[clinic end generated code: output=5c37c06887a20270 input=0bf1666b8758fda3]*/
8534 {
8535     pid_t res;
8536     int async_err = 0;
8537     WAIT_TYPE status;
8538     WAIT_STATUS_INT(status) = 0;
8539 
8540     do {
8541         Py_BEGIN_ALLOW_THREADS
8542         res = waitpid(pid, &status, options);
8543         Py_END_ALLOW_THREADS
8544     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8545     if (res < 0)
8546         return (!async_err) ? posix_error() : NULL;
8547 
8548     return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status));
8549 }
8550 #elif defined(HAVE_CWAIT)
8551 /* MS C has a variant of waitpid() that's usable for most purposes. */
8552 /*[clinic input]
8553 os.waitpid
8554     pid: intptr_t
8555     options: int
8556     /
8557 
8558 Wait for completion of a given process.
8559 
8560 Returns a tuple of information regarding the process:
8561     (pid, status << 8)
8562 
8563 The options argument is ignored on Windows.
8564 [clinic start generated code]*/
8565 
8566 static PyObject *
os_waitpid_impl(PyObject * module,intptr_t pid,int options)8567 os_waitpid_impl(PyObject *module, intptr_t pid, int options)
8568 /*[clinic end generated code: output=be836b221271d538 input=40f2440c515410f8]*/
8569 {
8570     int status;
8571     intptr_t res;
8572     int async_err = 0;
8573 
8574     do {
8575         Py_BEGIN_ALLOW_THREADS
8576         _Py_BEGIN_SUPPRESS_IPH
8577         res = _cwait(&status, pid, options);
8578         _Py_END_SUPPRESS_IPH
8579         Py_END_ALLOW_THREADS
8580     } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8581     if (res < 0)
8582         return (!async_err) ? posix_error() : NULL;
8583 
8584     unsigned long long ustatus = (unsigned int)status;
8585 
8586     /* shift the status left a byte so this is more like the POSIX waitpid */
8587     return Py_BuildValue(_Py_PARSE_INTPTR "K", res, ustatus << 8);
8588 }
8589 #endif
8590 
8591 
8592 #ifdef HAVE_WAIT
8593 /*[clinic input]
8594 os.wait
8595 
8596 Wait for completion of a child process.
8597 
8598 Returns a tuple of information about the child process:
8599     (pid, status)
8600 [clinic start generated code]*/
8601 
8602 static PyObject *
os_wait_impl(PyObject * module)8603 os_wait_impl(PyObject *module)
8604 /*[clinic end generated code: output=6bc419ac32fb364b input=03b0182d4a4700ce]*/
8605 {
8606     pid_t pid;
8607     int async_err = 0;
8608     WAIT_TYPE status;
8609     WAIT_STATUS_INT(status) = 0;
8610 
8611     do {
8612         Py_BEGIN_ALLOW_THREADS
8613         pid = wait(&status);
8614         Py_END_ALLOW_THREADS
8615     } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
8616     if (pid < 0)
8617         return (!async_err) ? posix_error() : NULL;
8618 
8619     return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
8620 }
8621 #endif /* HAVE_WAIT */
8622 
8623 #if defined(__linux__) && defined(__NR_pidfd_open)
8624 /*[clinic input]
8625 os.pidfd_open
8626   pid: pid_t
8627   flags: unsigned_int = 0
8628 
8629 Return a file descriptor referring to the process *pid*.
8630 
8631 The descriptor can be used to perform process management without races and
8632 signals.
8633 [clinic start generated code]*/
8634 
8635 static PyObject *
os_pidfd_open_impl(PyObject * module,pid_t pid,unsigned int flags)8636 os_pidfd_open_impl(PyObject *module, pid_t pid, unsigned int flags)
8637 /*[clinic end generated code: output=5c7252698947dc41 input=c3fd99ce947ccfef]*/
8638 {
8639     int fd = syscall(__NR_pidfd_open, pid, flags);
8640     if (fd < 0) {
8641         return posix_error();
8642     }
8643     return PyLong_FromLong(fd);
8644 }
8645 #endif
8646 
8647 
8648 #if defined(HAVE_READLINK) || defined(MS_WINDOWS)
8649 /*[clinic input]
8650 os.readlink
8651 
8652     path: path_t
8653     *
8654     dir_fd: dir_fd(requires='readlinkat') = None
8655 
8656 Return a string representing the path to which the symbolic link points.
8657 
8658 If dir_fd is not None, it should be a file descriptor open to a directory,
8659 and path should be relative; path will then be relative to that directory.
8660 
8661 dir_fd may not be implemented on your platform.  If it is unavailable,
8662 using it will raise a NotImplementedError.
8663 [clinic start generated code]*/
8664 
8665 static PyObject *
os_readlink_impl(PyObject * module,path_t * path,int dir_fd)8666 os_readlink_impl(PyObject *module, path_t *path, int dir_fd)
8667 /*[clinic end generated code: output=d21b732a2e814030 input=113c87e0db1ecaf2]*/
8668 {
8669 #if defined(HAVE_READLINK)
8670     char buffer[MAXPATHLEN+1];
8671     ssize_t length;
8672 #ifdef HAVE_READLINKAT
8673     int readlinkat_unavailable = 0;
8674 #endif
8675 
8676     Py_BEGIN_ALLOW_THREADS
8677 #ifdef HAVE_READLINKAT
8678     if (dir_fd != DEFAULT_DIR_FD) {
8679         if (HAVE_READLINKAT_RUNTIME) {
8680             length = readlinkat(dir_fd, path->narrow, buffer, MAXPATHLEN);
8681         } else {
8682             readlinkat_unavailable = 1;
8683         }
8684     } else
8685 #endif
8686         length = readlink(path->narrow, buffer, MAXPATHLEN);
8687     Py_END_ALLOW_THREADS
8688 
8689 #ifdef HAVE_READLINKAT
8690     if (readlinkat_unavailable) {
8691         argument_unavailable_error(NULL, "dir_fd");
8692         return NULL;
8693     }
8694 #endif
8695 
8696     if (length < 0) {
8697         return path_error(path);
8698     }
8699     buffer[length] = '\0';
8700 
8701     if (PyUnicode_Check(path->object))
8702         return PyUnicode_DecodeFSDefaultAndSize(buffer, length);
8703     else
8704         return PyBytes_FromStringAndSize(buffer, length);
8705 #elif defined(MS_WINDOWS)
8706     DWORD n_bytes_returned;
8707     DWORD io_result = 0;
8708     HANDLE reparse_point_handle;
8709     char target_buffer[_Py_MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
8710     _Py_REPARSE_DATA_BUFFER *rdb = (_Py_REPARSE_DATA_BUFFER *)target_buffer;
8711     PyObject *result = NULL;
8712 
8713     /* First get a handle to the reparse point */
8714     Py_BEGIN_ALLOW_THREADS
8715     reparse_point_handle = CreateFileW(
8716         path->wide,
8717         0,
8718         0,
8719         0,
8720         OPEN_EXISTING,
8721         FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
8722         0);
8723     if (reparse_point_handle != INVALID_HANDLE_VALUE) {
8724         /* New call DeviceIoControl to read the reparse point */
8725         io_result = DeviceIoControl(
8726             reparse_point_handle,
8727             FSCTL_GET_REPARSE_POINT,
8728             0, 0, /* in buffer */
8729             target_buffer, sizeof(target_buffer),
8730             &n_bytes_returned,
8731             0 /* we're not using OVERLAPPED_IO */
8732             );
8733         CloseHandle(reparse_point_handle);
8734     }
8735     Py_END_ALLOW_THREADS
8736 
8737     if (io_result == 0) {
8738         return path_error(path);
8739     }
8740 
8741     wchar_t *name = NULL;
8742     Py_ssize_t nameLen = 0;
8743     if (rdb->ReparseTag == IO_REPARSE_TAG_SYMLINK)
8744     {
8745         name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer +
8746                            rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset);
8747         nameLen = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8748     }
8749     else if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)
8750     {
8751         name = (wchar_t *)((char*)rdb->MountPointReparseBuffer.PathBuffer +
8752                            rdb->MountPointReparseBuffer.SubstituteNameOffset);
8753         nameLen = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
8754     }
8755     else
8756     {
8757         PyErr_SetString(PyExc_ValueError, "not a symbolic link");
8758     }
8759     if (name) {
8760         if (nameLen > 4 && wcsncmp(name, L"\\??\\", 4) == 0) {
8761             /* Our buffer is mutable, so this is okay */
8762             name[1] = L'\\';
8763         }
8764         result = PyUnicode_FromWideChar(name, nameLen);
8765         if (result && path->narrow) {
8766             Py_SETREF(result, PyUnicode_EncodeFSDefault(result));
8767         }
8768     }
8769     return result;
8770 #endif
8771 }
8772 #endif /* defined(HAVE_READLINK) || defined(MS_WINDOWS) */
8773 
8774 #if defined(MS_WINDOWS)
8775 
8776 /* Remove the last portion of the path - return 0 on success */
8777 static int
_dirnameW(WCHAR * path)8778 _dirnameW(WCHAR *path)
8779 {
8780     WCHAR *ptr;
8781     size_t length = wcsnlen_s(path, MAX_PATH);
8782     if (length == MAX_PATH) {
8783         return -1;
8784     }
8785 
8786     /* walk the path from the end until a backslash is encountered */
8787     for(ptr = path + length; ptr != path; ptr--) {
8788         if (*ptr == L'\\' || *ptr == L'/') {
8789             break;
8790         }
8791     }
8792     *ptr = 0;
8793     return 0;
8794 }
8795 
8796 #endif
8797 
8798 #ifdef HAVE_SYMLINK
8799 
8800 #if defined(MS_WINDOWS)
8801 
8802 /* Is this path absolute? */
8803 static int
_is_absW(const WCHAR * path)8804 _is_absW(const WCHAR *path)
8805 {
8806     return path[0] == L'\\' || path[0] == L'/' ||
8807         (path[0] && path[1] == L':');
8808 }
8809 
8810 /* join root and rest with a backslash - return 0 on success */
8811 static int
_joinW(WCHAR * dest_path,const WCHAR * root,const WCHAR * rest)8812 _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest)
8813 {
8814     if (_is_absW(rest)) {
8815         return wcscpy_s(dest_path, MAX_PATH, rest);
8816     }
8817 
8818     if (wcscpy_s(dest_path, MAX_PATH, root)) {
8819         return -1;
8820     }
8821 
8822     if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) {
8823         return -1;
8824     }
8825 
8826     return wcscat_s(dest_path, MAX_PATH, rest);
8827 }
8828 
8829 /* Return True if the path at src relative to dest is a directory */
8830 static int
_check_dirW(LPCWSTR src,LPCWSTR dest)8831 _check_dirW(LPCWSTR src, LPCWSTR dest)
8832 {
8833     WIN32_FILE_ATTRIBUTE_DATA src_info;
8834     WCHAR dest_parent[MAX_PATH];
8835     WCHAR src_resolved[MAX_PATH] = L"";
8836 
8837     /* dest_parent = os.path.dirname(dest) */
8838     if (wcscpy_s(dest_parent, MAX_PATH, dest) ||
8839         _dirnameW(dest_parent)) {
8840         return 0;
8841     }
8842     /* src_resolved = os.path.join(dest_parent, src) */
8843     if (_joinW(src_resolved, dest_parent, src)) {
8844         return 0;
8845     }
8846     return (
8847         GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info)
8848         && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
8849     );
8850 }
8851 #endif
8852 
8853 
8854 /*[clinic input]
8855 os.symlink
8856     src: path_t
8857     dst: path_t
8858     target_is_directory: bool = False
8859     *
8860     dir_fd: dir_fd(requires='symlinkat')=None
8861 
8862 # "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\
8863 
8864 Create a symbolic link pointing to src named dst.
8865 
8866 target_is_directory is required on Windows if the target is to be
8867   interpreted as a directory.  (On Windows, symlink requires
8868   Windows 6.0 or greater, and raises a NotImplementedError otherwise.)
8869   target_is_directory is ignored on non-Windows platforms.
8870 
8871 If dir_fd is not None, it should be a file descriptor open to a directory,
8872   and path should be relative; path will then be relative to that directory.
8873 dir_fd may not be implemented on your platform.
8874   If it is unavailable, using it will raise a NotImplementedError.
8875 
8876 [clinic start generated code]*/
8877 
8878 static PyObject *
os_symlink_impl(PyObject * module,path_t * src,path_t * dst,int target_is_directory,int dir_fd)8879 os_symlink_impl(PyObject *module, path_t *src, path_t *dst,
8880                 int target_is_directory, int dir_fd)
8881 /*[clinic end generated code: output=08ca9f3f3cf960f6 input=e820ec4472547bc3]*/
8882 {
8883 #ifdef MS_WINDOWS
8884     DWORD result;
8885     DWORD flags = 0;
8886 
8887     /* Assumed true, set to false if detected to not be available. */
8888     static int windows_has_symlink_unprivileged_flag = TRUE;
8889 #else
8890     int result;
8891 #ifdef HAVE_SYMLINKAT
8892     int symlinkat_unavailable = 0;
8893 #endif
8894 #endif
8895 
8896     if (PySys_Audit("os.symlink", "OOi", src->object, dst->object,
8897                     dir_fd == DEFAULT_DIR_FD ? -1 : dir_fd) < 0) {
8898         return NULL;
8899     }
8900 
8901 #ifdef MS_WINDOWS
8902 
8903     if (windows_has_symlink_unprivileged_flag) {
8904         /* Allow non-admin symlinks if system allows it. */
8905         flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
8906     }
8907 
8908     Py_BEGIN_ALLOW_THREADS
8909     _Py_BEGIN_SUPPRESS_IPH
8910     /* if src is a directory, ensure flags==1 (target_is_directory bit) */
8911     if (target_is_directory || _check_dirW(src->wide, dst->wide)) {
8912         flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
8913     }
8914 
8915     result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8916     _Py_END_SUPPRESS_IPH
8917     Py_END_ALLOW_THREADS
8918 
8919     if (windows_has_symlink_unprivileged_flag && !result &&
8920         ERROR_INVALID_PARAMETER == GetLastError()) {
8921 
8922         Py_BEGIN_ALLOW_THREADS
8923         _Py_BEGIN_SUPPRESS_IPH
8924         /* This error might be caused by
8925         SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE not being supported.
8926         Try again, and update windows_has_symlink_unprivileged_flag if we
8927         are successful this time.
8928 
8929         NOTE: There is a risk of a race condition here if there are other
8930         conditions than the flag causing ERROR_INVALID_PARAMETER, and
8931         another process (or thread) changes that condition in between our
8932         calls to CreateSymbolicLink.
8933         */
8934         flags &= ~(SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE);
8935         result = CreateSymbolicLinkW(dst->wide, src->wide, flags);
8936         _Py_END_SUPPRESS_IPH
8937         Py_END_ALLOW_THREADS
8938 
8939         if (result || ERROR_INVALID_PARAMETER != GetLastError()) {
8940             windows_has_symlink_unprivileged_flag = FALSE;
8941         }
8942     }
8943 
8944     if (!result)
8945         return path_error2(src, dst);
8946 
8947 #else
8948 
8949     if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) {
8950         PyErr_SetString(PyExc_ValueError,
8951             "symlink: src and dst must be the same type");
8952         return NULL;
8953     }
8954 
8955     Py_BEGIN_ALLOW_THREADS
8956 #ifdef HAVE_SYMLINKAT
8957     if (dir_fd != DEFAULT_DIR_FD) {
8958         if (HAVE_SYMLINKAT_RUNTIME) {
8959             result = symlinkat(src->narrow, dir_fd, dst->narrow);
8960         } else {
8961             symlinkat_unavailable = 1;
8962         }
8963     } else
8964 #endif
8965         result = symlink(src->narrow, dst->narrow);
8966     Py_END_ALLOW_THREADS
8967 
8968 #ifdef HAVE_SYMLINKAT
8969     if (symlinkat_unavailable) {
8970           argument_unavailable_error(NULL, "dir_fd");
8971           return NULL;
8972     }
8973 #endif
8974 
8975     if (result)
8976         return path_error2(src, dst);
8977 #endif
8978 
8979     Py_RETURN_NONE;
8980 }
8981 #endif /* HAVE_SYMLINK */
8982 
8983 
8984 
8985 
8986 static PyStructSequence_Field times_result_fields[] = {
8987     {"user",    "user time"},
8988     {"system",   "system time"},
8989     {"children_user",    "user time of children"},
8990     {"children_system",    "system time of children"},
8991     {"elapsed",    "elapsed time since an arbitrary point in the past"},
8992     {NULL}
8993 };
8994 
8995 PyDoc_STRVAR(times_result__doc__,
8996 "times_result: Result from os.times().\n\n\
8997 This object may be accessed either as a tuple of\n\
8998   (user, system, children_user, children_system, elapsed),\n\
8999 or via the attributes user, system, children_user, children_system,\n\
9000 and elapsed.\n\
9001 \n\
9002 See os.times for more information.");
9003 
9004 static PyStructSequence_Desc times_result_desc = {
9005     "times_result", /* name */
9006     times_result__doc__, /* doc */
9007     times_result_fields,
9008     5
9009 };
9010 
9011 #ifdef MS_WINDOWS
9012 #define HAVE_TIMES  /* mandatory, for the method table */
9013 #endif
9014 
9015 #ifdef HAVE_TIMES
9016 
9017 static PyObject *
build_times_result(PyObject * module,double user,double system,double children_user,double children_system,double elapsed)9018 build_times_result(PyObject *module, double user, double system,
9019     double children_user, double children_system,
9020     double elapsed)
9021 {
9022     PyObject *TimesResultType = get_posix_state(module)->TimesResultType;
9023     PyObject *value = PyStructSequence_New((PyTypeObject *)TimesResultType);
9024     if (value == NULL)
9025         return NULL;
9026 
9027 #define SET(i, field) \
9028     { \
9029     PyObject *o = PyFloat_FromDouble(field); \
9030     if (!o) { \
9031         Py_DECREF(value); \
9032         return NULL; \
9033     } \
9034     PyStructSequence_SET_ITEM(value, i, o); \
9035     } \
9036 
9037     SET(0, user);
9038     SET(1, system);
9039     SET(2, children_user);
9040     SET(3, children_system);
9041     SET(4, elapsed);
9042 
9043 #undef SET
9044 
9045     return value;
9046 }
9047 
9048 
9049 #ifndef MS_WINDOWS
9050 #define NEED_TICKS_PER_SECOND
9051 static long ticks_per_second = -1;
9052 #endif /* MS_WINDOWS */
9053 
9054 /*[clinic input]
9055 os.times
9056 
9057 Return a collection containing process timing information.
9058 
9059 The object returned behaves like a named tuple with these fields:
9060   (utime, stime, cutime, cstime, elapsed_time)
9061 All fields are floating point numbers.
9062 [clinic start generated code]*/
9063 
9064 static PyObject *
os_times_impl(PyObject * module)9065 os_times_impl(PyObject *module)
9066 /*[clinic end generated code: output=35f640503557d32a input=2bf9df3d6ab2e48b]*/
9067 #ifdef MS_WINDOWS
9068 {
9069     FILETIME create, exit, kernel, user;
9070     HANDLE hProc;
9071     hProc = GetCurrentProcess();
9072     GetProcessTimes(hProc, &create, &exit, &kernel, &user);
9073     /* The fields of a FILETIME structure are the hi and lo part
9074        of a 64-bit value expressed in 100 nanosecond units.
9075        1e7 is one second in such units; 1e-7 the inverse.
9076        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
9077     */
9078     return build_times_result(module,
9079         (double)(user.dwHighDateTime*429.4967296 +
9080                  user.dwLowDateTime*1e-7),
9081         (double)(kernel.dwHighDateTime*429.4967296 +
9082                  kernel.dwLowDateTime*1e-7),
9083         (double)0,
9084         (double)0,
9085         (double)0);
9086 }
9087 #else /* MS_WINDOWS */
9088 {
9089 
9090 
9091     struct tms t;
9092     clock_t c;
9093     errno = 0;
9094     c = times(&t);
9095     if (c == (clock_t) -1)
9096         return posix_error();
9097     return build_times_result(module,
9098                          (double)t.tms_utime / ticks_per_second,
9099                          (double)t.tms_stime / ticks_per_second,
9100                          (double)t.tms_cutime / ticks_per_second,
9101                          (double)t.tms_cstime / ticks_per_second,
9102                          (double)c / ticks_per_second);
9103 }
9104 #endif /* MS_WINDOWS */
9105 #endif /* HAVE_TIMES */
9106 
9107 
9108 #ifdef HAVE_GETSID
9109 /*[clinic input]
9110 os.getsid
9111 
9112     pid: pid_t
9113     /
9114 
9115 Call the system call getsid(pid) and return the result.
9116 [clinic start generated code]*/
9117 
9118 static PyObject *
os_getsid_impl(PyObject * module,pid_t pid)9119 os_getsid_impl(PyObject *module, pid_t pid)
9120 /*[clinic end generated code: output=112deae56b306460 input=eeb2b923a30ce04e]*/
9121 {
9122     int sid;
9123     sid = getsid(pid);
9124     if (sid < 0)
9125         return posix_error();
9126     return PyLong_FromLong((long)sid);
9127 }
9128 #endif /* HAVE_GETSID */
9129 
9130 
9131 #ifdef HAVE_SETSID
9132 /*[clinic input]
9133 os.setsid
9134 
9135 Call the system call setsid().
9136 [clinic start generated code]*/
9137 
9138 static PyObject *
os_setsid_impl(PyObject * module)9139 os_setsid_impl(PyObject *module)
9140 /*[clinic end generated code: output=e2ddedd517086d77 input=5fff45858e2f0776]*/
9141 {
9142     if (setsid() < 0)
9143         return posix_error();
9144     Py_RETURN_NONE;
9145 }
9146 #endif /* HAVE_SETSID */
9147 
9148 
9149 #ifdef HAVE_SETPGID
9150 /*[clinic input]
9151 os.setpgid
9152 
9153     pid: pid_t
9154     pgrp: pid_t
9155     /
9156 
9157 Call the system call setpgid(pid, pgrp).
9158 [clinic start generated code]*/
9159 
9160 static PyObject *
os_setpgid_impl(PyObject * module,pid_t pid,pid_t pgrp)9161 os_setpgid_impl(PyObject *module, pid_t pid, pid_t pgrp)
9162 /*[clinic end generated code: output=6461160319a43d6a input=fceb395eca572e1a]*/
9163 {
9164     if (setpgid(pid, pgrp) < 0)
9165         return posix_error();
9166     Py_RETURN_NONE;
9167 }
9168 #endif /* HAVE_SETPGID */
9169 
9170 
9171 #ifdef HAVE_TCGETPGRP
9172 /*[clinic input]
9173 os.tcgetpgrp
9174 
9175     fd: int
9176     /
9177 
9178 Return the process group associated with the terminal specified by fd.
9179 [clinic start generated code]*/
9180 
9181 static PyObject *
os_tcgetpgrp_impl(PyObject * module,int fd)9182 os_tcgetpgrp_impl(PyObject *module, int fd)
9183 /*[clinic end generated code: output=f865e88be86c272b input=7f6c18eac10ada86]*/
9184 {
9185     pid_t pgid = tcgetpgrp(fd);
9186     if (pgid < 0)
9187         return posix_error();
9188     return PyLong_FromPid(pgid);
9189 }
9190 #endif /* HAVE_TCGETPGRP */
9191 
9192 
9193 #ifdef HAVE_TCSETPGRP
9194 /*[clinic input]
9195 os.tcsetpgrp
9196 
9197     fd: int
9198     pgid: pid_t
9199     /
9200 
9201 Set the process group associated with the terminal specified by fd.
9202 [clinic start generated code]*/
9203 
9204 static PyObject *
os_tcsetpgrp_impl(PyObject * module,int fd,pid_t pgid)9205 os_tcsetpgrp_impl(PyObject *module, int fd, pid_t pgid)
9206 /*[clinic end generated code: output=f1821a381b9daa39 input=5bdc997c6a619020]*/
9207 {
9208     if (tcsetpgrp(fd, pgid) < 0)
9209         return posix_error();
9210     Py_RETURN_NONE;
9211 }
9212 #endif /* HAVE_TCSETPGRP */
9213 
9214 /* Functions acting on file descriptors */
9215 
9216 #ifdef O_CLOEXEC
9217 extern int _Py_open_cloexec_works;
9218 #endif
9219 
9220 
9221 /*[clinic input]
9222 os.open -> int
9223     path: path_t
9224     flags: int
9225     mode: int = 0o777
9226     *
9227     dir_fd: dir_fd(requires='openat') = None
9228 
9229 # "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\
9230 
9231 Open a file for low level IO.  Returns a file descriptor (integer).
9232 
9233 If dir_fd is not None, it should be a file descriptor open to a directory,
9234   and path should be relative; path will then be relative to that directory.
9235 dir_fd may not be implemented on your platform.
9236   If it is unavailable, using it will raise a NotImplementedError.
9237 [clinic start generated code]*/
9238 
9239 static int
os_open_impl(PyObject * module,path_t * path,int flags,int mode,int dir_fd)9240 os_open_impl(PyObject *module, path_t *path, int flags, int mode, int dir_fd)
9241 /*[clinic end generated code: output=abc7227888c8bc73 input=ad8623b29acd2934]*/
9242 {
9243     int fd;
9244     int async_err = 0;
9245 #ifdef HAVE_OPENAT
9246     int openat_unavailable = 0;
9247 #endif
9248 
9249 #ifdef O_CLOEXEC
9250     int *atomic_flag_works = &_Py_open_cloexec_works;
9251 #elif !defined(MS_WINDOWS)
9252     int *atomic_flag_works = NULL;
9253 #endif
9254 
9255 #ifdef MS_WINDOWS
9256     flags |= O_NOINHERIT;
9257 #elif defined(O_CLOEXEC)
9258     flags |= O_CLOEXEC;
9259 #endif
9260 
9261     if (PySys_Audit("open", "OOi", path->object, Py_None, flags) < 0) {
9262         return -1;
9263     }
9264 
9265     _Py_BEGIN_SUPPRESS_IPH
9266     do {
9267         Py_BEGIN_ALLOW_THREADS
9268 #ifdef MS_WINDOWS
9269         fd = _wopen(path->wide, flags, mode);
9270 #else
9271 #ifdef HAVE_OPENAT
9272         if (dir_fd != DEFAULT_DIR_FD) {
9273             if (HAVE_OPENAT_RUNTIME) {
9274                 fd = openat(dir_fd, path->narrow, flags, mode);
9275 
9276             } else {
9277                 openat_unavailable = 1;
9278                 fd = -1;
9279             }
9280         } else
9281 #endif /* HAVE_OPENAT */
9282             fd = open(path->narrow, flags, mode);
9283 #endif /* !MS_WINDOWS */
9284         Py_END_ALLOW_THREADS
9285     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9286     _Py_END_SUPPRESS_IPH
9287 
9288 #ifdef HAVE_OPENAT
9289     if (openat_unavailable) {
9290         argument_unavailable_error(NULL, "dir_fd");
9291         return -1;
9292     }
9293 #endif
9294 
9295     if (fd < 0) {
9296         if (!async_err)
9297             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object);
9298         return -1;
9299     }
9300 
9301 #ifndef MS_WINDOWS
9302     if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) {
9303         close(fd);
9304         return -1;
9305     }
9306 #endif
9307 
9308     return fd;
9309 }
9310 
9311 
9312 /*[clinic input]
9313 os.close
9314 
9315     fd: int
9316 
9317 Close a file descriptor.
9318 [clinic start generated code]*/
9319 
9320 static PyObject *
os_close_impl(PyObject * module,int fd)9321 os_close_impl(PyObject *module, int fd)
9322 /*[clinic end generated code: output=2fe4e93602822c14 input=2bc42451ca5c3223]*/
9323 {
9324     int res;
9325     /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/
9326      * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
9327      * for more details.
9328      */
9329     Py_BEGIN_ALLOW_THREADS
9330     _Py_BEGIN_SUPPRESS_IPH
9331     res = close(fd);
9332     _Py_END_SUPPRESS_IPH
9333     Py_END_ALLOW_THREADS
9334     if (res < 0)
9335         return posix_error();
9336     Py_RETURN_NONE;
9337 }
9338 
9339 /*[clinic input]
9340 os.closerange
9341 
9342     fd_low: int
9343     fd_high: int
9344     /
9345 
9346 Closes all file descriptors in [fd_low, fd_high), ignoring errors.
9347 [clinic start generated code]*/
9348 
9349 static PyObject *
os_closerange_impl(PyObject * module,int fd_low,int fd_high)9350 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
9351 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
9352 {
9353     Py_BEGIN_ALLOW_THREADS
9354     _Py_closerange(fd_low, fd_high - 1);
9355     Py_END_ALLOW_THREADS
9356     Py_RETURN_NONE;
9357 }
9358 
9359 
9360 /*[clinic input]
9361 os.dup -> int
9362 
9363     fd: int
9364     /
9365 
9366 Return a duplicate of a file descriptor.
9367 [clinic start generated code]*/
9368 
9369 static int
os_dup_impl(PyObject * module,int fd)9370 os_dup_impl(PyObject *module, int fd)
9371 /*[clinic end generated code: output=486f4860636b2a9f input=6f10f7ea97f7852a]*/
9372 {
9373     return _Py_dup(fd);
9374 }
9375 
9376 // dup2() is either provided by libc or dup2.c with AC_REPLACE_FUNCS().
9377 // dup2.c provides working dup2() if and only if F_DUPFD is available.
9378 #if (defined(HAVE_DUP3) || defined(F_DUPFD) || defined(MS_WINDOWS))
9379 /*[clinic input]
9380 os.dup2 -> int
9381     fd: int
9382     fd2: int
9383     inheritable: bool=True
9384 
9385 Duplicate file descriptor.
9386 [clinic start generated code]*/
9387 
9388 static int
os_dup2_impl(PyObject * module,int fd,int fd2,int inheritable)9389 os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable)
9390 /*[clinic end generated code: output=bc059d34a73404d1 input=c3cddda8922b038d]*/
9391 {
9392     int res = 0;
9393 #if defined(HAVE_DUP3) && \
9394     !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC))
9395     /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */
9396     static int dup3_works = -1;
9397 #endif
9398 
9399     /* dup2() can fail with EINTR if the target FD is already open, because it
9400      * then has to be closed. See os_close_impl() for why we don't handle EINTR
9401      * upon close(), and therefore below.
9402      */
9403 #ifdef MS_WINDOWS
9404     Py_BEGIN_ALLOW_THREADS
9405     _Py_BEGIN_SUPPRESS_IPH
9406     res = dup2(fd, fd2);
9407     _Py_END_SUPPRESS_IPH
9408     Py_END_ALLOW_THREADS
9409     if (res < 0) {
9410         posix_error();
9411         return -1;
9412     }
9413     res = fd2; // msvcrt dup2 returns 0 on success.
9414 
9415     /* Character files like console cannot be make non-inheritable */
9416     if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9417         close(fd2);
9418         return -1;
9419     }
9420 
9421 #elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)
9422     Py_BEGIN_ALLOW_THREADS
9423     if (!inheritable)
9424         res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2);
9425     else
9426         res = dup2(fd, fd2);
9427     Py_END_ALLOW_THREADS
9428     if (res < 0) {
9429         posix_error();
9430         return -1;
9431     }
9432 
9433 #else
9434 
9435 #ifdef HAVE_DUP3
9436     if (!inheritable && dup3_works != 0) {
9437         Py_BEGIN_ALLOW_THREADS
9438         res = dup3(fd, fd2, O_CLOEXEC);
9439         Py_END_ALLOW_THREADS
9440         if (res < 0) {
9441             if (dup3_works == -1)
9442                 dup3_works = (errno != ENOSYS);
9443             if (dup3_works) {
9444                 posix_error();
9445                 return -1;
9446             }
9447         }
9448     }
9449 
9450     if (inheritable || dup3_works == 0)
9451     {
9452 #endif
9453         Py_BEGIN_ALLOW_THREADS
9454         res = dup2(fd, fd2);
9455         Py_END_ALLOW_THREADS
9456         if (res < 0) {
9457             posix_error();
9458             return -1;
9459         }
9460 
9461         if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) {
9462             close(fd2);
9463             return -1;
9464         }
9465 #ifdef HAVE_DUP3
9466     }
9467 #endif
9468 
9469 #endif
9470 
9471     return res;
9472 }
9473 #endif
9474 
9475 
9476 #ifdef HAVE_LOCKF
9477 /*[clinic input]
9478 os.lockf
9479 
9480     fd: int
9481         An open file descriptor.
9482     command: int
9483         One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.
9484     length: Py_off_t
9485         The number of bytes to lock, starting at the current position.
9486     /
9487 
9488 Apply, test or remove a POSIX lock on an open file descriptor.
9489 
9490 [clinic start generated code]*/
9491 
9492 static PyObject *
os_lockf_impl(PyObject * module,int fd,int command,Py_off_t length)9493 os_lockf_impl(PyObject *module, int fd, int command, Py_off_t length)
9494 /*[clinic end generated code: output=af7051f3e7c29651 input=65da41d2106e9b79]*/
9495 {
9496     int res;
9497 
9498     if (PySys_Audit("os.lockf", "iiL", fd, command, length) < 0) {
9499         return NULL;
9500     }
9501 
9502     Py_BEGIN_ALLOW_THREADS
9503     res = lockf(fd, command, length);
9504     Py_END_ALLOW_THREADS
9505 
9506     if (res < 0)
9507         return posix_error();
9508 
9509     Py_RETURN_NONE;
9510 }
9511 #endif /* HAVE_LOCKF */
9512 
9513 
9514 /*[clinic input]
9515 os.lseek -> Py_off_t
9516 
9517     fd: int
9518     position: Py_off_t
9519     how: int
9520     /
9521 
9522 Set the position of a file descriptor.  Return the new position.
9523 
9524 Return the new cursor position in number of bytes
9525 relative to the beginning of the file.
9526 [clinic start generated code]*/
9527 
9528 static Py_off_t
os_lseek_impl(PyObject * module,int fd,Py_off_t position,int how)9529 os_lseek_impl(PyObject *module, int fd, Py_off_t position, int how)
9530 /*[clinic end generated code: output=971e1efb6b30bd2f input=902654ad3f96a6d3]*/
9531 {
9532     Py_off_t result;
9533 
9534 #ifdef SEEK_SET
9535     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
9536     switch (how) {
9537         case 0: how = SEEK_SET; break;
9538         case 1: how = SEEK_CUR; break;
9539         case 2: how = SEEK_END; break;
9540     }
9541 #endif /* SEEK_END */
9542 
9543     Py_BEGIN_ALLOW_THREADS
9544     _Py_BEGIN_SUPPRESS_IPH
9545 #ifdef MS_WINDOWS
9546     result = _lseeki64(fd, position, how);
9547 #else
9548     result = lseek(fd, position, how);
9549 #endif
9550     _Py_END_SUPPRESS_IPH
9551     Py_END_ALLOW_THREADS
9552     if (result < 0)
9553         posix_error();
9554 
9555     return result;
9556 }
9557 
9558 
9559 /*[clinic input]
9560 os.read
9561     fd: int
9562     length: Py_ssize_t
9563     /
9564 
9565 Read from a file descriptor.  Returns a bytes object.
9566 [clinic start generated code]*/
9567 
9568 static PyObject *
os_read_impl(PyObject * module,int fd,Py_ssize_t length)9569 os_read_impl(PyObject *module, int fd, Py_ssize_t length)
9570 /*[clinic end generated code: output=dafbe9a5cddb987b input=1df2eaa27c0bf1d3]*/
9571 {
9572     Py_ssize_t n;
9573     PyObject *buffer;
9574 
9575     if (length < 0) {
9576         errno = EINVAL;
9577         return posix_error();
9578     }
9579 
9580     length = Py_MIN(length, _PY_READ_MAX);
9581 
9582     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9583     if (buffer == NULL)
9584         return NULL;
9585 
9586     n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
9587     if (n == -1) {
9588         Py_DECREF(buffer);
9589         return NULL;
9590     }
9591 
9592     if (n != length)
9593         _PyBytes_Resize(&buffer, n);
9594 
9595     return buffer;
9596 }
9597 
9598 #if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \
9599                                 || defined(__APPLE__))) \
9600     || defined(HAVE_READV) || defined(HAVE_PREADV) || defined (HAVE_PREADV2) \
9601     || defined(HAVE_WRITEV) || defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
9602 static int
iov_setup(struct iovec ** iov,Py_buffer ** buf,PyObject * seq,Py_ssize_t cnt,int type)9603 iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, Py_ssize_t cnt, int type)
9604 {
9605     Py_ssize_t i, j;
9606 
9607     *iov = PyMem_New(struct iovec, cnt);
9608     if (*iov == NULL) {
9609         PyErr_NoMemory();
9610         return -1;
9611     }
9612 
9613     *buf = PyMem_New(Py_buffer, cnt);
9614     if (*buf == NULL) {
9615         PyMem_Free(*iov);
9616         PyErr_NoMemory();
9617         return -1;
9618     }
9619 
9620     for (i = 0; i < cnt; i++) {
9621         PyObject *item = PySequence_GetItem(seq, i);
9622         if (item == NULL)
9623             goto fail;
9624         if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) {
9625             Py_DECREF(item);
9626             goto fail;
9627         }
9628         Py_DECREF(item);
9629         (*iov)[i].iov_base = (*buf)[i].buf;
9630         (*iov)[i].iov_len = (*buf)[i].len;
9631     }
9632     return 0;
9633 
9634 fail:
9635     PyMem_Free(*iov);
9636     for (j = 0; j < i; j++) {
9637         PyBuffer_Release(&(*buf)[j]);
9638     }
9639     PyMem_Free(*buf);
9640     return -1;
9641 }
9642 
9643 static void
iov_cleanup(struct iovec * iov,Py_buffer * buf,int cnt)9644 iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt)
9645 {
9646     int i;
9647     PyMem_Free(iov);
9648     for (i = 0; i < cnt; i++) {
9649         PyBuffer_Release(&buf[i]);
9650     }
9651     PyMem_Free(buf);
9652 }
9653 #endif
9654 
9655 
9656 #ifdef HAVE_READV
9657 /*[clinic input]
9658 os.readv -> Py_ssize_t
9659 
9660     fd: int
9661     buffers: object
9662     /
9663 
9664 Read from a file descriptor fd into an iterable of buffers.
9665 
9666 The buffers should be mutable buffers accepting bytes.
9667 readv will transfer data into each buffer until it is full
9668 and then move on to the next buffer in the sequence to hold
9669 the rest of the data.
9670 
9671 readv returns the total number of bytes read,
9672 which may be less than the total capacity of all the buffers.
9673 [clinic start generated code]*/
9674 
9675 static Py_ssize_t
os_readv_impl(PyObject * module,int fd,PyObject * buffers)9676 os_readv_impl(PyObject *module, int fd, PyObject *buffers)
9677 /*[clinic end generated code: output=792da062d3fcebdb input=e679eb5dbfa0357d]*/
9678 {
9679     Py_ssize_t cnt, n;
9680     int async_err = 0;
9681     struct iovec *iov;
9682     Py_buffer *buf;
9683 
9684     if (!PySequence_Check(buffers)) {
9685         PyErr_SetString(PyExc_TypeError,
9686             "readv() arg 2 must be a sequence");
9687         return -1;
9688     }
9689 
9690     cnt = PySequence_Size(buffers);
9691     if (cnt < 0)
9692         return -1;
9693 
9694     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0)
9695         return -1;
9696 
9697     do {
9698         Py_BEGIN_ALLOW_THREADS
9699         n = readv(fd, iov, cnt);
9700         Py_END_ALLOW_THREADS
9701     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9702 
9703     iov_cleanup(iov, buf, cnt);
9704     if (n < 0) {
9705         if (!async_err)
9706             posix_error();
9707         return -1;
9708     }
9709 
9710     return n;
9711 }
9712 #endif /* HAVE_READV */
9713 
9714 
9715 #ifdef HAVE_PREAD
9716 /*[clinic input]
9717 os.pread
9718 
9719     fd: int
9720     length: Py_ssize_t
9721     offset: Py_off_t
9722     /
9723 
9724 Read a number of bytes from a file descriptor starting at a particular offset.
9725 
9726 Read length bytes from file descriptor fd, starting at offset bytes from
9727 the beginning of the file.  The file offset remains unchanged.
9728 [clinic start generated code]*/
9729 
9730 static PyObject *
os_pread_impl(PyObject * module,int fd,Py_ssize_t length,Py_off_t offset)9731 os_pread_impl(PyObject *module, int fd, Py_ssize_t length, Py_off_t offset)
9732 /*[clinic end generated code: output=3f875c1eef82e32f input=85cb4a5589627144]*/
9733 {
9734     Py_ssize_t n;
9735     int async_err = 0;
9736     PyObject *buffer;
9737 
9738     if (length < 0) {
9739         errno = EINVAL;
9740         return posix_error();
9741     }
9742     buffer = PyBytes_FromStringAndSize((char *)NULL, length);
9743     if (buffer == NULL)
9744         return NULL;
9745 
9746     do {
9747         Py_BEGIN_ALLOW_THREADS
9748         _Py_BEGIN_SUPPRESS_IPH
9749         n = pread(fd, PyBytes_AS_STRING(buffer), length, offset);
9750         _Py_END_SUPPRESS_IPH
9751         Py_END_ALLOW_THREADS
9752     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9753 
9754     if (n < 0) {
9755         Py_DECREF(buffer);
9756         return (!async_err) ? posix_error() : NULL;
9757     }
9758     if (n != length)
9759         _PyBytes_Resize(&buffer, n);
9760     return buffer;
9761 }
9762 #endif /* HAVE_PREAD */
9763 
9764 #if defined(HAVE_PREADV) || defined (HAVE_PREADV2)
9765 /*[clinic input]
9766 os.preadv -> Py_ssize_t
9767 
9768     fd: int
9769     buffers: object
9770     offset: Py_off_t
9771     flags: int = 0
9772     /
9773 
9774 Reads from a file descriptor into a number of mutable bytes-like objects.
9775 
9776 Combines the functionality of readv() and pread(). As readv(), it will
9777 transfer data into each buffer until it is full and then move on to the next
9778 buffer in the sequence to hold the rest of the data. Its fourth argument,
9779 specifies the file offset at which the input operation is to be performed. It
9780 will return the total number of bytes read (which can be less than the total
9781 capacity of all the objects).
9782 
9783 The flags argument contains a bitwise OR of zero or more of the following flags:
9784 
9785 - RWF_HIPRI
9786 - RWF_NOWAIT
9787 
9788 Using non-zero flags requires Linux 4.6 or newer.
9789 [clinic start generated code]*/
9790 
9791 static Py_ssize_t
os_preadv_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)9792 os_preadv_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
9793                int flags)
9794 /*[clinic end generated code: output=26fc9c6e58e7ada5 input=4173919dc1f7ed99]*/
9795 {
9796     Py_ssize_t cnt, n;
9797     int async_err = 0;
9798     struct iovec *iov;
9799     Py_buffer *buf;
9800 
9801     if (!PySequence_Check(buffers)) {
9802         PyErr_SetString(PyExc_TypeError,
9803             "preadv2() arg 2 must be a sequence");
9804         return -1;
9805     }
9806 
9807     cnt = PySequence_Size(buffers);
9808     if (cnt < 0) {
9809         return -1;
9810     }
9811 
9812 #ifndef HAVE_PREADV2
9813     if(flags != 0) {
9814         argument_unavailable_error("preadv2", "flags");
9815         return -1;
9816     }
9817 #endif
9818 
9819     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) {
9820         return -1;
9821     }
9822 #ifdef HAVE_PREADV2
9823     do {
9824         Py_BEGIN_ALLOW_THREADS
9825         _Py_BEGIN_SUPPRESS_IPH
9826         n = preadv2(fd, iov, cnt, offset, flags);
9827         _Py_END_SUPPRESS_IPH
9828         Py_END_ALLOW_THREADS
9829     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9830 #else
9831     do {
9832 #if defined(__APPLE__) && defined(__clang__)
9833 /* This entire function will be removed from the module dict when the API
9834  * is not available.
9835  */
9836 #pragma clang diagnostic push
9837 #pragma clang diagnostic ignored "-Wunguarded-availability"
9838 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
9839 #endif
9840         Py_BEGIN_ALLOW_THREADS
9841         _Py_BEGIN_SUPPRESS_IPH
9842         n = preadv(fd, iov, cnt, offset);
9843         _Py_END_SUPPRESS_IPH
9844         Py_END_ALLOW_THREADS
9845     } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
9846 
9847 #if defined(__APPLE__) && defined(__clang__)
9848 #pragma clang diagnostic pop
9849 #endif
9850 
9851 #endif
9852 
9853     iov_cleanup(iov, buf, cnt);
9854     if (n < 0) {
9855         if (!async_err) {
9856             posix_error();
9857         }
9858         return -1;
9859     }
9860 
9861     return n;
9862 }
9863 #endif /* HAVE_PREADV */
9864 
9865 
9866 /*[clinic input]
9867 os.write -> Py_ssize_t
9868 
9869     fd: int
9870     data: Py_buffer
9871     /
9872 
9873 Write a bytes object to a file descriptor.
9874 [clinic start generated code]*/
9875 
9876 static Py_ssize_t
os_write_impl(PyObject * module,int fd,Py_buffer * data)9877 os_write_impl(PyObject *module, int fd, Py_buffer *data)
9878 /*[clinic end generated code: output=e4ef5bc904b58ef9 input=3207e28963234f3c]*/
9879 {
9880     return _Py_write(fd, data->buf, data->len);
9881 }
9882 
9883 #ifdef HAVE_SENDFILE
9884 #ifdef __APPLE__
9885 /*[clinic input]
9886 os.sendfile
9887 
9888     out_fd: int
9889     in_fd: int
9890     offset: Py_off_t
9891     count as sbytes: Py_off_t
9892     headers: object(c_default="NULL") = ()
9893     trailers: object(c_default="NULL") = ()
9894     flags: int = 0
9895 
9896 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9897 [clinic start generated code]*/
9898 
9899 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)9900 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9901                  Py_off_t sbytes, PyObject *headers, PyObject *trailers,
9902                  int flags)
9903 /*[clinic end generated code: output=81c4bcd143f5c82b input=b0d72579d4c69afa]*/
9904 #elif defined(__FreeBSD__) || defined(__DragonFly__)
9905 /*[clinic input]
9906 os.sendfile
9907 
9908     out_fd: int
9909     in_fd: int
9910     offset: Py_off_t
9911     count: Py_ssize_t
9912     headers: object(c_default="NULL") = ()
9913     trailers: object(c_default="NULL") = ()
9914     flags: int = 0
9915 
9916 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9917 [clinic start generated code]*/
9918 
9919 static PyObject *
9920 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, Py_off_t offset,
9921                  Py_ssize_t count, PyObject *headers, PyObject *trailers,
9922                  int flags)
9923 /*[clinic end generated code: output=329ea009bdd55afc input=338adb8ff84ae8cd]*/
9924 #else
9925 /*[clinic input]
9926 os.sendfile
9927 
9928     out_fd: int
9929     in_fd: int
9930     offset as offobj: object
9931     count: Py_ssize_t
9932 
9933 Copy count bytes from file descriptor in_fd to file descriptor out_fd.
9934 [clinic start generated code]*/
9935 
9936 static PyObject *
9937 os_sendfile_impl(PyObject *module, int out_fd, int in_fd, PyObject *offobj,
9938                  Py_ssize_t count)
9939 /*[clinic end generated code: output=ae81216e40f167d8 input=76d64058c74477ba]*/
9940 #endif
9941 {
9942     Py_ssize_t ret;
9943     int async_err = 0;
9944 
9945 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
9946 #ifndef __APPLE__
9947     off_t sbytes;
9948 #endif
9949     Py_buffer *hbuf, *tbuf;
9950     struct sf_hdtr sf;
9951 
9952     sf.headers = NULL;
9953     sf.trailers = NULL;
9954 
9955     if (headers != NULL) {
9956         if (!PySequence_Check(headers)) {
9957             PyErr_SetString(PyExc_TypeError,
9958                 "sendfile() headers must be a sequence");
9959             return NULL;
9960         } else {
9961             Py_ssize_t i = PySequence_Size(headers);
9962             if (i < 0)
9963                 return NULL;
9964             if (i > INT_MAX) {
9965                 PyErr_SetString(PyExc_OverflowError,
9966                     "sendfile() header is too large");
9967                 return NULL;
9968             }
9969             if (i > 0) {
9970                 sf.hdr_cnt = (int)i;
9971                 if (iov_setup(&(sf.headers), &hbuf,
9972                               headers, sf.hdr_cnt, PyBUF_SIMPLE) < 0)
9973                     return NULL;
9974 #ifdef __APPLE__
9975                 for (i = 0; i < sf.hdr_cnt; i++) {
9976                     Py_ssize_t blen = sf.headers[i].iov_len;
9977 # define OFF_T_MAX 0x7fffffffffffffff
9978                     if (sbytes >= OFF_T_MAX - blen) {
9979                         PyErr_SetString(PyExc_OverflowError,
9980                             "sendfile() header is too large");
9981                         return NULL;
9982                     }
9983                     sbytes += blen;
9984                 }
9985 #endif
9986             }
9987         }
9988     }
9989     if (trailers != NULL) {
9990         if (!PySequence_Check(trailers)) {
9991             PyErr_SetString(PyExc_TypeError,
9992                 "sendfile() trailers must be a sequence");
9993             return NULL;
9994         } else {
9995             Py_ssize_t i = PySequence_Size(trailers);
9996             if (i < 0)
9997                 return NULL;
9998             if (i > INT_MAX) {
9999                 PyErr_SetString(PyExc_OverflowError,
10000                     "sendfile() trailer is too large");
10001                 return NULL;
10002             }
10003             if (i > 0) {
10004                 sf.trl_cnt = (int)i;
10005                 if (iov_setup(&(sf.trailers), &tbuf,
10006                               trailers, sf.trl_cnt, PyBUF_SIMPLE) < 0)
10007                     return NULL;
10008             }
10009         }
10010     }
10011 
10012     _Py_BEGIN_SUPPRESS_IPH
10013     do {
10014         Py_BEGIN_ALLOW_THREADS
10015 #ifdef __APPLE__
10016         ret = sendfile(in_fd, out_fd, offset, &sbytes, &sf, flags);
10017 #else
10018         ret = sendfile(in_fd, out_fd, offset, count, &sf, &sbytes, flags);
10019 #endif
10020         Py_END_ALLOW_THREADS
10021     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10022     _Py_END_SUPPRESS_IPH
10023 
10024     if (sf.headers != NULL)
10025         iov_cleanup(sf.headers, hbuf, sf.hdr_cnt);
10026     if (sf.trailers != NULL)
10027         iov_cleanup(sf.trailers, tbuf, sf.trl_cnt);
10028 
10029     if (ret < 0) {
10030         if ((errno == EAGAIN) || (errno == EBUSY)) {
10031             if (sbytes != 0) {
10032                 // some data has been sent
10033                 goto done;
10034             }
10035             else {
10036                 // no data has been sent; upper application is supposed
10037                 // to retry on EAGAIN or EBUSY
10038                 return posix_error();
10039             }
10040         }
10041         return (!async_err) ? posix_error() : NULL;
10042     }
10043     goto done;
10044 
10045 done:
10046     #if !defined(HAVE_LARGEFILE_SUPPORT)
10047         return Py_BuildValue("l", sbytes);
10048     #else
10049         return Py_BuildValue("L", sbytes);
10050     #endif
10051 
10052 #else
10053 #ifdef __linux__
10054     if (offobj == Py_None) {
10055         do {
10056             Py_BEGIN_ALLOW_THREADS
10057             ret = sendfile(out_fd, in_fd, NULL, count);
10058             Py_END_ALLOW_THREADS
10059         } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10060         if (ret < 0)
10061             return (!async_err) ? posix_error() : NULL;
10062         return Py_BuildValue("n", ret);
10063     }
10064 #endif
10065     off_t offset;
10066     if (!Py_off_t_converter(offobj, &offset))
10067         return NULL;
10068 
10069 #if defined(__sun) && defined(__SVR4)
10070     // On Solaris, sendfile raises EINVAL rather than returning 0
10071     // when the offset is equal or bigger than the in_fd size.
10072     struct stat st;
10073 
10074     do {
10075         Py_BEGIN_ALLOW_THREADS
10076         ret = fstat(in_fd, &st);
10077         Py_END_ALLOW_THREADS
10078     } while (ret != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10079     if (ret < 0)
10080         return (!async_err) ? posix_error() : NULL;
10081 
10082     if (offset >= st.st_size) {
10083         return Py_BuildValue("i", 0);
10084     }
10085 
10086     // On illumos specifically sendfile() may perform a partial write but
10087     // return -1/an error (in one confirmed case the destination socket
10088     // had a 5 second timeout set and errno was EAGAIN) and it's on the client
10089     // code to check if the offset parameter was modified by sendfile().
10090     //
10091     // We need this variable to track said change.
10092     off_t original_offset = offset;
10093 #endif
10094 
10095     do {
10096         Py_BEGIN_ALLOW_THREADS
10097         ret = sendfile(out_fd, in_fd, &offset, count);
10098 #if defined(__sun) && defined(__SVR4)
10099         // This handles illumos-specific sendfile() partial write behavior,
10100         // see a comment above for more details.
10101         if (ret < 0 && offset != original_offset) {
10102             ret = offset - original_offset;
10103         }
10104 #endif
10105         Py_END_ALLOW_THREADS
10106     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10107     if (ret < 0)
10108         return (!async_err) ? posix_error() : NULL;
10109     return Py_BuildValue("n", ret);
10110 #endif
10111 }
10112 #endif /* HAVE_SENDFILE */
10113 
10114 
10115 #if defined(__APPLE__)
10116 /*[clinic input]
10117 os._fcopyfile
10118 
10119     in_fd: int
10120     out_fd: int
10121     flags: int
10122     /
10123 
10124 Efficiently copy content or metadata of 2 regular file descriptors (macOS).
10125 [clinic start generated code]*/
10126 
10127 static PyObject *
os__fcopyfile_impl(PyObject * module,int in_fd,int out_fd,int flags)10128 os__fcopyfile_impl(PyObject *module, int in_fd, int out_fd, int flags)
10129 /*[clinic end generated code: output=c9d1a35a992e401b input=1e34638a86948795]*/
10130 {
10131     int ret;
10132 
10133     Py_BEGIN_ALLOW_THREADS
10134     ret = fcopyfile(in_fd, out_fd, NULL, flags);
10135     Py_END_ALLOW_THREADS
10136     if (ret < 0)
10137         return posix_error();
10138     Py_RETURN_NONE;
10139 }
10140 #endif
10141 
10142 
10143 /*[clinic input]
10144 os.fstat
10145 
10146     fd : int
10147 
10148 Perform a stat system call on the given file descriptor.
10149 
10150 Like stat(), but for an open file descriptor.
10151 Equivalent to os.stat(fd).
10152 [clinic start generated code]*/
10153 
10154 static PyObject *
os_fstat_impl(PyObject * module,int fd)10155 os_fstat_impl(PyObject *module, int fd)
10156 /*[clinic end generated code: output=efc038cb5f654492 input=27e0e0ebbe5600c9]*/
10157 {
10158     STRUCT_STAT st;
10159     int res;
10160     int async_err = 0;
10161 
10162     do {
10163         Py_BEGIN_ALLOW_THREADS
10164         res = FSTAT(fd, &st);
10165         Py_END_ALLOW_THREADS
10166     } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10167     if (res != 0) {
10168 #ifdef MS_WINDOWS
10169         return PyErr_SetFromWindowsErr(0);
10170 #else
10171         return (!async_err) ? posix_error() : NULL;
10172 #endif
10173     }
10174 
10175     return _pystat_fromstructstat(module, &st);
10176 }
10177 
10178 
10179 /*[clinic input]
10180 os.isatty -> bool
10181     fd: int
10182     /
10183 
10184 Return True if the fd is connected to a terminal.
10185 
10186 Return True if the file descriptor is an open file descriptor
10187 connected to the slave end of a terminal.
10188 [clinic start generated code]*/
10189 
10190 static int
os_isatty_impl(PyObject * module,int fd)10191 os_isatty_impl(PyObject *module, int fd)
10192 /*[clinic end generated code: output=6a48c8b4e644ca00 input=08ce94aa1eaf7b5e]*/
10193 {
10194     int return_value;
10195     Py_BEGIN_ALLOW_THREADS
10196     _Py_BEGIN_SUPPRESS_IPH
10197     return_value = isatty(fd);
10198     _Py_END_SUPPRESS_IPH
10199     Py_END_ALLOW_THREADS
10200     return return_value;
10201 }
10202 
10203 
10204 #ifdef HAVE_PIPE
10205 /*[clinic input]
10206 os.pipe
10207 
10208 Create a pipe.
10209 
10210 Returns a tuple of two file descriptors:
10211   (read_fd, write_fd)
10212 [clinic start generated code]*/
10213 
10214 static PyObject *
os_pipe_impl(PyObject * module)10215 os_pipe_impl(PyObject *module)
10216 /*[clinic end generated code: output=ff9b76255793b440 input=02535e8c8fa6c4d4]*/
10217 {
10218     int fds[2];
10219 #ifdef MS_WINDOWS
10220     HANDLE read, write;
10221     SECURITY_ATTRIBUTES attr;
10222     BOOL ok;
10223 #else
10224     int res;
10225 #endif
10226 
10227 #ifdef MS_WINDOWS
10228     attr.nLength = sizeof(attr);
10229     attr.lpSecurityDescriptor = NULL;
10230     attr.bInheritHandle = FALSE;
10231 
10232     Py_BEGIN_ALLOW_THREADS
10233     ok = CreatePipe(&read, &write, &attr, 0);
10234     if (ok) {
10235         fds[0] = _Py_open_osfhandle_noraise(read, _O_RDONLY);
10236         fds[1] = _Py_open_osfhandle_noraise(write, _O_WRONLY);
10237         if (fds[0] == -1 || fds[1] == -1) {
10238             CloseHandle(read);
10239             CloseHandle(write);
10240             ok = 0;
10241         }
10242     }
10243     Py_END_ALLOW_THREADS
10244 
10245     if (!ok)
10246         return PyErr_SetFromWindowsErr(0);
10247 #else
10248 
10249 #ifdef HAVE_PIPE2
10250     Py_BEGIN_ALLOW_THREADS
10251     res = pipe2(fds, O_CLOEXEC);
10252     Py_END_ALLOW_THREADS
10253 
10254     if (res != 0 && errno == ENOSYS)
10255     {
10256 #endif
10257         Py_BEGIN_ALLOW_THREADS
10258         res = pipe(fds);
10259         Py_END_ALLOW_THREADS
10260 
10261         if (res == 0) {
10262             if (_Py_set_inheritable(fds[0], 0, NULL) < 0) {
10263                 close(fds[0]);
10264                 close(fds[1]);
10265                 return NULL;
10266             }
10267             if (_Py_set_inheritable(fds[1], 0, NULL) < 0) {
10268                 close(fds[0]);
10269                 close(fds[1]);
10270                 return NULL;
10271             }
10272         }
10273 #ifdef HAVE_PIPE2
10274     }
10275 #endif
10276 
10277     if (res != 0)
10278         return PyErr_SetFromErrno(PyExc_OSError);
10279 #endif /* !MS_WINDOWS */
10280     return Py_BuildValue("(ii)", fds[0], fds[1]);
10281 }
10282 #endif  /* HAVE_PIPE */
10283 
10284 
10285 #ifdef HAVE_PIPE2
10286 /*[clinic input]
10287 os.pipe2
10288 
10289     flags: int
10290     /
10291 
10292 Create a pipe with flags set atomically.
10293 
10294 Returns a tuple of two file descriptors:
10295   (read_fd, write_fd)
10296 
10297 flags can be constructed by ORing together one or more of these values:
10298 O_NONBLOCK, O_CLOEXEC.
10299 [clinic start generated code]*/
10300 
10301 static PyObject *
os_pipe2_impl(PyObject * module,int flags)10302 os_pipe2_impl(PyObject *module, int flags)
10303 /*[clinic end generated code: output=25751fb43a45540f input=f261b6e7e63c6817]*/
10304 {
10305     int fds[2];
10306     int res;
10307 
10308     res = pipe2(fds, flags);
10309     if (res != 0)
10310         return posix_error();
10311     return Py_BuildValue("(ii)", fds[0], fds[1]);
10312 }
10313 #endif /* HAVE_PIPE2 */
10314 
10315 
10316 #ifdef HAVE_WRITEV
10317 /*[clinic input]
10318 os.writev -> Py_ssize_t
10319     fd: int
10320     buffers: object
10321     /
10322 
10323 Iterate over buffers, and write the contents of each to a file descriptor.
10324 
10325 Returns the total number of bytes written.
10326 buffers must be a sequence of bytes-like objects.
10327 [clinic start generated code]*/
10328 
10329 static Py_ssize_t
os_writev_impl(PyObject * module,int fd,PyObject * buffers)10330 os_writev_impl(PyObject *module, int fd, PyObject *buffers)
10331 /*[clinic end generated code: output=56565cfac3aac15b input=5b8d17fe4189d2fe]*/
10332 {
10333     Py_ssize_t cnt;
10334     Py_ssize_t result;
10335     int async_err = 0;
10336     struct iovec *iov;
10337     Py_buffer *buf;
10338 
10339     if (!PySequence_Check(buffers)) {
10340         PyErr_SetString(PyExc_TypeError,
10341             "writev() arg 2 must be a sequence");
10342         return -1;
10343     }
10344     cnt = PySequence_Size(buffers);
10345     if (cnt < 0)
10346         return -1;
10347 
10348     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10349         return -1;
10350     }
10351 
10352     do {
10353         Py_BEGIN_ALLOW_THREADS
10354         result = writev(fd, iov, cnt);
10355         Py_END_ALLOW_THREADS
10356     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10357 
10358     iov_cleanup(iov, buf, cnt);
10359     if (result < 0 && !async_err)
10360         posix_error();
10361 
10362     return result;
10363 }
10364 #endif /* HAVE_WRITEV */
10365 
10366 
10367 #ifdef HAVE_PWRITE
10368 /*[clinic input]
10369 os.pwrite -> Py_ssize_t
10370 
10371     fd: int
10372     buffer: Py_buffer
10373     offset: Py_off_t
10374     /
10375 
10376 Write bytes to a file descriptor starting at a particular offset.
10377 
10378 Write buffer to fd, starting at offset bytes from the beginning of
10379 the file.  Returns the number of bytes writte.  Does not change the
10380 current file offset.
10381 [clinic start generated code]*/
10382 
10383 static Py_ssize_t
os_pwrite_impl(PyObject * module,int fd,Py_buffer * buffer,Py_off_t offset)10384 os_pwrite_impl(PyObject *module, int fd, Py_buffer *buffer, Py_off_t offset)
10385 /*[clinic end generated code: output=c74da630758ee925 input=19903f1b3dd26377]*/
10386 {
10387     Py_ssize_t size;
10388     int async_err = 0;
10389 
10390     do {
10391         Py_BEGIN_ALLOW_THREADS
10392         _Py_BEGIN_SUPPRESS_IPH
10393         size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset);
10394         _Py_END_SUPPRESS_IPH
10395         Py_END_ALLOW_THREADS
10396     } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10397 
10398     if (size < 0 && !async_err)
10399         posix_error();
10400     return size;
10401 }
10402 #endif /* HAVE_PWRITE */
10403 
10404 #if defined(HAVE_PWRITEV) || defined (HAVE_PWRITEV2)
10405 /*[clinic input]
10406 os.pwritev -> Py_ssize_t
10407 
10408     fd: int
10409     buffers: object
10410     offset: Py_off_t
10411     flags: int = 0
10412     /
10413 
10414 Writes the contents of bytes-like objects to a file descriptor at a given offset.
10415 
10416 Combines the functionality of writev() and pwrite(). All buffers must be a sequence
10417 of bytes-like objects. Buffers are processed in array order. Entire contents of first
10418 buffer is written before proceeding to second, and so on. The operating system may
10419 set a limit (sysconf() value SC_IOV_MAX) on the number of buffers that can be used.
10420 This function writes the contents of each object to the file descriptor and returns
10421 the total number of bytes written.
10422 
10423 The flags argument contains a bitwise OR of zero or more of the following flags:
10424 
10425 - RWF_DSYNC
10426 - RWF_SYNC
10427 - RWF_APPEND
10428 
10429 Using non-zero flags requires Linux 4.7 or newer.
10430 [clinic start generated code]*/
10431 
10432 static Py_ssize_t
os_pwritev_impl(PyObject * module,int fd,PyObject * buffers,Py_off_t offset,int flags)10433 os_pwritev_impl(PyObject *module, int fd, PyObject *buffers, Py_off_t offset,
10434                 int flags)
10435 /*[clinic end generated code: output=e3dd3e9d11a6a5c7 input=35358c327e1a2a8e]*/
10436 {
10437     Py_ssize_t cnt;
10438     Py_ssize_t result;
10439     int async_err = 0;
10440     struct iovec *iov;
10441     Py_buffer *buf;
10442 
10443     if (!PySequence_Check(buffers)) {
10444         PyErr_SetString(PyExc_TypeError,
10445             "pwritev() arg 2 must be a sequence");
10446         return -1;
10447     }
10448 
10449     cnt = PySequence_Size(buffers);
10450     if (cnt < 0) {
10451         return -1;
10452     }
10453 
10454 #ifndef HAVE_PWRITEV2
10455     if(flags != 0) {
10456         argument_unavailable_error("pwritev2", "flags");
10457         return -1;
10458     }
10459 #endif
10460 
10461     if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) {
10462         return -1;
10463     }
10464 #ifdef HAVE_PWRITEV2
10465     do {
10466         Py_BEGIN_ALLOW_THREADS
10467         _Py_BEGIN_SUPPRESS_IPH
10468         result = pwritev2(fd, iov, cnt, offset, flags);
10469         _Py_END_SUPPRESS_IPH
10470         Py_END_ALLOW_THREADS
10471     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10472 #else
10473 
10474 #if defined(__APPLE__) && defined(__clang__)
10475 /* This entire function will be removed from the module dict when the API
10476  * is not available.
10477  */
10478 #pragma clang diagnostic push
10479 #pragma clang diagnostic ignored "-Wunguarded-availability"
10480 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
10481 #endif
10482     do {
10483         Py_BEGIN_ALLOW_THREADS
10484         _Py_BEGIN_SUPPRESS_IPH
10485         result = pwritev(fd, iov, cnt, offset);
10486         _Py_END_SUPPRESS_IPH
10487         Py_END_ALLOW_THREADS
10488     } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10489 
10490 #if defined(__APPLE__) && defined(__clang__)
10491 #pragma clang diagnostic pop
10492 #endif
10493 
10494 #endif
10495 
10496     iov_cleanup(iov, buf, cnt);
10497     if (result < 0) {
10498         if (!async_err) {
10499             posix_error();
10500         }
10501         return -1;
10502     }
10503 
10504     return result;
10505 }
10506 #endif /* HAVE_PWRITEV */
10507 
10508 #ifdef HAVE_COPY_FILE_RANGE
10509 /*[clinic input]
10510 
10511 os.copy_file_range
10512     src: int
10513         Source file descriptor.
10514     dst: int
10515         Destination file descriptor.
10516     count: Py_ssize_t
10517         Number of bytes to copy.
10518     offset_src: object = None
10519         Starting offset in src.
10520     offset_dst: object = None
10521         Starting offset in dst.
10522 
10523 Copy count bytes from one file descriptor to another.
10524 
10525 If offset_src is None, then src is read from the current position;
10526 respectively for offset_dst.
10527 [clinic start generated code]*/
10528 
10529 static PyObject *
os_copy_file_range_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst)10530 os_copy_file_range_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10531                         PyObject *offset_src, PyObject *offset_dst)
10532 /*[clinic end generated code: output=1a91713a1d99fc7a input=42fdce72681b25a9]*/
10533 {
10534     off_t offset_src_val, offset_dst_val;
10535     off_t *p_offset_src = NULL;
10536     off_t *p_offset_dst = NULL;
10537     Py_ssize_t ret;
10538     int async_err = 0;
10539     /* The flags argument is provided to allow
10540      * for future extensions and currently must be to 0. */
10541     int flags = 0;
10542 
10543 
10544     if (count < 0) {
10545         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10546         return NULL;
10547     }
10548 
10549     if (offset_src != Py_None) {
10550         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10551             return NULL;
10552         }
10553         p_offset_src = &offset_src_val;
10554     }
10555 
10556     if (offset_dst != Py_None) {
10557         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10558             return NULL;
10559         }
10560         p_offset_dst = &offset_dst_val;
10561     }
10562 
10563     do {
10564         Py_BEGIN_ALLOW_THREADS
10565         ret = copy_file_range(src, p_offset_src, dst, p_offset_dst, count, flags);
10566         Py_END_ALLOW_THREADS
10567     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10568 
10569     if (ret < 0) {
10570         return (!async_err) ? posix_error() : NULL;
10571     }
10572 
10573     return PyLong_FromSsize_t(ret);
10574 }
10575 #endif /* HAVE_COPY_FILE_RANGE*/
10576 
10577 #if (defined(HAVE_SPLICE) && !defined(_AIX))
10578 /*[clinic input]
10579 
10580 os.splice
10581     src: int
10582         Source file descriptor.
10583     dst: int
10584         Destination file descriptor.
10585     count: Py_ssize_t
10586         Number of bytes to copy.
10587     offset_src: object = None
10588         Starting offset in src.
10589     offset_dst: object = None
10590         Starting offset in dst.
10591     flags: unsigned_int = 0
10592         Flags to modify the semantics of the call.
10593 
10594 Transfer count bytes from one pipe to a descriptor or vice versa.
10595 
10596 If offset_src is None, then src is read from the current position;
10597 respectively for offset_dst. The offset associated to the file
10598 descriptor that refers to a pipe must be None.
10599 [clinic start generated code]*/
10600 
10601 static PyObject *
os_splice_impl(PyObject * module,int src,int dst,Py_ssize_t count,PyObject * offset_src,PyObject * offset_dst,unsigned int flags)10602 os_splice_impl(PyObject *module, int src, int dst, Py_ssize_t count,
10603                PyObject *offset_src, PyObject *offset_dst,
10604                unsigned int flags)
10605 /*[clinic end generated code: output=d0386f25a8519dc5 input=047527c66c6d2e0a]*/
10606 {
10607     off_t offset_src_val, offset_dst_val;
10608     off_t *p_offset_src = NULL;
10609     off_t *p_offset_dst = NULL;
10610     Py_ssize_t ret;
10611     int async_err = 0;
10612 
10613     if (count < 0) {
10614         PyErr_SetString(PyExc_ValueError, "negative value for 'count' not allowed");
10615         return NULL;
10616     }
10617 
10618     if (offset_src != Py_None) {
10619         if (!Py_off_t_converter(offset_src, &offset_src_val)) {
10620             return NULL;
10621         }
10622         p_offset_src = &offset_src_val;
10623     }
10624 
10625     if (offset_dst != Py_None) {
10626         if (!Py_off_t_converter(offset_dst, &offset_dst_val)) {
10627             return NULL;
10628         }
10629         p_offset_dst = &offset_dst_val;
10630     }
10631 
10632     do {
10633         Py_BEGIN_ALLOW_THREADS
10634         ret = splice(src, p_offset_src, dst, p_offset_dst, count, flags);
10635         Py_END_ALLOW_THREADS
10636     } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
10637 
10638     if (ret < 0) {
10639         return (!async_err) ? posix_error() : NULL;
10640     }
10641 
10642     return PyLong_FromSsize_t(ret);
10643 }
10644 #endif /* HAVE_SPLICE*/
10645 
10646 #ifdef HAVE_MKFIFO
10647 /*[clinic input]
10648 os.mkfifo
10649 
10650     path: path_t
10651     mode: int=0o666
10652     *
10653     dir_fd: dir_fd(requires='mkfifoat')=None
10654 
10655 Create a "fifo" (a POSIX named pipe).
10656 
10657 If dir_fd is not None, it should be a file descriptor open to a directory,
10658   and path should be relative; path will then be relative to that directory.
10659 dir_fd may not be implemented on your platform.
10660   If it is unavailable, using it will raise a NotImplementedError.
10661 [clinic start generated code]*/
10662 
10663 static PyObject *
os_mkfifo_impl(PyObject * module,path_t * path,int mode,int dir_fd)10664 os_mkfifo_impl(PyObject *module, path_t *path, int mode, int dir_fd)
10665 /*[clinic end generated code: output=ce41cfad0e68c940 input=73032e98a36e0e19]*/
10666 {
10667     int result;
10668     int async_err = 0;
10669 #ifdef HAVE_MKFIFOAT
10670     int mkfifoat_unavailable = 0;
10671 #endif
10672 
10673     do {
10674         Py_BEGIN_ALLOW_THREADS
10675 #ifdef HAVE_MKFIFOAT
10676         if (dir_fd != DEFAULT_DIR_FD) {
10677             if (HAVE_MKFIFOAT_RUNTIME) {
10678                 result = mkfifoat(dir_fd, path->narrow, mode);
10679 
10680             } else {
10681                 mkfifoat_unavailable = 1;
10682                 result = 0;
10683             }
10684         } else
10685 #endif
10686             result = mkfifo(path->narrow, mode);
10687         Py_END_ALLOW_THREADS
10688     } while (result != 0 && errno == EINTR &&
10689              !(async_err = PyErr_CheckSignals()));
10690 
10691 #ifdef HAVE_MKFIFOAT
10692     if (mkfifoat_unavailable) {
10693         argument_unavailable_error(NULL, "dir_fd");
10694         return NULL;
10695     }
10696 #endif
10697 
10698     if (result != 0)
10699         return (!async_err) ? posix_error() : NULL;
10700 
10701     Py_RETURN_NONE;
10702 }
10703 #endif /* HAVE_MKFIFO */
10704 
10705 
10706 #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
10707 /*[clinic input]
10708 os.mknod
10709 
10710     path: path_t
10711     mode: int=0o600
10712     device: dev_t=0
10713     *
10714     dir_fd: dir_fd(requires='mknodat')=None
10715 
10716 Create a node in the file system.
10717 
10718 Create a node in the file system (file, device special file or named pipe)
10719 at path.  mode specifies both the permissions to use and the
10720 type of node to be created, being combined (bitwise OR) with one of
10721 S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO.  If S_IFCHR or S_IFBLK is set on mode,
10722 device defines the newly created device special file (probably using
10723 os.makedev()).  Otherwise device is ignored.
10724 
10725 If dir_fd is not None, it should be a file descriptor open to a directory,
10726   and path should be relative; path will then be relative to that directory.
10727 dir_fd may not be implemented on your platform.
10728   If it is unavailable, using it will raise a NotImplementedError.
10729 [clinic start generated code]*/
10730 
10731 static PyObject *
os_mknod_impl(PyObject * module,path_t * path,int mode,dev_t device,int dir_fd)10732 os_mknod_impl(PyObject *module, path_t *path, int mode, dev_t device,
10733               int dir_fd)
10734 /*[clinic end generated code: output=92e55d3ca8917461 input=ee44531551a4d83b]*/
10735 {
10736     int result;
10737     int async_err = 0;
10738 #ifdef HAVE_MKNODAT
10739     int mknodat_unavailable = 0;
10740 #endif
10741 
10742     do {
10743         Py_BEGIN_ALLOW_THREADS
10744 #ifdef HAVE_MKNODAT
10745         if (dir_fd != DEFAULT_DIR_FD) {
10746             if (HAVE_MKNODAT_RUNTIME) {
10747                 result = mknodat(dir_fd, path->narrow, mode, device);
10748 
10749             } else {
10750                 mknodat_unavailable = 1;
10751                 result = 0;
10752             }
10753         } else
10754 #endif
10755             result = mknod(path->narrow, mode, device);
10756         Py_END_ALLOW_THREADS
10757     } while (result != 0 && errno == EINTR &&
10758              !(async_err = PyErr_CheckSignals()));
10759 #ifdef HAVE_MKNODAT
10760     if (mknodat_unavailable) {
10761         argument_unavailable_error(NULL, "dir_fd");
10762         return NULL;
10763     }
10764 #endif
10765     if (result != 0)
10766         return (!async_err) ? posix_error() : NULL;
10767 
10768     Py_RETURN_NONE;
10769 }
10770 #endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */
10771 
10772 
10773 #ifdef HAVE_DEVICE_MACROS
10774 /*[clinic input]
10775 os.major -> unsigned_int
10776 
10777     device: dev_t
10778     /
10779 
10780 Extracts a device major number from a raw device number.
10781 [clinic start generated code]*/
10782 
10783 static unsigned int
os_major_impl(PyObject * module,dev_t device)10784 os_major_impl(PyObject *module, dev_t device)
10785 /*[clinic end generated code: output=5b3b2589bafb498e input=1e16a4d30c4d4462]*/
10786 {
10787     return major(device);
10788 }
10789 
10790 
10791 /*[clinic input]
10792 os.minor -> unsigned_int
10793 
10794     device: dev_t
10795     /
10796 
10797 Extracts a device minor number from a raw device number.
10798 [clinic start generated code]*/
10799 
10800 static unsigned int
os_minor_impl(PyObject * module,dev_t device)10801 os_minor_impl(PyObject *module, dev_t device)
10802 /*[clinic end generated code: output=5e1a25e630b0157d input=0842c6d23f24c65e]*/
10803 {
10804     return minor(device);
10805 }
10806 
10807 
10808 /*[clinic input]
10809 os.makedev -> dev_t
10810 
10811     major: int
10812     minor: int
10813     /
10814 
10815 Composes a raw device number from the major and minor device numbers.
10816 [clinic start generated code]*/
10817 
10818 static dev_t
os_makedev_impl(PyObject * module,int major,int minor)10819 os_makedev_impl(PyObject *module, int major, int minor)
10820 /*[clinic end generated code: output=881aaa4aba6f6a52 input=4b9fd8fc73cbe48f]*/
10821 {
10822     return makedev(major, minor);
10823 }
10824 #endif /* HAVE_DEVICE_MACROS */
10825 
10826 
10827 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
10828 /*[clinic input]
10829 os.ftruncate
10830 
10831     fd: int
10832     length: Py_off_t
10833     /
10834 
10835 Truncate a file, specified by file descriptor, to a specific length.
10836 [clinic start generated code]*/
10837 
10838 static PyObject *
os_ftruncate_impl(PyObject * module,int fd,Py_off_t length)10839 os_ftruncate_impl(PyObject *module, int fd, Py_off_t length)
10840 /*[clinic end generated code: output=fba15523721be7e4 input=63b43641e52818f2]*/
10841 {
10842     int result;
10843     int async_err = 0;
10844 
10845     if (PySys_Audit("os.truncate", "in", fd, length) < 0) {
10846         return NULL;
10847     }
10848 
10849     do {
10850         Py_BEGIN_ALLOW_THREADS
10851         _Py_BEGIN_SUPPRESS_IPH
10852 #ifdef MS_WINDOWS
10853         result = _chsize_s(fd, length);
10854 #else
10855         result = ftruncate(fd, length);
10856 #endif
10857         _Py_END_SUPPRESS_IPH
10858         Py_END_ALLOW_THREADS
10859     } while (result != 0 && errno == EINTR &&
10860              !(async_err = PyErr_CheckSignals()));
10861     if (result != 0)
10862         return (!async_err) ? posix_error() : NULL;
10863     Py_RETURN_NONE;
10864 }
10865 #endif /* HAVE_FTRUNCATE || MS_WINDOWS */
10866 
10867 
10868 #if defined HAVE_TRUNCATE || defined MS_WINDOWS
10869 /*[clinic input]
10870 os.truncate
10871     path: path_t(allow_fd='PATH_HAVE_FTRUNCATE')
10872     length: Py_off_t
10873 
10874 Truncate a file, specified by path, to a specific length.
10875 
10876 On some platforms, path may also be specified as an open file descriptor.
10877   If this functionality is unavailable, using it raises an exception.
10878 [clinic start generated code]*/
10879 
10880 static PyObject *
os_truncate_impl(PyObject * module,path_t * path,Py_off_t length)10881 os_truncate_impl(PyObject *module, path_t *path, Py_off_t length)
10882 /*[clinic end generated code: output=43009c8df5c0a12b input=77229cf0b50a9b77]*/
10883 {
10884     int result;
10885 #ifdef MS_WINDOWS
10886     int fd;
10887 #endif
10888 
10889     if (path->fd != -1)
10890         return os_ftruncate_impl(module, path->fd, length);
10891 
10892     if (PySys_Audit("os.truncate", "On", path->object, length) < 0) {
10893         return NULL;
10894     }
10895 
10896     Py_BEGIN_ALLOW_THREADS
10897     _Py_BEGIN_SUPPRESS_IPH
10898 #ifdef MS_WINDOWS
10899     fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT);
10900     if (fd < 0)
10901         result = -1;
10902     else {
10903         result = _chsize_s(fd, length);
10904         close(fd);
10905         if (result < 0)
10906             errno = result;
10907     }
10908 #else
10909     result = truncate(path->narrow, length);
10910 #endif
10911     _Py_END_SUPPRESS_IPH
10912     Py_END_ALLOW_THREADS
10913     if (result < 0)
10914         return posix_path_error(path);
10915 
10916     Py_RETURN_NONE;
10917 }
10918 #endif /* HAVE_TRUNCATE || MS_WINDOWS */
10919 
10920 
10921 /* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise()
10922    and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is
10923    defined, which is the case in Python on AIX. AIX bug report:
10924    http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */
10925 #if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__)
10926 #  define POSIX_FADVISE_AIX_BUG
10927 #endif
10928 
10929 
10930 #if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)
10931 /*[clinic input]
10932 os.posix_fallocate
10933 
10934     fd: int
10935     offset: Py_off_t
10936     length: Py_off_t
10937     /
10938 
10939 Ensure a file has allocated at least a particular number of bytes on disk.
10940 
10941 Ensure that the file specified by fd encompasses a range of bytes
10942 starting at offset bytes from the beginning and continuing for length bytes.
10943 [clinic start generated code]*/
10944 
10945 static PyObject *
os_posix_fallocate_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length)10946 os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset,
10947                         Py_off_t length)
10948 /*[clinic end generated code: output=73f107139564aa9d input=d7a2ef0ab2ca52fb]*/
10949 {
10950     int result;
10951     int async_err = 0;
10952 
10953     do {
10954         Py_BEGIN_ALLOW_THREADS
10955         result = posix_fallocate(fd, offset, length);
10956         Py_END_ALLOW_THREADS
10957     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
10958 
10959     if (result == 0)
10960         Py_RETURN_NONE;
10961 
10962     if (async_err)
10963         return NULL;
10964 
10965     errno = result;
10966     return posix_error();
10967 }
10968 #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */
10969 
10970 
10971 #if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)
10972 /*[clinic input]
10973 os.posix_fadvise
10974 
10975     fd: int
10976     offset: Py_off_t
10977     length: Py_off_t
10978     advice: int
10979     /
10980 
10981 Announce an intention to access data in a specific pattern.
10982 
10983 Announce an intention to access data in a specific pattern, thus allowing
10984 the kernel to make optimizations.
10985 The advice applies to the region of the file specified by fd starting at
10986 offset and continuing for length bytes.
10987 advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,
10988 POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or
10989 POSIX_FADV_DONTNEED.
10990 [clinic start generated code]*/
10991 
10992 static PyObject *
os_posix_fadvise_impl(PyObject * module,int fd,Py_off_t offset,Py_off_t length,int advice)10993 os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
10994                       Py_off_t length, int advice)
10995 /*[clinic end generated code: output=412ef4aa70c98642 input=0fbe554edc2f04b5]*/
10996 {
10997     int result;
10998     int async_err = 0;
10999 
11000     do {
11001         Py_BEGIN_ALLOW_THREADS
11002         result = posix_fadvise(fd, offset, length, advice);
11003         Py_END_ALLOW_THREADS
11004     } while (result == EINTR && !(async_err = PyErr_CheckSignals()));
11005 
11006     if (result == 0)
11007         Py_RETURN_NONE;
11008 
11009     if (async_err)
11010         return NULL;
11011 
11012     errno = result;
11013     return posix_error();
11014 }
11015 #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
11016 
11017 
11018 #ifdef MS_WINDOWS
11019 static PyObject*
win32_putenv(PyObject * name,PyObject * value)11020 win32_putenv(PyObject *name, PyObject *value)
11021 {
11022     /* Search from index 1 because on Windows starting '=' is allowed for
11023        defining hidden environment variables. */
11024     if (PyUnicode_GET_LENGTH(name) == 0 ||
11025         PyUnicode_FindChar(name, '=', 1, PyUnicode_GET_LENGTH(name), 1) != -1)
11026     {
11027         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11028         return NULL;
11029     }
11030     PyObject *unicode;
11031     if (value != NULL) {
11032         unicode = PyUnicode_FromFormat("%U=%U", name, value);
11033     }
11034     else {
11035         unicode = PyUnicode_FromFormat("%U=", name);
11036     }
11037     if (unicode == NULL) {
11038         return NULL;
11039     }
11040 
11041     Py_ssize_t size;
11042     /* PyUnicode_AsWideCharString() rejects embedded null characters */
11043     wchar_t *env = PyUnicode_AsWideCharString(unicode, &size);
11044     Py_DECREF(unicode);
11045 
11046     if (env == NULL) {
11047         return NULL;
11048     }
11049     if (size > _MAX_ENV) {
11050         PyErr_Format(PyExc_ValueError,
11051                      "the environment variable is longer than %u characters",
11052                      _MAX_ENV);
11053         PyMem_Free(env);
11054         return NULL;
11055     }
11056 
11057     /* _wputenv() and SetEnvironmentVariableW() update the environment in the
11058        Process Environment Block (PEB). _wputenv() also updates CRT 'environ'
11059        and '_wenviron' variables, whereas SetEnvironmentVariableW() does not.
11060 
11061        Prefer _wputenv() to be compatible with C libraries using CRT
11062        variables and CRT functions using these variables (ex: getenv()). */
11063     int err = _wputenv(env);
11064     PyMem_Free(env);
11065 
11066     if (err) {
11067         posix_error();
11068         return NULL;
11069     }
11070 
11071     Py_RETURN_NONE;
11072 }
11073 #endif
11074 
11075 
11076 #ifdef MS_WINDOWS
11077 /*[clinic input]
11078 os.putenv
11079 
11080     name: unicode
11081     value: unicode
11082     /
11083 
11084 Change or add an environment variable.
11085 [clinic start generated code]*/
11086 
11087 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11088 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11089 /*[clinic end generated code: output=d29a567d6b2327d2 input=ba586581c2e6105f]*/
11090 {
11091     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11092         return NULL;
11093     }
11094     return win32_putenv(name, value);
11095 }
11096 #else
11097 /*[clinic input]
11098 os.putenv
11099 
11100     name: FSConverter
11101     value: FSConverter
11102     /
11103 
11104 Change or add an environment variable.
11105 [clinic start generated code]*/
11106 
11107 static PyObject *
os_putenv_impl(PyObject * module,PyObject * name,PyObject * value)11108 os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
11109 /*[clinic end generated code: output=d29a567d6b2327d2 input=a97bc6152f688d31]*/
11110 {
11111     const char *name_string = PyBytes_AS_STRING(name);
11112     const char *value_string = PyBytes_AS_STRING(value);
11113 
11114     if (strchr(name_string, '=') != NULL) {
11115         PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
11116         return NULL;
11117     }
11118 
11119     if (PySys_Audit("os.putenv", "OO", name, value) < 0) {
11120         return NULL;
11121     }
11122 
11123     if (setenv(name_string, value_string, 1)) {
11124         return posix_error();
11125     }
11126     Py_RETURN_NONE;
11127 }
11128 #endif  /* !defined(MS_WINDOWS) */
11129 
11130 
11131 #ifdef MS_WINDOWS
11132 /*[clinic input]
11133 os.unsetenv
11134     name: unicode
11135     /
11136 
11137 Delete an environment variable.
11138 [clinic start generated code]*/
11139 
11140 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11141 os_unsetenv_impl(PyObject *module, PyObject *name)
11142 /*[clinic end generated code: output=54c4137ab1834f02 input=4d6a1747cc526d2f]*/
11143 {
11144     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11145         return NULL;
11146     }
11147     return win32_putenv(name, NULL);
11148 }
11149 #else
11150 /*[clinic input]
11151 os.unsetenv
11152     name: FSConverter
11153     /
11154 
11155 Delete an environment variable.
11156 [clinic start generated code]*/
11157 
11158 static PyObject *
os_unsetenv_impl(PyObject * module,PyObject * name)11159 os_unsetenv_impl(PyObject *module, PyObject *name)
11160 /*[clinic end generated code: output=54c4137ab1834f02 input=2bb5288a599c7107]*/
11161 {
11162     if (PySys_Audit("os.unsetenv", "(O)", name) < 0) {
11163         return NULL;
11164     }
11165 #ifdef HAVE_BROKEN_UNSETENV
11166     unsetenv(PyBytes_AS_STRING(name));
11167 #else
11168     int err = unsetenv(PyBytes_AS_STRING(name));
11169     if (err) {
11170         return posix_error();
11171     }
11172 #endif
11173 
11174     Py_RETURN_NONE;
11175 }
11176 #endif /* !MS_WINDOWS */
11177 
11178 
11179 /*[clinic input]
11180 os.strerror
11181 
11182     code: int
11183     /
11184 
11185 Translate an error code to a message string.
11186 [clinic start generated code]*/
11187 
11188 static PyObject *
os_strerror_impl(PyObject * module,int code)11189 os_strerror_impl(PyObject *module, int code)
11190 /*[clinic end generated code: output=baebf09fa02a78f2 input=75a8673d97915a91]*/
11191 {
11192     char *message = strerror(code);
11193     if (message == NULL) {
11194         PyErr_SetString(PyExc_ValueError,
11195                         "strerror() argument out of range");
11196         return NULL;
11197     }
11198     return PyUnicode_DecodeLocale(message, "surrogateescape");
11199 }
11200 
11201 
11202 #ifdef HAVE_SYS_WAIT_H
11203 #ifdef WCOREDUMP
11204 /*[clinic input]
11205 os.WCOREDUMP -> bool
11206 
11207     status: int
11208     /
11209 
11210 Return True if the process returning status was dumped to a core file.
11211 [clinic start generated code]*/
11212 
11213 static int
os_WCOREDUMP_impl(PyObject * module,int status)11214 os_WCOREDUMP_impl(PyObject *module, int status)
11215 /*[clinic end generated code: output=1a584b147b16bd18 input=8b05e7ab38528d04]*/
11216 {
11217     WAIT_TYPE wait_status;
11218     WAIT_STATUS_INT(wait_status) = status;
11219     return WCOREDUMP(wait_status);
11220 }
11221 #endif /* WCOREDUMP */
11222 
11223 
11224 #ifdef WIFCONTINUED
11225 /*[clinic input]
11226 os.WIFCONTINUED -> bool
11227 
11228     status: int
11229 
11230 Return True if a particular process was continued from a job control stop.
11231 
11232 Return True if the process returning status was continued from a
11233 job control stop.
11234 [clinic start generated code]*/
11235 
11236 static int
os_WIFCONTINUED_impl(PyObject * module,int status)11237 os_WIFCONTINUED_impl(PyObject *module, int status)
11238 /*[clinic end generated code: output=1e35295d844364bd input=e777e7d38eb25bd9]*/
11239 {
11240     WAIT_TYPE wait_status;
11241     WAIT_STATUS_INT(wait_status) = status;
11242     return WIFCONTINUED(wait_status);
11243 }
11244 #endif /* WIFCONTINUED */
11245 
11246 
11247 #ifdef WIFSTOPPED
11248 /*[clinic input]
11249 os.WIFSTOPPED -> bool
11250 
11251     status: int
11252 
11253 Return True if the process returning status was stopped.
11254 [clinic start generated code]*/
11255 
11256 static int
os_WIFSTOPPED_impl(PyObject * module,int status)11257 os_WIFSTOPPED_impl(PyObject *module, int status)
11258 /*[clinic end generated code: output=fdb57122a5c9b4cb input=043cb7f1289ef904]*/
11259 {
11260     WAIT_TYPE wait_status;
11261     WAIT_STATUS_INT(wait_status) = status;
11262     return WIFSTOPPED(wait_status);
11263 }
11264 #endif /* WIFSTOPPED */
11265 
11266 
11267 #ifdef WIFSIGNALED
11268 /*[clinic input]
11269 os.WIFSIGNALED -> bool
11270 
11271     status: int
11272 
11273 Return True if the process returning status was terminated by a signal.
11274 [clinic start generated code]*/
11275 
11276 static int
os_WIFSIGNALED_impl(PyObject * module,int status)11277 os_WIFSIGNALED_impl(PyObject *module, int status)
11278 /*[clinic end generated code: output=d1dde4dcc819a5f5 input=d55ba7cc9ce5dc43]*/
11279 {
11280     WAIT_TYPE wait_status;
11281     WAIT_STATUS_INT(wait_status) = status;
11282     return WIFSIGNALED(wait_status);
11283 }
11284 #endif /* WIFSIGNALED */
11285 
11286 
11287 #ifdef WIFEXITED
11288 /*[clinic input]
11289 os.WIFEXITED -> bool
11290 
11291     status: int
11292 
11293 Return True if the process returning status exited via the exit() system call.
11294 [clinic start generated code]*/
11295 
11296 static int
os_WIFEXITED_impl(PyObject * module,int status)11297 os_WIFEXITED_impl(PyObject *module, int status)
11298 /*[clinic end generated code: output=01c09d6ebfeea397 input=d63775a6791586c0]*/
11299 {
11300     WAIT_TYPE wait_status;
11301     WAIT_STATUS_INT(wait_status) = status;
11302     return WIFEXITED(wait_status);
11303 }
11304 #endif /* WIFEXITED */
11305 
11306 
11307 #ifdef WEXITSTATUS
11308 /*[clinic input]
11309 os.WEXITSTATUS -> int
11310 
11311     status: int
11312 
11313 Return the process return code from status.
11314 [clinic start generated code]*/
11315 
11316 static int
os_WEXITSTATUS_impl(PyObject * module,int status)11317 os_WEXITSTATUS_impl(PyObject *module, int status)
11318 /*[clinic end generated code: output=6e3efbba11f6488d input=e1fb4944e377585b]*/
11319 {
11320     WAIT_TYPE wait_status;
11321     WAIT_STATUS_INT(wait_status) = status;
11322     return WEXITSTATUS(wait_status);
11323 }
11324 #endif /* WEXITSTATUS */
11325 
11326 
11327 #ifdef WTERMSIG
11328 /*[clinic input]
11329 os.WTERMSIG -> int
11330 
11331     status: int
11332 
11333 Return the signal that terminated the process that provided the status value.
11334 [clinic start generated code]*/
11335 
11336 static int
os_WTERMSIG_impl(PyObject * module,int status)11337 os_WTERMSIG_impl(PyObject *module, int status)
11338 /*[clinic end generated code: output=172f7dfc8dcfc3ad input=727fd7f84ec3f243]*/
11339 {
11340     WAIT_TYPE wait_status;
11341     WAIT_STATUS_INT(wait_status) = status;
11342     return WTERMSIG(wait_status);
11343 }
11344 #endif /* WTERMSIG */
11345 
11346 
11347 #ifdef WSTOPSIG
11348 /*[clinic input]
11349 os.WSTOPSIG -> int
11350 
11351     status: int
11352 
11353 Return the signal that stopped the process that provided the status value.
11354 [clinic start generated code]*/
11355 
11356 static int
os_WSTOPSIG_impl(PyObject * module,int status)11357 os_WSTOPSIG_impl(PyObject *module, int status)
11358 /*[clinic end generated code: output=0ab7586396f5d82b input=46ebf1d1b293c5c1]*/
11359 {
11360     WAIT_TYPE wait_status;
11361     WAIT_STATUS_INT(wait_status) = status;
11362     return WSTOPSIG(wait_status);
11363 }
11364 #endif /* WSTOPSIG */
11365 #endif /* HAVE_SYS_WAIT_H */
11366 
11367 
11368 #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
11369 #ifdef _SCO_DS
11370 /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
11371    needed definitions in sys/statvfs.h */
11372 #define _SVID3
11373 #endif
11374 #include <sys/statvfs.h>
11375 
11376 static PyObject*
_pystatvfs_fromstructstatvfs(PyObject * module,struct statvfs st)11377 _pystatvfs_fromstructstatvfs(PyObject *module, struct statvfs st) {
11378     PyObject *StatVFSResultType = get_posix_state(module)->StatVFSResultType;
11379     PyObject *v = PyStructSequence_New((PyTypeObject *)StatVFSResultType);
11380     if (v == NULL)
11381         return NULL;
11382 
11383 #if !defined(HAVE_LARGEFILE_SUPPORT)
11384     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11385     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11386     PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
11387     PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
11388     PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
11389     PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
11390     PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
11391     PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
11392     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11393     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11394 #else
11395     PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
11396     PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
11397     PyStructSequence_SET_ITEM(v, 2,
11398                               PyLong_FromLongLong((long long) st.f_blocks));
11399     PyStructSequence_SET_ITEM(v, 3,
11400                               PyLong_FromLongLong((long long) st.f_bfree));
11401     PyStructSequence_SET_ITEM(v, 4,
11402                               PyLong_FromLongLong((long long) st.f_bavail));
11403     PyStructSequence_SET_ITEM(v, 5,
11404                               PyLong_FromLongLong((long long) st.f_files));
11405     PyStructSequence_SET_ITEM(v, 6,
11406                               PyLong_FromLongLong((long long) st.f_ffree));
11407     PyStructSequence_SET_ITEM(v, 7,
11408                               PyLong_FromLongLong((long long) st.f_favail));
11409     PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
11410     PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
11411 #endif
11412 /* The _ALL_SOURCE feature test macro defines f_fsid as a structure
11413  * (issue #32390). */
11414 #if defined(_AIX) && defined(_ALL_SOURCE)
11415     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid.val[0]));
11416 #else
11417     PyStructSequence_SET_ITEM(v, 10, PyLong_FromUnsignedLong(st.f_fsid));
11418 #endif
11419     if (PyErr_Occurred()) {
11420         Py_DECREF(v);
11421         return NULL;
11422     }
11423 
11424     return v;
11425 }
11426 
11427 
11428 /*[clinic input]
11429 os.fstatvfs
11430     fd: int
11431     /
11432 
11433 Perform an fstatvfs system call on the given fd.
11434 
11435 Equivalent to statvfs(fd).
11436 [clinic start generated code]*/
11437 
11438 static PyObject *
os_fstatvfs_impl(PyObject * module,int fd)11439 os_fstatvfs_impl(PyObject *module, int fd)
11440 /*[clinic end generated code: output=53547cf0cc55e6c5 input=d8122243ac50975e]*/
11441 {
11442     int result;
11443     int async_err = 0;
11444     struct statvfs st;
11445 
11446     do {
11447         Py_BEGIN_ALLOW_THREADS
11448         result = fstatvfs(fd, &st);
11449         Py_END_ALLOW_THREADS
11450     } while (result != 0 && errno == EINTR &&
11451              !(async_err = PyErr_CheckSignals()));
11452     if (result != 0)
11453         return (!async_err) ? posix_error() : NULL;
11454 
11455     return _pystatvfs_fromstructstatvfs(module, st);
11456 }
11457 #endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */
11458 
11459 
11460 #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
11461 #include <sys/statvfs.h>
11462 /*[clinic input]
11463 os.statvfs
11464 
11465     path: path_t(allow_fd='PATH_HAVE_FSTATVFS')
11466 
11467 Perform a statvfs system call on the given path.
11468 
11469 path may always be specified as a string.
11470 On some platforms, path may also be specified as an open file descriptor.
11471   If this functionality is unavailable, using it raises an exception.
11472 [clinic start generated code]*/
11473 
11474 static PyObject *
os_statvfs_impl(PyObject * module,path_t * path)11475 os_statvfs_impl(PyObject *module, path_t *path)
11476 /*[clinic end generated code: output=87106dd1beb8556e input=3f5c35791c669bd9]*/
11477 {
11478     int result;
11479     struct statvfs st;
11480 
11481     Py_BEGIN_ALLOW_THREADS
11482 #ifdef HAVE_FSTATVFS
11483     if (path->fd != -1) {
11484         result = fstatvfs(path->fd, &st);
11485     }
11486     else
11487 #endif
11488         result = statvfs(path->narrow, &st);
11489     Py_END_ALLOW_THREADS
11490 
11491     if (result) {
11492         return path_error(path);
11493     }
11494 
11495     return _pystatvfs_fromstructstatvfs(module, st);
11496 }
11497 #endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */
11498 
11499 
11500 #ifdef MS_WINDOWS
11501 /*[clinic input]
11502 os._getdiskusage
11503 
11504     path: path_t
11505 
11506 Return disk usage statistics about the given path as a (total, free) tuple.
11507 [clinic start generated code]*/
11508 
11509 static PyObject *
os__getdiskusage_impl(PyObject * module,path_t * path)11510 os__getdiskusage_impl(PyObject *module, path_t *path)
11511 /*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/
11512 {
11513     BOOL retval;
11514     ULARGE_INTEGER _, total, free;
11515     DWORD err = 0;
11516 
11517     Py_BEGIN_ALLOW_THREADS
11518     retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free);
11519     Py_END_ALLOW_THREADS
11520     if (retval == 0) {
11521         if (GetLastError() == ERROR_DIRECTORY) {
11522             wchar_t *dir_path = NULL;
11523 
11524             dir_path = PyMem_New(wchar_t, path->length + 1);
11525             if (dir_path == NULL) {
11526                 return PyErr_NoMemory();
11527             }
11528 
11529             wcscpy_s(dir_path, path->length + 1, path->wide);
11530 
11531             if (_dirnameW(dir_path) != -1) {
11532                 Py_BEGIN_ALLOW_THREADS
11533                 retval = GetDiskFreeSpaceExW(dir_path, &_, &total, &free);
11534                 Py_END_ALLOW_THREADS
11535             }
11536             /* Record the last error in case it's modified by PyMem_Free. */
11537             err = GetLastError();
11538             PyMem_Free(dir_path);
11539             if (retval) {
11540                 goto success;
11541             }
11542         }
11543         return PyErr_SetFromWindowsErr(err);
11544     }
11545 
11546 success:
11547     return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
11548 }
11549 #endif /* MS_WINDOWS */
11550 
11551 
11552 /* This is used for fpathconf(), pathconf(), confstr() and sysconf().
11553  * It maps strings representing configuration variable names to
11554  * integer values, allowing those functions to be called with the
11555  * magic names instead of polluting the module's namespace with tons of
11556  * rarely-used constants.  There are three separate tables that use
11557  * these definitions.
11558  *
11559  * This code is always included, even if none of the interfaces that
11560  * need it are included.  The #if hackery needed to avoid it would be
11561  * sufficiently pervasive that it's not worth the loss of readability.
11562  */
11563 struct constdef {
11564     const char *name;
11565     int value;
11566 };
11567 
11568 static int
conv_confname(PyObject * arg,int * valuep,struct constdef * table,size_t tablesize)11569 conv_confname(PyObject *arg, int *valuep, struct constdef *table,
11570               size_t tablesize)
11571 {
11572     if (PyLong_Check(arg)) {
11573         int value = _PyLong_AsInt(arg);
11574         if (value == -1 && PyErr_Occurred())
11575             return 0;
11576         *valuep = value;
11577         return 1;
11578     }
11579     else {
11580         /* look up the value in the table using a binary search */
11581         size_t lo = 0;
11582         size_t mid;
11583         size_t hi = tablesize;
11584         int cmp;
11585         const char *confname;
11586         if (!PyUnicode_Check(arg)) {
11587             PyErr_SetString(PyExc_TypeError,
11588                 "configuration names must be strings or integers");
11589             return 0;
11590         }
11591         confname = PyUnicode_AsUTF8(arg);
11592         if (confname == NULL)
11593             return 0;
11594         while (lo < hi) {
11595             mid = (lo + hi) / 2;
11596             cmp = strcmp(confname, table[mid].name);
11597             if (cmp < 0)
11598                 hi = mid;
11599             else if (cmp > 0)
11600                 lo = mid + 1;
11601             else {
11602                 *valuep = table[mid].value;
11603                 return 1;
11604             }
11605         }
11606         PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
11607         return 0;
11608     }
11609 }
11610 
11611 
11612 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
11613 static struct constdef  posix_constants_pathconf[] = {
11614 #ifdef _PC_ABI_AIO_XFER_MAX
11615     {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
11616 #endif
11617 #ifdef _PC_ABI_ASYNC_IO
11618     {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
11619 #endif
11620 #ifdef _PC_ASYNC_IO
11621     {"PC_ASYNC_IO",     _PC_ASYNC_IO},
11622 #endif
11623 #ifdef _PC_CHOWN_RESTRICTED
11624     {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
11625 #endif
11626 #ifdef _PC_FILESIZEBITS
11627     {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
11628 #endif
11629 #ifdef _PC_LAST
11630     {"PC_LAST", _PC_LAST},
11631 #endif
11632 #ifdef _PC_LINK_MAX
11633     {"PC_LINK_MAX",     _PC_LINK_MAX},
11634 #endif
11635 #ifdef _PC_MAX_CANON
11636     {"PC_MAX_CANON",    _PC_MAX_CANON},
11637 #endif
11638 #ifdef _PC_MAX_INPUT
11639     {"PC_MAX_INPUT",    _PC_MAX_INPUT},
11640 #endif
11641 #ifdef _PC_NAME_MAX
11642     {"PC_NAME_MAX",     _PC_NAME_MAX},
11643 #endif
11644 #ifdef _PC_NO_TRUNC
11645     {"PC_NO_TRUNC",     _PC_NO_TRUNC},
11646 #endif
11647 #ifdef _PC_PATH_MAX
11648     {"PC_PATH_MAX",     _PC_PATH_MAX},
11649 #endif
11650 #ifdef _PC_PIPE_BUF
11651     {"PC_PIPE_BUF",     _PC_PIPE_BUF},
11652 #endif
11653 #ifdef _PC_PRIO_IO
11654     {"PC_PRIO_IO",      _PC_PRIO_IO},
11655 #endif
11656 #ifdef _PC_SOCK_MAXBUF
11657     {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
11658 #endif
11659 #ifdef _PC_SYNC_IO
11660     {"PC_SYNC_IO",      _PC_SYNC_IO},
11661 #endif
11662 #ifdef _PC_VDISABLE
11663     {"PC_VDISABLE",     _PC_VDISABLE},
11664 #endif
11665 #ifdef _PC_ACL_ENABLED
11666     {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
11667 #endif
11668 #ifdef _PC_MIN_HOLE_SIZE
11669     {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
11670 #endif
11671 #ifdef _PC_ALLOC_SIZE_MIN
11672     {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
11673 #endif
11674 #ifdef _PC_REC_INCR_XFER_SIZE
11675     {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
11676 #endif
11677 #ifdef _PC_REC_MAX_XFER_SIZE
11678     {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
11679 #endif
11680 #ifdef _PC_REC_MIN_XFER_SIZE
11681     {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
11682 #endif
11683 #ifdef _PC_REC_XFER_ALIGN
11684     {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
11685 #endif
11686 #ifdef _PC_SYMLINK_MAX
11687     {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
11688 #endif
11689 #ifdef _PC_XATTR_ENABLED
11690     {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
11691 #endif
11692 #ifdef _PC_XATTR_EXISTS
11693     {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
11694 #endif
11695 #ifdef _PC_TIMESTAMP_RESOLUTION
11696     {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
11697 #endif
11698 };
11699 
11700 static int
conv_path_confname(PyObject * arg,int * valuep)11701 conv_path_confname(PyObject *arg, int *valuep)
11702 {
11703     return conv_confname(arg, valuep, posix_constants_pathconf,
11704                          sizeof(posix_constants_pathconf)
11705                            / sizeof(struct constdef));
11706 }
11707 #endif
11708 
11709 
11710 #ifdef HAVE_FPATHCONF
11711 /*[clinic input]
11712 os.fpathconf -> long
11713 
11714     fd: fildes
11715     name: path_confname
11716     /
11717 
11718 Return the configuration limit name for the file descriptor fd.
11719 
11720 If there is no limit, return -1.
11721 [clinic start generated code]*/
11722 
11723 static long
os_fpathconf_impl(PyObject * module,int fd,int name)11724 os_fpathconf_impl(PyObject *module, int fd, int name)
11725 /*[clinic end generated code: output=d5b7042425fc3e21 input=5b8d2471cfaae186]*/
11726 {
11727     long limit;
11728 
11729     errno = 0;
11730     limit = fpathconf(fd, name);
11731     if (limit == -1 && errno != 0)
11732         posix_error();
11733 
11734     return limit;
11735 }
11736 #endif /* HAVE_FPATHCONF */
11737 
11738 
11739 #ifdef HAVE_PATHCONF
11740 /*[clinic input]
11741 os.pathconf -> long
11742     path: path_t(allow_fd='PATH_HAVE_FPATHCONF')
11743     name: path_confname
11744 
11745 Return the configuration limit name for the file or directory path.
11746 
11747 If there is no limit, return -1.
11748 On some platforms, path may also be specified as an open file descriptor.
11749   If this functionality is unavailable, using it raises an exception.
11750 [clinic start generated code]*/
11751 
11752 static long
os_pathconf_impl(PyObject * module,path_t * path,int name)11753 os_pathconf_impl(PyObject *module, path_t *path, int name)
11754 /*[clinic end generated code: output=5bedee35b293a089 input=bc3e2a985af27e5e]*/
11755 {
11756     long limit;
11757 
11758     errno = 0;
11759 #ifdef HAVE_FPATHCONF
11760     if (path->fd != -1)
11761         limit = fpathconf(path->fd, name);
11762     else
11763 #endif
11764         limit = pathconf(path->narrow, name);
11765     if (limit == -1 && errno != 0) {
11766         if (errno == EINVAL)
11767             /* could be a path or name problem */
11768             posix_error();
11769         else
11770             path_error(path);
11771     }
11772 
11773     return limit;
11774 }
11775 #endif /* HAVE_PATHCONF */
11776 
11777 #ifdef HAVE_CONFSTR
11778 static struct constdef posix_constants_confstr[] = {
11779 #ifdef _CS_ARCHITECTURE
11780     {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
11781 #endif
11782 #ifdef _CS_GNU_LIBC_VERSION
11783     {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
11784 #endif
11785 #ifdef _CS_GNU_LIBPTHREAD_VERSION
11786     {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
11787 #endif
11788 #ifdef _CS_HOSTNAME
11789     {"CS_HOSTNAME",     _CS_HOSTNAME},
11790 #endif
11791 #ifdef _CS_HW_PROVIDER
11792     {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
11793 #endif
11794 #ifdef _CS_HW_SERIAL
11795     {"CS_HW_SERIAL",    _CS_HW_SERIAL},
11796 #endif
11797 #ifdef _CS_INITTAB_NAME
11798     {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
11799 #endif
11800 #ifdef _CS_LFS64_CFLAGS
11801     {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
11802 #endif
11803 #ifdef _CS_LFS64_LDFLAGS
11804     {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
11805 #endif
11806 #ifdef _CS_LFS64_LIBS
11807     {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
11808 #endif
11809 #ifdef _CS_LFS64_LINTFLAGS
11810     {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
11811 #endif
11812 #ifdef _CS_LFS_CFLAGS
11813     {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
11814 #endif
11815 #ifdef _CS_LFS_LDFLAGS
11816     {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
11817 #endif
11818 #ifdef _CS_LFS_LIBS
11819     {"CS_LFS_LIBS",     _CS_LFS_LIBS},
11820 #endif
11821 #ifdef _CS_LFS_LINTFLAGS
11822     {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
11823 #endif
11824 #ifdef _CS_MACHINE
11825     {"CS_MACHINE",      _CS_MACHINE},
11826 #endif
11827 #ifdef _CS_PATH
11828     {"CS_PATH", _CS_PATH},
11829 #endif
11830 #ifdef _CS_RELEASE
11831     {"CS_RELEASE",      _CS_RELEASE},
11832 #endif
11833 #ifdef _CS_SRPC_DOMAIN
11834     {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
11835 #endif
11836 #ifdef _CS_SYSNAME
11837     {"CS_SYSNAME",      _CS_SYSNAME},
11838 #endif
11839 #ifdef _CS_VERSION
11840     {"CS_VERSION",      _CS_VERSION},
11841 #endif
11842 #ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
11843     {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
11844 #endif
11845 #ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
11846     {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
11847 #endif
11848 #ifdef _CS_XBS5_ILP32_OFF32_LIBS
11849     {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
11850 #endif
11851 #ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
11852     {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
11853 #endif
11854 #ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
11855     {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
11856 #endif
11857 #ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
11858     {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
11859 #endif
11860 #ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
11861     {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
11862 #endif
11863 #ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
11864     {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
11865 #endif
11866 #ifdef _CS_XBS5_LP64_OFF64_CFLAGS
11867     {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
11868 #endif
11869 #ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
11870     {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
11871 #endif
11872 #ifdef _CS_XBS5_LP64_OFF64_LIBS
11873     {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
11874 #endif
11875 #ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
11876     {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
11877 #endif
11878 #ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
11879     {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
11880 #endif
11881 #ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
11882     {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
11883 #endif
11884 #ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
11885     {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
11886 #endif
11887 #ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
11888     {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
11889 #endif
11890 #ifdef _MIPS_CS_AVAIL_PROCESSORS
11891     {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
11892 #endif
11893 #ifdef _MIPS_CS_BASE
11894     {"MIPS_CS_BASE",    _MIPS_CS_BASE},
11895 #endif
11896 #ifdef _MIPS_CS_HOSTID
11897     {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
11898 #endif
11899 #ifdef _MIPS_CS_HW_NAME
11900     {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
11901 #endif
11902 #ifdef _MIPS_CS_NUM_PROCESSORS
11903     {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
11904 #endif
11905 #ifdef _MIPS_CS_OSREL_MAJ
11906     {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
11907 #endif
11908 #ifdef _MIPS_CS_OSREL_MIN
11909     {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
11910 #endif
11911 #ifdef _MIPS_CS_OSREL_PATCH
11912     {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
11913 #endif
11914 #ifdef _MIPS_CS_OS_NAME
11915     {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
11916 #endif
11917 #ifdef _MIPS_CS_OS_PROVIDER
11918     {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
11919 #endif
11920 #ifdef _MIPS_CS_PROCESSORS
11921     {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
11922 #endif
11923 #ifdef _MIPS_CS_SERIAL
11924     {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
11925 #endif
11926 #ifdef _MIPS_CS_VENDOR
11927     {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
11928 #endif
11929 };
11930 
11931 static int
conv_confstr_confname(PyObject * arg,int * valuep)11932 conv_confstr_confname(PyObject *arg, int *valuep)
11933 {
11934     return conv_confname(arg, valuep, posix_constants_confstr,
11935                          sizeof(posix_constants_confstr)
11936                            / sizeof(struct constdef));
11937 }
11938 
11939 
11940 /*[clinic input]
11941 os.confstr
11942 
11943     name: confstr_confname
11944     /
11945 
11946 Return a string-valued system configuration variable.
11947 [clinic start generated code]*/
11948 
11949 static PyObject *
os_confstr_impl(PyObject * module,int name)11950 os_confstr_impl(PyObject *module, int name)
11951 /*[clinic end generated code: output=bfb0b1b1e49b9383 input=18fb4d0567242e65]*/
11952 {
11953     PyObject *result = NULL;
11954     char buffer[255];
11955     size_t len;
11956 
11957     errno = 0;
11958     len = confstr(name, buffer, sizeof(buffer));
11959     if (len == 0) {
11960         if (errno) {
11961             posix_error();
11962             return NULL;
11963         }
11964         else {
11965             Py_RETURN_NONE;
11966         }
11967     }
11968 
11969     if (len >= sizeof(buffer)) {
11970         size_t len2;
11971         char *buf = PyMem_Malloc(len);
11972         if (buf == NULL)
11973             return PyErr_NoMemory();
11974         len2 = confstr(name, buf, len);
11975         assert(len == len2);
11976         result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1);
11977         PyMem_Free(buf);
11978     }
11979     else
11980         result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
11981     return result;
11982 }
11983 #endif /* HAVE_CONFSTR */
11984 
11985 
11986 #ifdef HAVE_SYSCONF
11987 static struct constdef posix_constants_sysconf[] = {
11988 #ifdef _SC_2_CHAR_TERM
11989     {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
11990 #endif
11991 #ifdef _SC_2_C_BIND
11992     {"SC_2_C_BIND",     _SC_2_C_BIND},
11993 #endif
11994 #ifdef _SC_2_C_DEV
11995     {"SC_2_C_DEV",      _SC_2_C_DEV},
11996 #endif
11997 #ifdef _SC_2_C_VERSION
11998     {"SC_2_C_VERSION",  _SC_2_C_VERSION},
11999 #endif
12000 #ifdef _SC_2_FORT_DEV
12001     {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
12002 #endif
12003 #ifdef _SC_2_FORT_RUN
12004     {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
12005 #endif
12006 #ifdef _SC_2_LOCALEDEF
12007     {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
12008 #endif
12009 #ifdef _SC_2_SW_DEV
12010     {"SC_2_SW_DEV",     _SC_2_SW_DEV},
12011 #endif
12012 #ifdef _SC_2_UPE
12013     {"SC_2_UPE",        _SC_2_UPE},
12014 #endif
12015 #ifdef _SC_2_VERSION
12016     {"SC_2_VERSION",    _SC_2_VERSION},
12017 #endif
12018 #ifdef _SC_ABI_ASYNCHRONOUS_IO
12019     {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
12020 #endif
12021 #ifdef _SC_ACL
12022     {"SC_ACL",  _SC_ACL},
12023 #endif
12024 #ifdef _SC_AIO_LISTIO_MAX
12025     {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
12026 #endif
12027 #ifdef _SC_AIO_MAX
12028     {"SC_AIO_MAX",      _SC_AIO_MAX},
12029 #endif
12030 #ifdef _SC_AIO_PRIO_DELTA_MAX
12031     {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
12032 #endif
12033 #ifdef _SC_ARG_MAX
12034     {"SC_ARG_MAX",      _SC_ARG_MAX},
12035 #endif
12036 #ifdef _SC_ASYNCHRONOUS_IO
12037     {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
12038 #endif
12039 #ifdef _SC_ATEXIT_MAX
12040     {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
12041 #endif
12042 #ifdef _SC_AUDIT
12043     {"SC_AUDIT",        _SC_AUDIT},
12044 #endif
12045 #ifdef _SC_AVPHYS_PAGES
12046     {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
12047 #endif
12048 #ifdef _SC_BC_BASE_MAX
12049     {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
12050 #endif
12051 #ifdef _SC_BC_DIM_MAX
12052     {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
12053 #endif
12054 #ifdef _SC_BC_SCALE_MAX
12055     {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
12056 #endif
12057 #ifdef _SC_BC_STRING_MAX
12058     {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
12059 #endif
12060 #ifdef _SC_CAP
12061     {"SC_CAP",  _SC_CAP},
12062 #endif
12063 #ifdef _SC_CHARCLASS_NAME_MAX
12064     {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
12065 #endif
12066 #ifdef _SC_CHAR_BIT
12067     {"SC_CHAR_BIT",     _SC_CHAR_BIT},
12068 #endif
12069 #ifdef _SC_CHAR_MAX
12070     {"SC_CHAR_MAX",     _SC_CHAR_MAX},
12071 #endif
12072 #ifdef _SC_CHAR_MIN
12073     {"SC_CHAR_MIN",     _SC_CHAR_MIN},
12074 #endif
12075 #ifdef _SC_CHILD_MAX
12076     {"SC_CHILD_MAX",    _SC_CHILD_MAX},
12077 #endif
12078 #ifdef _SC_CLK_TCK
12079     {"SC_CLK_TCK",      _SC_CLK_TCK},
12080 #endif
12081 #ifdef _SC_COHER_BLKSZ
12082     {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
12083 #endif
12084 #ifdef _SC_COLL_WEIGHTS_MAX
12085     {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
12086 #endif
12087 #ifdef _SC_DCACHE_ASSOC
12088     {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
12089 #endif
12090 #ifdef _SC_DCACHE_BLKSZ
12091     {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
12092 #endif
12093 #ifdef _SC_DCACHE_LINESZ
12094     {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
12095 #endif
12096 #ifdef _SC_DCACHE_SZ
12097     {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
12098 #endif
12099 #ifdef _SC_DCACHE_TBLKSZ
12100     {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
12101 #endif
12102 #ifdef _SC_DELAYTIMER_MAX
12103     {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
12104 #endif
12105 #ifdef _SC_EQUIV_CLASS_MAX
12106     {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
12107 #endif
12108 #ifdef _SC_EXPR_NEST_MAX
12109     {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
12110 #endif
12111 #ifdef _SC_FSYNC
12112     {"SC_FSYNC",        _SC_FSYNC},
12113 #endif
12114 #ifdef _SC_GETGR_R_SIZE_MAX
12115     {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
12116 #endif
12117 #ifdef _SC_GETPW_R_SIZE_MAX
12118     {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
12119 #endif
12120 #ifdef _SC_ICACHE_ASSOC
12121     {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
12122 #endif
12123 #ifdef _SC_ICACHE_BLKSZ
12124     {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
12125 #endif
12126 #ifdef _SC_ICACHE_LINESZ
12127     {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
12128 #endif
12129 #ifdef _SC_ICACHE_SZ
12130     {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
12131 #endif
12132 #ifdef _SC_INF
12133     {"SC_INF",  _SC_INF},
12134 #endif
12135 #ifdef _SC_INT_MAX
12136     {"SC_INT_MAX",      _SC_INT_MAX},
12137 #endif
12138 #ifdef _SC_INT_MIN
12139     {"SC_INT_MIN",      _SC_INT_MIN},
12140 #endif
12141 #ifdef _SC_IOV_MAX
12142     {"SC_IOV_MAX",      _SC_IOV_MAX},
12143 #endif
12144 #ifdef _SC_IP_SECOPTS
12145     {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
12146 #endif
12147 #ifdef _SC_JOB_CONTROL
12148     {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
12149 #endif
12150 #ifdef _SC_KERN_POINTERS
12151     {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
12152 #endif
12153 #ifdef _SC_KERN_SIM
12154     {"SC_KERN_SIM",     _SC_KERN_SIM},
12155 #endif
12156 #ifdef _SC_LINE_MAX
12157     {"SC_LINE_MAX",     _SC_LINE_MAX},
12158 #endif
12159 #ifdef _SC_LOGIN_NAME_MAX
12160     {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
12161 #endif
12162 #ifdef _SC_LOGNAME_MAX
12163     {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
12164 #endif
12165 #ifdef _SC_LONG_BIT
12166     {"SC_LONG_BIT",     _SC_LONG_BIT},
12167 #endif
12168 #ifdef _SC_MAC
12169     {"SC_MAC",  _SC_MAC},
12170 #endif
12171 #ifdef _SC_MAPPED_FILES
12172     {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
12173 #endif
12174 #ifdef _SC_MAXPID
12175     {"SC_MAXPID",       _SC_MAXPID},
12176 #endif
12177 #ifdef _SC_MB_LEN_MAX
12178     {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
12179 #endif
12180 #ifdef _SC_MEMLOCK
12181     {"SC_MEMLOCK",      _SC_MEMLOCK},
12182 #endif
12183 #ifdef _SC_MEMLOCK_RANGE
12184     {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
12185 #endif
12186 #ifdef _SC_MEMORY_PROTECTION
12187     {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
12188 #endif
12189 #ifdef _SC_MESSAGE_PASSING
12190     {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
12191 #endif
12192 #ifdef _SC_MMAP_FIXED_ALIGNMENT
12193     {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
12194 #endif
12195 #ifdef _SC_MQ_OPEN_MAX
12196     {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
12197 #endif
12198 #ifdef _SC_MQ_PRIO_MAX
12199     {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
12200 #endif
12201 #ifdef _SC_NACLS_MAX
12202     {"SC_NACLS_MAX",    _SC_NACLS_MAX},
12203 #endif
12204 #ifdef _SC_NGROUPS_MAX
12205     {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
12206 #endif
12207 #ifdef _SC_NL_ARGMAX
12208     {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
12209 #endif
12210 #ifdef _SC_NL_LANGMAX
12211     {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
12212 #endif
12213 #ifdef _SC_NL_MSGMAX
12214     {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
12215 #endif
12216 #ifdef _SC_NL_NMAX
12217     {"SC_NL_NMAX",      _SC_NL_NMAX},
12218 #endif
12219 #ifdef _SC_NL_SETMAX
12220     {"SC_NL_SETMAX",    _SC_NL_SETMAX},
12221 #endif
12222 #ifdef _SC_NL_TEXTMAX
12223     {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
12224 #endif
12225 #ifdef _SC_NPROCESSORS_CONF
12226     {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
12227 #endif
12228 #ifdef _SC_NPROCESSORS_ONLN
12229     {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
12230 #endif
12231 #ifdef _SC_NPROC_CONF
12232     {"SC_NPROC_CONF",   _SC_NPROC_CONF},
12233 #endif
12234 #ifdef _SC_NPROC_ONLN
12235     {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
12236 #endif
12237 #ifdef _SC_NZERO
12238     {"SC_NZERO",        _SC_NZERO},
12239 #endif
12240 #ifdef _SC_OPEN_MAX
12241     {"SC_OPEN_MAX",     _SC_OPEN_MAX},
12242 #endif
12243 #ifdef _SC_PAGESIZE
12244     {"SC_PAGESIZE",     _SC_PAGESIZE},
12245 #endif
12246 #ifdef _SC_PAGE_SIZE
12247     {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
12248 #endif
12249 #ifdef _SC_AIX_REALMEM
12250     {"SC_AIX_REALMEM", _SC_AIX_REALMEM},
12251 #endif
12252 #ifdef _SC_PASS_MAX
12253     {"SC_PASS_MAX",     _SC_PASS_MAX},
12254 #endif
12255 #ifdef _SC_PHYS_PAGES
12256     {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
12257 #endif
12258 #ifdef _SC_PII
12259     {"SC_PII",  _SC_PII},
12260 #endif
12261 #ifdef _SC_PII_INTERNET
12262     {"SC_PII_INTERNET", _SC_PII_INTERNET},
12263 #endif
12264 #ifdef _SC_PII_INTERNET_DGRAM
12265     {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
12266 #endif
12267 #ifdef _SC_PII_INTERNET_STREAM
12268     {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
12269 #endif
12270 #ifdef _SC_PII_OSI
12271     {"SC_PII_OSI",      _SC_PII_OSI},
12272 #endif
12273 #ifdef _SC_PII_OSI_CLTS
12274     {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
12275 #endif
12276 #ifdef _SC_PII_OSI_COTS
12277     {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
12278 #endif
12279 #ifdef _SC_PII_OSI_M
12280     {"SC_PII_OSI_M",    _SC_PII_OSI_M},
12281 #endif
12282 #ifdef _SC_PII_SOCKET
12283     {"SC_PII_SOCKET",   _SC_PII_SOCKET},
12284 #endif
12285 #ifdef _SC_PII_XTI
12286     {"SC_PII_XTI",      _SC_PII_XTI},
12287 #endif
12288 #ifdef _SC_POLL
12289     {"SC_POLL", _SC_POLL},
12290 #endif
12291 #ifdef _SC_PRIORITIZED_IO
12292     {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
12293 #endif
12294 #ifdef _SC_PRIORITY_SCHEDULING
12295     {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
12296 #endif
12297 #ifdef _SC_REALTIME_SIGNALS
12298     {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
12299 #endif
12300 #ifdef _SC_RE_DUP_MAX
12301     {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
12302 #endif
12303 #ifdef _SC_RTSIG_MAX
12304     {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
12305 #endif
12306 #ifdef _SC_SAVED_IDS
12307     {"SC_SAVED_IDS",    _SC_SAVED_IDS},
12308 #endif
12309 #ifdef _SC_SCHAR_MAX
12310     {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
12311 #endif
12312 #ifdef _SC_SCHAR_MIN
12313     {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
12314 #endif
12315 #ifdef _SC_SELECT
12316     {"SC_SELECT",       _SC_SELECT},
12317 #endif
12318 #ifdef _SC_SEMAPHORES
12319     {"SC_SEMAPHORES",   _SC_SEMAPHORES},
12320 #endif
12321 #ifdef _SC_SEM_NSEMS_MAX
12322     {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
12323 #endif
12324 #ifdef _SC_SEM_VALUE_MAX
12325     {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
12326 #endif
12327 #ifdef _SC_SHARED_MEMORY_OBJECTS
12328     {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
12329 #endif
12330 #ifdef _SC_SHRT_MAX
12331     {"SC_SHRT_MAX",     _SC_SHRT_MAX},
12332 #endif
12333 #ifdef _SC_SHRT_MIN
12334     {"SC_SHRT_MIN",     _SC_SHRT_MIN},
12335 #endif
12336 #ifdef _SC_SIGQUEUE_MAX
12337     {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
12338 #endif
12339 #ifdef _SC_SIGRT_MAX
12340     {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
12341 #endif
12342 #ifdef _SC_SIGRT_MIN
12343     {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
12344 #endif
12345 #ifdef _SC_SOFTPOWER
12346     {"SC_SOFTPOWER",    _SC_SOFTPOWER},
12347 #endif
12348 #ifdef _SC_SPLIT_CACHE
12349     {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
12350 #endif
12351 #ifdef _SC_SSIZE_MAX
12352     {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
12353 #endif
12354 #ifdef _SC_STACK_PROT
12355     {"SC_STACK_PROT",   _SC_STACK_PROT},
12356 #endif
12357 #ifdef _SC_STREAM_MAX
12358     {"SC_STREAM_MAX",   _SC_STREAM_MAX},
12359 #endif
12360 #ifdef _SC_SYNCHRONIZED_IO
12361     {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
12362 #endif
12363 #ifdef _SC_THREADS
12364     {"SC_THREADS",      _SC_THREADS},
12365 #endif
12366 #ifdef _SC_THREAD_ATTR_STACKADDR
12367     {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
12368 #endif
12369 #ifdef _SC_THREAD_ATTR_STACKSIZE
12370     {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
12371 #endif
12372 #ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
12373     {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
12374 #endif
12375 #ifdef _SC_THREAD_KEYS_MAX
12376     {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
12377 #endif
12378 #ifdef _SC_THREAD_PRIORITY_SCHEDULING
12379     {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
12380 #endif
12381 #ifdef _SC_THREAD_PRIO_INHERIT
12382     {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
12383 #endif
12384 #ifdef _SC_THREAD_PRIO_PROTECT
12385     {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
12386 #endif
12387 #ifdef _SC_THREAD_PROCESS_SHARED
12388     {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
12389 #endif
12390 #ifdef _SC_THREAD_SAFE_FUNCTIONS
12391     {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
12392 #endif
12393 #ifdef _SC_THREAD_STACK_MIN
12394     {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
12395 #endif
12396 #ifdef _SC_THREAD_THREADS_MAX
12397     {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
12398 #endif
12399 #ifdef _SC_TIMERS
12400     {"SC_TIMERS",       _SC_TIMERS},
12401 #endif
12402 #ifdef _SC_TIMER_MAX
12403     {"SC_TIMER_MAX",    _SC_TIMER_MAX},
12404 #endif
12405 #ifdef _SC_TTY_NAME_MAX
12406     {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
12407 #endif
12408 #ifdef _SC_TZNAME_MAX
12409     {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
12410 #endif
12411 #ifdef _SC_T_IOV_MAX
12412     {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
12413 #endif
12414 #ifdef _SC_UCHAR_MAX
12415     {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
12416 #endif
12417 #ifdef _SC_UINT_MAX
12418     {"SC_UINT_MAX",     _SC_UINT_MAX},
12419 #endif
12420 #ifdef _SC_UIO_MAXIOV
12421     {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
12422 #endif
12423 #ifdef _SC_ULONG_MAX
12424     {"SC_ULONG_MAX",    _SC_ULONG_MAX},
12425 #endif
12426 #ifdef _SC_USHRT_MAX
12427     {"SC_USHRT_MAX",    _SC_USHRT_MAX},
12428 #endif
12429 #ifdef _SC_VERSION
12430     {"SC_VERSION",      _SC_VERSION},
12431 #endif
12432 #ifdef _SC_WORD_BIT
12433     {"SC_WORD_BIT",     _SC_WORD_BIT},
12434 #endif
12435 #ifdef _SC_XBS5_ILP32_OFF32
12436     {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
12437 #endif
12438 #ifdef _SC_XBS5_ILP32_OFFBIG
12439     {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
12440 #endif
12441 #ifdef _SC_XBS5_LP64_OFF64
12442     {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
12443 #endif
12444 #ifdef _SC_XBS5_LPBIG_OFFBIG
12445     {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
12446 #endif
12447 #ifdef _SC_XOPEN_CRYPT
12448     {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
12449 #endif
12450 #ifdef _SC_XOPEN_ENH_I18N
12451     {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
12452 #endif
12453 #ifdef _SC_XOPEN_LEGACY
12454     {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
12455 #endif
12456 #ifdef _SC_XOPEN_REALTIME
12457     {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
12458 #endif
12459 #ifdef _SC_XOPEN_REALTIME_THREADS
12460     {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
12461 #endif
12462 #ifdef _SC_XOPEN_SHM
12463     {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
12464 #endif
12465 #ifdef _SC_XOPEN_UNIX
12466     {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
12467 #endif
12468 #ifdef _SC_XOPEN_VERSION
12469     {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
12470 #endif
12471 #ifdef _SC_XOPEN_XCU_VERSION
12472     {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
12473 #endif
12474 #ifdef _SC_XOPEN_XPG2
12475     {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
12476 #endif
12477 #ifdef _SC_XOPEN_XPG3
12478     {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
12479 #endif
12480 #ifdef _SC_XOPEN_XPG4
12481     {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
12482 #endif
12483 #ifdef _SC_MINSIGSTKSZ
12484     {"SC_MINSIGSTKSZ",   _SC_MINSIGSTKSZ},
12485 #endif
12486 };
12487 
12488 static int
conv_sysconf_confname(PyObject * arg,int * valuep)12489 conv_sysconf_confname(PyObject *arg, int *valuep)
12490 {
12491     return conv_confname(arg, valuep, posix_constants_sysconf,
12492                          sizeof(posix_constants_sysconf)
12493                            / sizeof(struct constdef));
12494 }
12495 
12496 
12497 /*[clinic input]
12498 os.sysconf -> long
12499     name: sysconf_confname
12500     /
12501 
12502 Return an integer-valued system configuration variable.
12503 [clinic start generated code]*/
12504 
12505 static long
os_sysconf_impl(PyObject * module,int name)12506 os_sysconf_impl(PyObject *module, int name)
12507 /*[clinic end generated code: output=3662f945fc0cc756 input=279e3430a33f29e4]*/
12508 {
12509     long value;
12510 
12511     errno = 0;
12512     value = sysconf(name);
12513     if (value == -1 && errno != 0)
12514         posix_error();
12515     return value;
12516 }
12517 #endif /* HAVE_SYSCONF */
12518 
12519 
12520 /* This code is used to ensure that the tables of configuration value names
12521  * are in sorted order as required by conv_confname(), and also to build
12522  * the exported dictionaries that are used to publish information about the
12523  * names available on the host platform.
12524  *
12525  * Sorting the table at runtime ensures that the table is properly ordered
12526  * when used, even for platforms we're not able to test on.  It also makes
12527  * it easier to add additional entries to the tables.
12528  */
12529 
12530 static int
cmp_constdefs(const void * v1,const void * v2)12531 cmp_constdefs(const void *v1,  const void *v2)
12532 {
12533     const struct constdef *c1 =
12534     (const struct constdef *) v1;
12535     const struct constdef *c2 =
12536     (const struct constdef *) v2;
12537 
12538     return strcmp(c1->name, c2->name);
12539 }
12540 
12541 static int
setup_confname_table(struct constdef * table,size_t tablesize,const char * tablename,PyObject * module)12542 setup_confname_table(struct constdef *table, size_t tablesize,
12543                      const char *tablename, PyObject *module)
12544 {
12545     PyObject *d = NULL;
12546     size_t i;
12547 
12548     qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
12549     d = PyDict_New();
12550     if (d == NULL)
12551         return -1;
12552 
12553     for (i=0; i < tablesize; ++i) {
12554         PyObject *o = PyLong_FromLong(table[i].value);
12555         if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
12556             Py_XDECREF(o);
12557             Py_DECREF(d);
12558             return -1;
12559         }
12560         Py_DECREF(o);
12561     }
12562     return PyModule_AddObject(module, tablename, d);
12563 }
12564 
12565 /* Return -1 on failure, 0 on success. */
12566 static int
setup_confname_tables(PyObject * module)12567 setup_confname_tables(PyObject *module)
12568 {
12569 #if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
12570     if (setup_confname_table(posix_constants_pathconf,
12571                              sizeof(posix_constants_pathconf)
12572                                / sizeof(struct constdef),
12573                              "pathconf_names", module))
12574         return -1;
12575 #endif
12576 #ifdef HAVE_CONFSTR
12577     if (setup_confname_table(posix_constants_confstr,
12578                              sizeof(posix_constants_confstr)
12579                                / sizeof(struct constdef),
12580                              "confstr_names", module))
12581         return -1;
12582 #endif
12583 #ifdef HAVE_SYSCONF
12584     if (setup_confname_table(posix_constants_sysconf,
12585                              sizeof(posix_constants_sysconf)
12586                                / sizeof(struct constdef),
12587                              "sysconf_names", module))
12588         return -1;
12589 #endif
12590     return 0;
12591 }
12592 
12593 
12594 /*[clinic input]
12595 os.abort
12596 
12597 Abort the interpreter immediately.
12598 
12599 This function 'dumps core' or otherwise fails in the hardest way possible
12600 on the hosting operating system.  This function never returns.
12601 [clinic start generated code]*/
12602 
12603 static PyObject *
os_abort_impl(PyObject * module)12604 os_abort_impl(PyObject *module)
12605 /*[clinic end generated code: output=dcf52586dad2467c input=cf2c7d98bc504047]*/
12606 {
12607     abort();
12608     /*NOTREACHED*/
12609 #ifndef __clang__
12610     /* Issue #28152: abort() is declared with __attribute__((__noreturn__)).
12611        GCC emits a warning without "return NULL;" (compiler bug?), but Clang
12612        is smarter and emits a warning on the return. */
12613     Py_FatalError("abort() called from Python code didn't abort!");
12614     return NULL;
12615 #endif
12616 }
12617 
12618 #ifdef MS_WINDOWS
12619 /* Grab ShellExecute dynamically from shell32 */
12620 static int has_ShellExecute = -1;
12621 static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR,
12622                                               LPCWSTR, INT);
12623 static int
check_ShellExecute()12624 check_ShellExecute()
12625 {
12626     HINSTANCE hShell32;
12627 
12628     /* only recheck */
12629     if (-1 == has_ShellExecute) {
12630         Py_BEGIN_ALLOW_THREADS
12631         /* Security note: this call is not vulnerable to "DLL hijacking".
12632            SHELL32 is part of "KnownDLLs" and so Windows always load
12633            the system SHELL32.DLL, even if there is another SHELL32.DLL
12634            in the DLL search path. */
12635         hShell32 = LoadLibraryW(L"SHELL32");
12636         if (hShell32) {
12637             *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
12638                                             "ShellExecuteW");
12639             has_ShellExecute = Py_ShellExecuteW != NULL;
12640         } else {
12641             has_ShellExecute = 0;
12642         }
12643         Py_END_ALLOW_THREADS
12644     }
12645     return has_ShellExecute;
12646 }
12647 
12648 
12649 /*[clinic input]
12650 os.startfile
12651     filepath: path_t
12652     operation: Py_UNICODE = NULL
12653     arguments: Py_UNICODE = NULL
12654     cwd: path_t(nullable=True) = None
12655     show_cmd: int = 1
12656 
12657 Start a file with its associated application.
12658 
12659 When "operation" is not specified or "open", this acts like
12660 double-clicking the file in Explorer, or giving the file name as an
12661 argument to the DOS "start" command: the file is opened with whatever
12662 application (if any) its extension is associated.
12663 When another "operation" is given, it specifies what should be done with
12664 the file.  A typical operation is "print".
12665 
12666 "arguments" is passed to the application, but should be omitted if the
12667 file is a document.
12668 
12669 "cwd" is the working directory for the operation. If "filepath" is
12670 relative, it will be resolved against this directory. This argument
12671 should usually be an absolute path.
12672 
12673 "show_cmd" can be used to override the recommended visibility option.
12674 See the Windows ShellExecute documentation for values.
12675 
12676 startfile returns as soon as the associated application is launched.
12677 There is no option to wait for the application to close, and no way
12678 to retrieve the application's exit status.
12679 
12680 The filepath is relative to the current directory.  If you want to use
12681 an absolute path, make sure the first character is not a slash ("/");
12682 the underlying Win32 ShellExecute function doesn't work if it is.
12683 [clinic start generated code]*/
12684 
12685 static PyObject *
os_startfile_impl(PyObject * module,path_t * filepath,const Py_UNICODE * operation,const Py_UNICODE * arguments,path_t * cwd,int show_cmd)12686 os_startfile_impl(PyObject *module, path_t *filepath,
12687                   const Py_UNICODE *operation, const Py_UNICODE *arguments,
12688                   path_t *cwd, int show_cmd)
12689 /*[clinic end generated code: output=3baa4f9795841880 input=8248997b80669622]*/
12690 {
12691     HINSTANCE rc;
12692 
12693     if(!check_ShellExecute()) {
12694         /* If the OS doesn't have ShellExecute, return a
12695            NotImplementedError. */
12696         return PyErr_Format(PyExc_NotImplementedError,
12697             "startfile not available on this platform");
12698     }
12699 
12700     if (PySys_Audit("os.startfile", "Ou", filepath->object, operation) < 0) {
12701         return NULL;
12702     }
12703     if (PySys_Audit("os.startfile/2", "OuuOi", filepath->object, operation,
12704                     arguments, cwd->object ? cwd->object : Py_None,
12705                     show_cmd) < 0) {
12706         return NULL;
12707     }
12708 
12709     Py_BEGIN_ALLOW_THREADS
12710     rc = Py_ShellExecuteW((HWND)0, operation, filepath->wide,
12711                           arguments, cwd->wide, show_cmd);
12712     Py_END_ALLOW_THREADS
12713 
12714     if (rc <= (HINSTANCE)32) {
12715         win32_error_object("startfile", filepath->object);
12716         return NULL;
12717     }
12718     Py_RETURN_NONE;
12719 }
12720 #endif /* MS_WINDOWS */
12721 
12722 
12723 #ifdef HAVE_GETLOADAVG
12724 /*[clinic input]
12725 os.getloadavg
12726 
12727 Return average recent system load information.
12728 
12729 Return the number of processes in the system run queue averaged over
12730 the last 1, 5, and 15 minutes as a tuple of three floats.
12731 Raises OSError if the load average was unobtainable.
12732 [clinic start generated code]*/
12733 
12734 static PyObject *
os_getloadavg_impl(PyObject * module)12735 os_getloadavg_impl(PyObject *module)
12736 /*[clinic end generated code: output=9ad3a11bfb4f4bd2 input=3d6d826b76d8a34e]*/
12737 {
12738     double loadavg[3];
12739     if (getloadavg(loadavg, 3)!=3) {
12740         PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
12741         return NULL;
12742     } else
12743         return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
12744 }
12745 #endif /* HAVE_GETLOADAVG */
12746 
12747 
12748 /*[clinic input]
12749 os.device_encoding
12750     fd: int
12751 
12752 Return a string describing the encoding of a terminal's file descriptor.
12753 
12754 The file descriptor must be attached to a terminal.
12755 If the device is not a terminal, return None.
12756 [clinic start generated code]*/
12757 
12758 static PyObject *
os_device_encoding_impl(PyObject * module,int fd)12759 os_device_encoding_impl(PyObject *module, int fd)
12760 /*[clinic end generated code: output=e0d294bbab7e8c2b input=9e1d4a42b66df312]*/
12761 {
12762     return _Py_device_encoding(fd);
12763 }
12764 
12765 
12766 #ifdef HAVE_SETRESUID
12767 /*[clinic input]
12768 os.setresuid
12769 
12770     ruid: uid_t
12771     euid: uid_t
12772     suid: uid_t
12773     /
12774 
12775 Set the current process's real, effective, and saved user ids.
12776 [clinic start generated code]*/
12777 
12778 static PyObject *
os_setresuid_impl(PyObject * module,uid_t ruid,uid_t euid,uid_t suid)12779 os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
12780 /*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
12781 {
12782     if (setresuid(ruid, euid, suid) < 0)
12783         return posix_error();
12784     Py_RETURN_NONE;
12785 }
12786 #endif /* HAVE_SETRESUID */
12787 
12788 
12789 #ifdef HAVE_SETRESGID
12790 /*[clinic input]
12791 os.setresgid
12792 
12793     rgid: gid_t
12794     egid: gid_t
12795     sgid: gid_t
12796     /
12797 
12798 Set the current process's real, effective, and saved group ids.
12799 [clinic start generated code]*/
12800 
12801 static PyObject *
os_setresgid_impl(PyObject * module,gid_t rgid,gid_t egid,gid_t sgid)12802 os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
12803 /*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
12804 {
12805     if (setresgid(rgid, egid, sgid) < 0)
12806         return posix_error();
12807     Py_RETURN_NONE;
12808 }
12809 #endif /* HAVE_SETRESGID */
12810 
12811 
12812 #ifdef HAVE_GETRESUID
12813 /*[clinic input]
12814 os.getresuid
12815 
12816 Return a tuple of the current process's real, effective, and saved user ids.
12817 [clinic start generated code]*/
12818 
12819 static PyObject *
os_getresuid_impl(PyObject * module)12820 os_getresuid_impl(PyObject *module)
12821 /*[clinic end generated code: output=8e0becff5dece5bf input=41ccfa8e1f6517ad]*/
12822 {
12823     uid_t ruid, euid, suid;
12824     if (getresuid(&ruid, &euid, &suid) < 0)
12825         return posix_error();
12826     return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid),
12827                                   _PyLong_FromUid(euid),
12828                                   _PyLong_FromUid(suid));
12829 }
12830 #endif /* HAVE_GETRESUID */
12831 
12832 
12833 #ifdef HAVE_GETRESGID
12834 /*[clinic input]
12835 os.getresgid
12836 
12837 Return a tuple of the current process's real, effective, and saved group ids.
12838 [clinic start generated code]*/
12839 
12840 static PyObject *
os_getresgid_impl(PyObject * module)12841 os_getresgid_impl(PyObject *module)
12842 /*[clinic end generated code: output=2719c4bfcf27fb9f input=517e68db9ca32df6]*/
12843 {
12844     gid_t rgid, egid, sgid;
12845     if (getresgid(&rgid, &egid, &sgid) < 0)
12846         return posix_error();
12847     return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid),
12848                                   _PyLong_FromGid(egid),
12849                                   _PyLong_FromGid(sgid));
12850 }
12851 #endif /* HAVE_GETRESGID */
12852 
12853 
12854 #ifdef USE_XATTRS
12855 /*[clinic input]
12856 os.getxattr
12857 
12858     path: path_t(allow_fd=True)
12859     attribute: path_t
12860     *
12861     follow_symlinks: bool = True
12862 
12863 Return the value of extended attribute attribute on path.
12864 
12865 path may be either a string, a path-like object, or an open file descriptor.
12866 If follow_symlinks is False, and the last element of the path is a symbolic
12867   link, getxattr will examine the symbolic link itself instead of the file
12868   the link points to.
12869 
12870 [clinic start generated code]*/
12871 
12872 static PyObject *
os_getxattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)12873 os_getxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12874                  int follow_symlinks)
12875 /*[clinic end generated code: output=5f2f44200a43cff2 input=025789491708f7eb]*/
12876 {
12877     Py_ssize_t i;
12878     PyObject *buffer = NULL;
12879 
12880     if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks))
12881         return NULL;
12882 
12883     if (PySys_Audit("os.getxattr", "OO", path->object, attribute->object) < 0) {
12884         return NULL;
12885     }
12886 
12887     for (i = 0; ; i++) {
12888         void *ptr;
12889         ssize_t result;
12890         static const Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0};
12891         Py_ssize_t buffer_size = buffer_sizes[i];
12892         if (!buffer_size) {
12893             path_error(path);
12894             return NULL;
12895         }
12896         buffer = PyBytes_FromStringAndSize(NULL, buffer_size);
12897         if (!buffer)
12898             return NULL;
12899         ptr = PyBytes_AS_STRING(buffer);
12900 
12901         Py_BEGIN_ALLOW_THREADS;
12902         if (path->fd >= 0)
12903             result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size);
12904         else if (follow_symlinks)
12905             result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12906         else
12907             result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size);
12908         Py_END_ALLOW_THREADS;
12909 
12910         if (result < 0) {
12911             Py_DECREF(buffer);
12912             if (errno == ERANGE)
12913                 continue;
12914             path_error(path);
12915             return NULL;
12916         }
12917 
12918         if (result != buffer_size) {
12919             /* Can only shrink. */
12920             _PyBytes_Resize(&buffer, result);
12921         }
12922         break;
12923     }
12924 
12925     return buffer;
12926 }
12927 
12928 
12929 /*[clinic input]
12930 os.setxattr
12931 
12932     path: path_t(allow_fd=True)
12933     attribute: path_t
12934     value: Py_buffer
12935     flags: int = 0
12936     *
12937     follow_symlinks: bool = True
12938 
12939 Set extended attribute attribute on path to value.
12940 
12941 path may be either a string, a path-like object,  or an open file descriptor.
12942 If follow_symlinks is False, and the last element of the path is a symbolic
12943   link, setxattr will modify the symbolic link itself instead of the file
12944   the link points to.
12945 
12946 [clinic start generated code]*/
12947 
12948 static PyObject *
os_setxattr_impl(PyObject * module,path_t * path,path_t * attribute,Py_buffer * value,int flags,int follow_symlinks)12949 os_setxattr_impl(PyObject *module, path_t *path, path_t *attribute,
12950                  Py_buffer *value, int flags, int follow_symlinks)
12951 /*[clinic end generated code: output=98b83f63fdde26bb input=c17c0103009042f0]*/
12952 {
12953     ssize_t result;
12954 
12955     if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks))
12956         return NULL;
12957 
12958     if (PySys_Audit("os.setxattr", "OOy#i", path->object, attribute->object,
12959                     value->buf, value->len, flags) < 0) {
12960         return NULL;
12961     }
12962 
12963     Py_BEGIN_ALLOW_THREADS;
12964     if (path->fd > -1)
12965         result = fsetxattr(path->fd, attribute->narrow,
12966                            value->buf, value->len, flags);
12967     else if (follow_symlinks)
12968         result = setxattr(path->narrow, attribute->narrow,
12969                            value->buf, value->len, flags);
12970     else
12971         result = lsetxattr(path->narrow, attribute->narrow,
12972                            value->buf, value->len, flags);
12973     Py_END_ALLOW_THREADS;
12974 
12975     if (result) {
12976         path_error(path);
12977         return NULL;
12978     }
12979 
12980     Py_RETURN_NONE;
12981 }
12982 
12983 
12984 /*[clinic input]
12985 os.removexattr
12986 
12987     path: path_t(allow_fd=True)
12988     attribute: path_t
12989     *
12990     follow_symlinks: bool = True
12991 
12992 Remove extended attribute attribute on path.
12993 
12994 path may be either a string, a path-like object, or an open file descriptor.
12995 If follow_symlinks is False, and the last element of the path is a symbolic
12996   link, removexattr will modify the symbolic link itself instead of the file
12997   the link points to.
12998 
12999 [clinic start generated code]*/
13000 
13001 static PyObject *
os_removexattr_impl(PyObject * module,path_t * path,path_t * attribute,int follow_symlinks)13002 os_removexattr_impl(PyObject *module, path_t *path, path_t *attribute,
13003                     int follow_symlinks)
13004 /*[clinic end generated code: output=521a51817980cda6 input=3d9a7d36fe2f7c4e]*/
13005 {
13006     ssize_t result;
13007 
13008     if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks))
13009         return NULL;
13010 
13011     if (PySys_Audit("os.removexattr", "OO", path->object, attribute->object) < 0) {
13012         return NULL;
13013     }
13014 
13015     Py_BEGIN_ALLOW_THREADS;
13016     if (path->fd > -1)
13017         result = fremovexattr(path->fd, attribute->narrow);
13018     else if (follow_symlinks)
13019         result = removexattr(path->narrow, attribute->narrow);
13020     else
13021         result = lremovexattr(path->narrow, attribute->narrow);
13022     Py_END_ALLOW_THREADS;
13023 
13024     if (result) {
13025         return path_error(path);
13026     }
13027 
13028     Py_RETURN_NONE;
13029 }
13030 
13031 
13032 /*[clinic input]
13033 os.listxattr
13034 
13035     path: path_t(allow_fd=True, nullable=True) = None
13036     *
13037     follow_symlinks: bool = True
13038 
13039 Return a list of extended attributes on path.
13040 
13041 path may be either None, a string, a path-like object, or an open file descriptor.
13042 if path is None, listxattr will examine the current directory.
13043 If follow_symlinks is False, and the last element of the path is a symbolic
13044   link, listxattr will examine the symbolic link itself instead of the file
13045   the link points to.
13046 [clinic start generated code]*/
13047 
13048 static PyObject *
os_listxattr_impl(PyObject * module,path_t * path,int follow_symlinks)13049 os_listxattr_impl(PyObject *module, path_t *path, int follow_symlinks)
13050 /*[clinic end generated code: output=bebdb4e2ad0ce435 input=9826edf9fdb90869]*/
13051 {
13052     Py_ssize_t i;
13053     PyObject *result = NULL;
13054     const char *name;
13055     char *buffer = NULL;
13056 
13057     if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks))
13058         goto exit;
13059 
13060     if (PySys_Audit("os.listxattr", "(O)",
13061                     path->object ? path->object : Py_None) < 0) {
13062         return NULL;
13063     }
13064 
13065     name = path->narrow ? path->narrow : ".";
13066 
13067     for (i = 0; ; i++) {
13068         const char *start, *trace, *end;
13069         ssize_t length;
13070         static const Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 };
13071         Py_ssize_t buffer_size = buffer_sizes[i];
13072         if (!buffer_size) {
13073             /* ERANGE */
13074             path_error(path);
13075             break;
13076         }
13077         buffer = PyMem_Malloc(buffer_size);
13078         if (!buffer) {
13079             PyErr_NoMemory();
13080             break;
13081         }
13082 
13083         Py_BEGIN_ALLOW_THREADS;
13084         if (path->fd > -1)
13085             length = flistxattr(path->fd, buffer, buffer_size);
13086         else if (follow_symlinks)
13087             length = listxattr(name, buffer, buffer_size);
13088         else
13089             length = llistxattr(name, buffer, buffer_size);
13090         Py_END_ALLOW_THREADS;
13091 
13092         if (length < 0) {
13093             if (errno == ERANGE) {
13094                 PyMem_Free(buffer);
13095                 buffer = NULL;
13096                 continue;
13097             }
13098             path_error(path);
13099             break;
13100         }
13101 
13102         result = PyList_New(0);
13103         if (!result) {
13104             goto exit;
13105         }
13106 
13107         end = buffer + length;
13108         for (trace = start = buffer; trace != end; trace++) {
13109             if (!*trace) {
13110                 int error;
13111                 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start,
13112                                                                  trace - start);
13113                 if (!attribute) {
13114                     Py_DECREF(result);
13115                     result = NULL;
13116                     goto exit;
13117                 }
13118                 error = PyList_Append(result, attribute);
13119                 Py_DECREF(attribute);
13120                 if (error) {
13121                     Py_DECREF(result);
13122                     result = NULL;
13123                     goto exit;
13124                 }
13125                 start = trace + 1;
13126             }
13127         }
13128     break;
13129     }
13130 exit:
13131     if (buffer)
13132         PyMem_Free(buffer);
13133     return result;
13134 }
13135 #endif /* USE_XATTRS */
13136 
13137 
13138 /*[clinic input]
13139 os.urandom
13140 
13141     size: Py_ssize_t
13142     /
13143 
13144 Return a bytes object containing random bytes suitable for cryptographic use.
13145 [clinic start generated code]*/
13146 
13147 static PyObject *
os_urandom_impl(PyObject * module,Py_ssize_t size)13148 os_urandom_impl(PyObject *module, Py_ssize_t size)
13149 /*[clinic end generated code: output=42c5cca9d18068e9 input=4067cdb1b6776c29]*/
13150 {
13151     PyObject *bytes;
13152     int result;
13153 
13154     if (size < 0)
13155         return PyErr_Format(PyExc_ValueError,
13156                             "negative argument not allowed");
13157     bytes = PyBytes_FromStringAndSize(NULL, size);
13158     if (bytes == NULL)
13159         return NULL;
13160 
13161     result = _PyOS_URandom(PyBytes_AS_STRING(bytes), PyBytes_GET_SIZE(bytes));
13162     if (result == -1) {
13163         Py_DECREF(bytes);
13164         return NULL;
13165     }
13166     return bytes;
13167 }
13168 
13169 #ifdef HAVE_MEMFD_CREATE
13170 /*[clinic input]
13171 os.memfd_create
13172 
13173     name: FSConverter
13174     flags: unsigned_int(bitwise=True, c_default="MFD_CLOEXEC") = MFD_CLOEXEC
13175 
13176 [clinic start generated code]*/
13177 
13178 static PyObject *
os_memfd_create_impl(PyObject * module,PyObject * name,unsigned int flags)13179 os_memfd_create_impl(PyObject *module, PyObject *name, unsigned int flags)
13180 /*[clinic end generated code: output=6681ede983bdb9a6 input=a42cfc199bcd56e9]*/
13181 {
13182     int fd;
13183     const char *bytes = PyBytes_AS_STRING(name);
13184     Py_BEGIN_ALLOW_THREADS
13185     fd = memfd_create(bytes, flags);
13186     Py_END_ALLOW_THREADS
13187     if (fd == -1) {
13188         return PyErr_SetFromErrno(PyExc_OSError);
13189     }
13190     return PyLong_FromLong(fd);
13191 }
13192 #endif
13193 
13194 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
13195 /*[clinic input]
13196 os.eventfd
13197 
13198     initval: unsigned_int
13199     flags: int(c_default="EFD_CLOEXEC") = EFD_CLOEXEC
13200 
13201 Creates and returns an event notification file descriptor.
13202 [clinic start generated code]*/
13203 
13204 static PyObject *
os_eventfd_impl(PyObject * module,unsigned int initval,int flags)13205 os_eventfd_impl(PyObject *module, unsigned int initval, int flags)
13206 /*[clinic end generated code: output=ce9c9bbd1446f2de input=66203e3c50c4028b]*/
13207 
13208 {
13209     /* initval is limited to uint32_t, internal counter is uint64_t */
13210     int fd;
13211     Py_BEGIN_ALLOW_THREADS
13212     fd = eventfd(initval, flags);
13213     Py_END_ALLOW_THREADS
13214     if (fd == -1) {
13215         return PyErr_SetFromErrno(PyExc_OSError);
13216     }
13217     return PyLong_FromLong(fd);
13218 }
13219 
13220 /*[clinic input]
13221 os.eventfd_read
13222 
13223     fd: fildes
13224 
13225 Read eventfd value
13226 [clinic start generated code]*/
13227 
13228 static PyObject *
os_eventfd_read_impl(PyObject * module,int fd)13229 os_eventfd_read_impl(PyObject *module, int fd)
13230 /*[clinic end generated code: output=8f2c7b59a3521fd1 input=110f8b57fa596afe]*/
13231 {
13232     eventfd_t value;
13233     int result;
13234     Py_BEGIN_ALLOW_THREADS
13235     result = eventfd_read(fd, &value);
13236     Py_END_ALLOW_THREADS
13237     if (result == -1) {
13238         return PyErr_SetFromErrno(PyExc_OSError);
13239     }
13240     return PyLong_FromUnsignedLongLong(value);
13241 }
13242 
13243 /*[clinic input]
13244 os.eventfd_write
13245 
13246     fd: fildes
13247     value: unsigned_long_long
13248 
13249 Write eventfd value.
13250 [clinic start generated code]*/
13251 
13252 static PyObject *
os_eventfd_write_impl(PyObject * module,int fd,unsigned long long value)13253 os_eventfd_write_impl(PyObject *module, int fd, unsigned long long value)
13254 /*[clinic end generated code: output=bebd9040bbf987f5 input=156de8555be5a949]*/
13255 {
13256     int result;
13257     Py_BEGIN_ALLOW_THREADS
13258     result = eventfd_write(fd, value);
13259     Py_END_ALLOW_THREADS
13260     if (result == -1) {
13261         return PyErr_SetFromErrno(PyExc_OSError);
13262     }
13263     Py_RETURN_NONE;
13264 }
13265 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
13266 
13267 /* Terminal size querying */
13268 
13269 PyDoc_STRVAR(TerminalSize_docstring,
13270     "A tuple of (columns, lines) for holding terminal window size");
13271 
13272 static PyStructSequence_Field TerminalSize_fields[] = {
13273     {"columns", "width of the terminal window in characters"},
13274     {"lines", "height of the terminal window in characters"},
13275     {NULL, NULL}
13276 };
13277 
13278 static PyStructSequence_Desc TerminalSize_desc = {
13279     "os.terminal_size",
13280     TerminalSize_docstring,
13281     TerminalSize_fields,
13282     2,
13283 };
13284 
13285 #if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL)
13286 /*[clinic input]
13287 os.get_terminal_size
13288 
13289     fd: int(c_default="fileno(stdout)", py_default="<unrepresentable>") = -1
13290     /
13291 
13292 Return the size of the terminal window as (columns, lines).
13293 
13294 The optional argument fd (default standard output) specifies
13295 which file descriptor should be queried.
13296 
13297 If the file descriptor is not connected to a terminal, an OSError
13298 is thrown.
13299 
13300 This function will only be defined if an implementation is
13301 available for this system.
13302 
13303 shutil.get_terminal_size is the high-level function which should
13304 normally be used, os.get_terminal_size is the low-level implementation.
13305 [clinic start generated code]*/
13306 
13307 static PyObject *
os_get_terminal_size_impl(PyObject * module,int fd)13308 os_get_terminal_size_impl(PyObject *module, int fd)
13309 /*[clinic end generated code: output=fbab93acef980508 input=ead5679b82ddb920]*/
13310 {
13311     int columns, lines;
13312     PyObject *termsize;
13313 
13314     /* Under some conditions stdout may not be connected and
13315      * fileno(stdout) may point to an invalid file descriptor. For example
13316      * GUI apps don't have valid standard streams by default.
13317      *
13318      * If this happens, and the optional fd argument is not present,
13319      * the ioctl below will fail returning EBADF. This is what we want.
13320      */
13321 
13322 #ifdef TERMSIZE_USE_IOCTL
13323     {
13324         struct winsize w;
13325         if (ioctl(fd, TIOCGWINSZ, &w))
13326             return PyErr_SetFromErrno(PyExc_OSError);
13327         columns = w.ws_col;
13328         lines = w.ws_row;
13329     }
13330 #endif /* TERMSIZE_USE_IOCTL */
13331 
13332 #ifdef TERMSIZE_USE_CONIO
13333     {
13334         DWORD nhandle;
13335         HANDLE handle;
13336         CONSOLE_SCREEN_BUFFER_INFO csbi;
13337         switch (fd) {
13338         case 0: nhandle = STD_INPUT_HANDLE;
13339             break;
13340         case 1: nhandle = STD_OUTPUT_HANDLE;
13341             break;
13342         case 2: nhandle = STD_ERROR_HANDLE;
13343             break;
13344         default:
13345             return PyErr_Format(PyExc_ValueError, "bad file descriptor");
13346         }
13347         handle = GetStdHandle(nhandle);
13348         if (handle == NULL)
13349             return PyErr_Format(PyExc_OSError, "handle cannot be retrieved");
13350         if (handle == INVALID_HANDLE_VALUE)
13351             return PyErr_SetFromWindowsErr(0);
13352 
13353         if (!GetConsoleScreenBufferInfo(handle, &csbi))
13354             return PyErr_SetFromWindowsErr(0);
13355 
13356         columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
13357         lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
13358     }
13359 #endif /* TERMSIZE_USE_CONIO */
13360 
13361     PyObject *TerminalSizeType = get_posix_state(module)->TerminalSizeType;
13362     termsize = PyStructSequence_New((PyTypeObject *)TerminalSizeType);
13363     if (termsize == NULL)
13364         return NULL;
13365     PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns));
13366     PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines));
13367     if (PyErr_Occurred()) {
13368         Py_DECREF(termsize);
13369         return NULL;
13370     }
13371     return termsize;
13372 }
13373 #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */
13374 
13375 
13376 /*[clinic input]
13377 os.cpu_count
13378 
13379 Return the number of CPUs in the system; return None if indeterminable.
13380 
13381 This number is not equivalent to the number of CPUs the current process can
13382 use.  The number of usable CPUs can be obtained with
13383 ``len(os.sched_getaffinity(0))``
13384 [clinic start generated code]*/
13385 
13386 static PyObject *
os_cpu_count_impl(PyObject * module)13387 os_cpu_count_impl(PyObject *module)
13388 /*[clinic end generated code: output=5fc29463c3936a9c input=e7c8f4ba6dbbadd3]*/
13389 {
13390     int ncpu = 0;
13391 #ifdef MS_WINDOWS
13392     ncpu = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
13393 #elif defined(__hpux)
13394     ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL);
13395 #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
13396     ncpu = sysconf(_SC_NPROCESSORS_ONLN);
13397 #elif defined(__VXWORKS__)
13398     ncpu = _Py_popcount32(vxCpuEnabledGet());
13399 #elif defined(__DragonFly__) || \
13400       defined(__OpenBSD__)   || \
13401       defined(__FreeBSD__)   || \
13402       defined(__NetBSD__)    || \
13403       defined(__APPLE__)
13404     int mib[2];
13405     size_t len = sizeof(ncpu);
13406     mib[0] = CTL_HW;
13407     mib[1] = HW_NCPU;
13408     if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0)
13409         ncpu = 0;
13410 #endif
13411     if (ncpu >= 1)
13412         return PyLong_FromLong(ncpu);
13413     else
13414         Py_RETURN_NONE;
13415 }
13416 
13417 
13418 /*[clinic input]
13419 os.get_inheritable -> bool
13420 
13421     fd: int
13422     /
13423 
13424 Get the close-on-exe flag of the specified file descriptor.
13425 [clinic start generated code]*/
13426 
13427 static int
os_get_inheritable_impl(PyObject * module,int fd)13428 os_get_inheritable_impl(PyObject *module, int fd)
13429 /*[clinic end generated code: output=0445e20e149aa5b8 input=89ac008dc9ab6b95]*/
13430 {
13431     int return_value;
13432     _Py_BEGIN_SUPPRESS_IPH
13433     return_value = _Py_get_inheritable(fd);
13434     _Py_END_SUPPRESS_IPH
13435     return return_value;
13436 }
13437 
13438 
13439 /*[clinic input]
13440 os.set_inheritable
13441     fd: int
13442     inheritable: int
13443     /
13444 
13445 Set the inheritable flag of the specified file descriptor.
13446 [clinic start generated code]*/
13447 
13448 static PyObject *
os_set_inheritable_impl(PyObject * module,int fd,int inheritable)13449 os_set_inheritable_impl(PyObject *module, int fd, int inheritable)
13450 /*[clinic end generated code: output=f1b1918a2f3c38c2 input=9ceaead87a1e2402]*/
13451 {
13452     int result;
13453 
13454     _Py_BEGIN_SUPPRESS_IPH
13455     result = _Py_set_inheritable(fd, inheritable, NULL);
13456     _Py_END_SUPPRESS_IPH
13457     if (result < 0)
13458         return NULL;
13459     Py_RETURN_NONE;
13460 }
13461 
13462 
13463 #ifdef MS_WINDOWS
13464 /*[clinic input]
13465 os.get_handle_inheritable -> bool
13466     handle: intptr_t
13467     /
13468 
13469 Get the close-on-exe flag of the specified file descriptor.
13470 [clinic start generated code]*/
13471 
13472 static int
os_get_handle_inheritable_impl(PyObject * module,intptr_t handle)13473 os_get_handle_inheritable_impl(PyObject *module, intptr_t handle)
13474 /*[clinic end generated code: output=36be5afca6ea84d8 input=cfe99f9c05c70ad1]*/
13475 {
13476     DWORD flags;
13477 
13478     if (!GetHandleInformation((HANDLE)handle, &flags)) {
13479         PyErr_SetFromWindowsErr(0);
13480         return -1;
13481     }
13482 
13483     return flags & HANDLE_FLAG_INHERIT;
13484 }
13485 
13486 
13487 /*[clinic input]
13488 os.set_handle_inheritable
13489     handle: intptr_t
13490     inheritable: bool
13491     /
13492 
13493 Set the inheritable flag of the specified handle.
13494 [clinic start generated code]*/
13495 
13496 static PyObject *
os_set_handle_inheritable_impl(PyObject * module,intptr_t handle,int inheritable)13497 os_set_handle_inheritable_impl(PyObject *module, intptr_t handle,
13498                                int inheritable)
13499 /*[clinic end generated code: output=021d74fe6c96baa3 input=7a7641390d8364fc]*/
13500 {
13501     DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0;
13502     if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) {
13503         PyErr_SetFromWindowsErr(0);
13504         return NULL;
13505     }
13506     Py_RETURN_NONE;
13507 }
13508 #endif /* MS_WINDOWS */
13509 
13510 #ifndef MS_WINDOWS
13511 /*[clinic input]
13512 os.get_blocking -> bool
13513     fd: int
13514     /
13515 
13516 Get the blocking mode of the file descriptor.
13517 
13518 Return False if the O_NONBLOCK flag is set, True if the flag is cleared.
13519 [clinic start generated code]*/
13520 
13521 static int
os_get_blocking_impl(PyObject * module,int fd)13522 os_get_blocking_impl(PyObject *module, int fd)
13523 /*[clinic end generated code: output=336a12ad76a61482 input=f4afb59d51560179]*/
13524 {
13525     int blocking;
13526 
13527     _Py_BEGIN_SUPPRESS_IPH
13528     blocking = _Py_get_blocking(fd);
13529     _Py_END_SUPPRESS_IPH
13530     return blocking;
13531 }
13532 
13533 /*[clinic input]
13534 os.set_blocking
13535     fd: int
13536     blocking: bool(accept={int})
13537     /
13538 
13539 Set the blocking mode of the specified file descriptor.
13540 
13541 Set the O_NONBLOCK flag if blocking is False,
13542 clear the O_NONBLOCK flag otherwise.
13543 [clinic start generated code]*/
13544 
13545 static PyObject *
os_set_blocking_impl(PyObject * module,int fd,int blocking)13546 os_set_blocking_impl(PyObject *module, int fd, int blocking)
13547 /*[clinic end generated code: output=384eb43aa0762a9d input=bf5c8efdc5860ff3]*/
13548 {
13549     int result;
13550 
13551     _Py_BEGIN_SUPPRESS_IPH
13552     result = _Py_set_blocking(fd, blocking);
13553     _Py_END_SUPPRESS_IPH
13554     if (result < 0)
13555         return NULL;
13556     Py_RETURN_NONE;
13557 }
13558 #endif   /* !MS_WINDOWS */
13559 
13560 
13561 /*[clinic input]
13562 class os.DirEntry "DirEntry *" "DirEntryType"
13563 [clinic start generated code]*/
13564 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3c18c7a448247980]*/
13565 
13566 typedef struct {
13567     PyObject_HEAD
13568     PyObject *name;
13569     PyObject *path;
13570     PyObject *stat;
13571     PyObject *lstat;
13572 #ifdef MS_WINDOWS
13573     struct _Py_stat_struct win32_lstat;
13574     uint64_t win32_file_index;
13575     int got_file_index;
13576 #else /* POSIX */
13577 #ifdef HAVE_DIRENT_D_TYPE
13578     unsigned char d_type;
13579 #endif
13580     ino_t d_ino;
13581     int dir_fd;
13582 #endif
13583 } DirEntry;
13584 
13585 static void
DirEntry_dealloc(DirEntry * entry)13586 DirEntry_dealloc(DirEntry *entry)
13587 {
13588     PyTypeObject *tp = Py_TYPE(entry);
13589     Py_XDECREF(entry->name);
13590     Py_XDECREF(entry->path);
13591     Py_XDECREF(entry->stat);
13592     Py_XDECREF(entry->lstat);
13593     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
13594     free_func(entry);
13595     Py_DECREF(tp);
13596 }
13597 
13598 /* Forward reference */
13599 static int
13600 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13601                    int follow_symlinks, unsigned short mode_bits);
13602 
13603 /*[clinic input]
13604 os.DirEntry.is_symlink -> bool
13605     defining_class: defining_class
13606     /
13607 
13608 Return True if the entry is a symbolic link; cached per entry.
13609 [clinic start generated code]*/
13610 
13611 static int
os_DirEntry_is_symlink_impl(DirEntry * self,PyTypeObject * defining_class)13612 os_DirEntry_is_symlink_impl(DirEntry *self, PyTypeObject *defining_class)
13613 /*[clinic end generated code: output=293096d589b6d47c input=e9acc5ee4d511113]*/
13614 {
13615 #ifdef MS_WINDOWS
13616     return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13617 #elif defined(HAVE_DIRENT_D_TYPE)
13618     /* POSIX */
13619     if (self->d_type != DT_UNKNOWN)
13620         return self->d_type == DT_LNK;
13621     else
13622         return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13623 #else
13624     /* POSIX without d_type */
13625     return DirEntry_test_mode(defining_class, self, 0, S_IFLNK);
13626 #endif
13627 }
13628 
13629 static PyObject *
DirEntry_fetch_stat(PyObject * module,DirEntry * self,int follow_symlinks)13630 DirEntry_fetch_stat(PyObject *module, DirEntry *self, int follow_symlinks)
13631 {
13632     int result;
13633     STRUCT_STAT st;
13634     PyObject *ub;
13635 
13636 #ifdef MS_WINDOWS
13637     if (!PyUnicode_FSDecoder(self->path, &ub))
13638         return NULL;
13639 #if USE_UNICODE_WCHAR_CACHE
13640 _Py_COMP_DIAG_PUSH
13641 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13642     const wchar_t *path = PyUnicode_AsUnicode(ub);
13643 _Py_COMP_DIAG_POP
13644 #else /* USE_UNICODE_WCHAR_CACHE */
13645     wchar_t *path = PyUnicode_AsWideCharString(ub, NULL);
13646     Py_DECREF(ub);
13647 #endif /* USE_UNICODE_WCHAR_CACHE */
13648 #else /* POSIX */
13649     if (!PyUnicode_FSConverter(self->path, &ub))
13650         return NULL;
13651     const char *path = PyBytes_AS_STRING(ub);
13652     if (self->dir_fd != DEFAULT_DIR_FD) {
13653 #ifdef HAVE_FSTATAT
13654       if (HAVE_FSTATAT_RUNTIME) {
13655         Py_BEGIN_ALLOW_THREADS
13656         result = fstatat(self->dir_fd, path, &st,
13657                          follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
13658         Py_END_ALLOW_THREADS
13659       } else
13660 
13661 #endif /* HAVE_FSTATAT */
13662       {
13663         Py_DECREF(ub);
13664         PyErr_SetString(PyExc_NotImplementedError, "can't fetch stat");
13665         return NULL;
13666       }
13667     }
13668     else
13669 #endif
13670     {
13671         Py_BEGIN_ALLOW_THREADS
13672         if (follow_symlinks) {
13673             result = STAT(path, &st);
13674         }
13675         else {
13676             result = LSTAT(path, &st);
13677         }
13678         Py_END_ALLOW_THREADS
13679     }
13680 #if defined(MS_WINDOWS) && !USE_UNICODE_WCHAR_CACHE
13681     PyMem_Free(path);
13682 #else /* USE_UNICODE_WCHAR_CACHE */
13683     Py_DECREF(ub);
13684 #endif /* USE_UNICODE_WCHAR_CACHE */
13685 
13686     if (result != 0)
13687         return path_object_error(self->path);
13688 
13689     return _pystat_fromstructstat(module, &st);
13690 }
13691 
13692 static PyObject *
DirEntry_get_lstat(PyTypeObject * defining_class,DirEntry * self)13693 DirEntry_get_lstat(PyTypeObject *defining_class, DirEntry *self)
13694 {
13695     if (!self->lstat) {
13696         PyObject *module = PyType_GetModule(defining_class);
13697 #ifdef MS_WINDOWS
13698         self->lstat = _pystat_fromstructstat(module, &self->win32_lstat);
13699 #else /* POSIX */
13700         self->lstat = DirEntry_fetch_stat(module, self, 0);
13701 #endif
13702     }
13703     Py_XINCREF(self->lstat);
13704     return self->lstat;
13705 }
13706 
13707 /*[clinic input]
13708 os.DirEntry.stat
13709     defining_class: defining_class
13710     /
13711     *
13712     follow_symlinks: bool = True
13713 
13714 Return stat_result object for the entry; cached per entry.
13715 [clinic start generated code]*/
13716 
13717 static PyObject *
os_DirEntry_stat_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13718 os_DirEntry_stat_impl(DirEntry *self, PyTypeObject *defining_class,
13719                       int follow_symlinks)
13720 /*[clinic end generated code: output=23f803e19c3e780e input=e816273c4e67ee98]*/
13721 {
13722     if (!follow_symlinks) {
13723         return DirEntry_get_lstat(defining_class, self);
13724     }
13725 
13726     if (!self->stat) {
13727         int result = os_DirEntry_is_symlink_impl(self, defining_class);
13728         if (result == -1) {
13729             return NULL;
13730         }
13731         if (result) {
13732             PyObject *module = PyType_GetModule(defining_class);
13733             self->stat = DirEntry_fetch_stat(module, self, 1);
13734         }
13735         else {
13736             self->stat = DirEntry_get_lstat(defining_class, self);
13737         }
13738     }
13739 
13740     Py_XINCREF(self->stat);
13741     return self->stat;
13742 }
13743 
13744 /* Set exception and return -1 on error, 0 for False, 1 for True */
13745 static int
DirEntry_test_mode(PyTypeObject * defining_class,DirEntry * self,int follow_symlinks,unsigned short mode_bits)13746 DirEntry_test_mode(PyTypeObject *defining_class, DirEntry *self,
13747                    int follow_symlinks, unsigned short mode_bits)
13748 {
13749     PyObject *stat = NULL;
13750     PyObject *st_mode = NULL;
13751     long mode;
13752     int result;
13753 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13754     int is_symlink;
13755     int need_stat;
13756 #endif
13757 #ifdef MS_WINDOWS
13758     unsigned long dir_bits;
13759 #endif
13760 
13761 #ifdef MS_WINDOWS
13762     is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK;
13763     need_stat = follow_symlinks && is_symlink;
13764 #elif defined(HAVE_DIRENT_D_TYPE)
13765     is_symlink = self->d_type == DT_LNK;
13766     need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink);
13767 #endif
13768 
13769 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13770     if (need_stat) {
13771 #endif
13772         stat = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
13773         if (!stat) {
13774             if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) {
13775                 /* If file doesn't exist (anymore), then return False
13776                    (i.e., say it's not a file/directory) */
13777                 PyErr_Clear();
13778                 return 0;
13779             }
13780             goto error;
13781         }
13782         _posixstate* state = get_posix_state(PyType_GetModule(defining_class));
13783         st_mode = PyObject_GetAttr(stat, state->st_mode);
13784         if (!st_mode)
13785             goto error;
13786 
13787         mode = PyLong_AsLong(st_mode);
13788         if (mode == -1 && PyErr_Occurred())
13789             goto error;
13790         Py_CLEAR(st_mode);
13791         Py_CLEAR(stat);
13792         result = (mode & S_IFMT) == mode_bits;
13793 #if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE)
13794     }
13795     else if (is_symlink) {
13796         assert(mode_bits != S_IFLNK);
13797         result = 0;
13798     }
13799     else {
13800         assert(mode_bits == S_IFDIR || mode_bits == S_IFREG);
13801 #ifdef MS_WINDOWS
13802         dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY;
13803         if (mode_bits == S_IFDIR)
13804             result = dir_bits != 0;
13805         else
13806             result = dir_bits == 0;
13807 #else /* POSIX */
13808         if (mode_bits == S_IFDIR)
13809             result = self->d_type == DT_DIR;
13810         else
13811             result = self->d_type == DT_REG;
13812 #endif
13813     }
13814 #endif
13815 
13816     return result;
13817 
13818 error:
13819     Py_XDECREF(st_mode);
13820     Py_XDECREF(stat);
13821     return -1;
13822 }
13823 
13824 /*[clinic input]
13825 os.DirEntry.is_dir -> bool
13826     defining_class: defining_class
13827     /
13828     *
13829     follow_symlinks: bool = True
13830 
13831 Return True if the entry is a directory; cached per entry.
13832 [clinic start generated code]*/
13833 
13834 static int
os_DirEntry_is_dir_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13835 os_DirEntry_is_dir_impl(DirEntry *self, PyTypeObject *defining_class,
13836                         int follow_symlinks)
13837 /*[clinic end generated code: output=0cd453b9c0987fdf input=1a4ffd6dec9920cb]*/
13838 {
13839     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFDIR);
13840 }
13841 
13842 /*[clinic input]
13843 os.DirEntry.is_file -> bool
13844     defining_class: defining_class
13845     /
13846     *
13847     follow_symlinks: bool = True
13848 
13849 Return True if the entry is a file; cached per entry.
13850 [clinic start generated code]*/
13851 
13852 static int
os_DirEntry_is_file_impl(DirEntry * self,PyTypeObject * defining_class,int follow_symlinks)13853 os_DirEntry_is_file_impl(DirEntry *self, PyTypeObject *defining_class,
13854                          int follow_symlinks)
13855 /*[clinic end generated code: output=f7c277ab5ba80908 input=0a64c5a12e802e3b]*/
13856 {
13857     return DirEntry_test_mode(defining_class, self, follow_symlinks, S_IFREG);
13858 }
13859 
13860 /*[clinic input]
13861 os.DirEntry.inode
13862 
13863 Return inode of the entry; cached per entry.
13864 [clinic start generated code]*/
13865 
13866 static PyObject *
os_DirEntry_inode_impl(DirEntry * self)13867 os_DirEntry_inode_impl(DirEntry *self)
13868 /*[clinic end generated code: output=156bb3a72162440e input=3ee7b872ae8649f0]*/
13869 {
13870 #ifdef MS_WINDOWS
13871     if (!self->got_file_index) {
13872         PyObject *unicode;
13873         STRUCT_STAT stat;
13874         int result;
13875 
13876         if (!PyUnicode_FSDecoder(self->path, &unicode))
13877             return NULL;
13878 #if USE_UNICODE_WCHAR_CACHE
13879 _Py_COMP_DIAG_PUSH
13880 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
13881         const wchar_t *path = PyUnicode_AsUnicode(unicode);
13882         result = LSTAT(path, &stat);
13883         Py_DECREF(unicode);
13884 _Py_COMP_DIAG_POP
13885 #else /* USE_UNICODE_WCHAR_CACHE */
13886         wchar_t *path = PyUnicode_AsWideCharString(unicode, NULL);
13887         Py_DECREF(unicode);
13888         result = LSTAT(path, &stat);
13889         PyMem_Free(path);
13890 #endif /* USE_UNICODE_WCHAR_CACHE */
13891 
13892         if (result != 0)
13893             return path_object_error(self->path);
13894 
13895         self->win32_file_index = stat.st_ino;
13896         self->got_file_index = 1;
13897     }
13898     static_assert(sizeof(unsigned long long) >= sizeof(self->win32_file_index),
13899                   "DirEntry.win32_file_index is larger than unsigned long long");
13900     return PyLong_FromUnsignedLongLong(self->win32_file_index);
13901 #else /* POSIX */
13902     static_assert(sizeof(unsigned long long) >= sizeof(self->d_ino),
13903                   "DirEntry.d_ino is larger than unsigned long long");
13904     return PyLong_FromUnsignedLongLong(self->d_ino);
13905 #endif
13906 }
13907 
13908 static PyObject *
DirEntry_repr(DirEntry * self)13909 DirEntry_repr(DirEntry *self)
13910 {
13911     return PyUnicode_FromFormat("<DirEntry %R>", self->name);
13912 }
13913 
13914 /*[clinic input]
13915 os.DirEntry.__fspath__
13916 
13917 Returns the path for the entry.
13918 [clinic start generated code]*/
13919 
13920 static PyObject *
os_DirEntry___fspath___impl(DirEntry * self)13921 os_DirEntry___fspath___impl(DirEntry *self)
13922 /*[clinic end generated code: output=6dd7f7ef752e6f4f input=3c49d0cf38df4fac]*/
13923 {
13924     Py_INCREF(self->path);
13925     return self->path;
13926 }
13927 
13928 static PyMemberDef DirEntry_members[] = {
13929     {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY,
13930      "the entry's base filename, relative to scandir() \"path\" argument"},
13931     {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY,
13932      "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"},
13933     {NULL}
13934 };
13935 
13936 #include "clinic/posixmodule.c.h"
13937 
13938 static PyMethodDef DirEntry_methods[] = {
13939     OS_DIRENTRY_IS_DIR_METHODDEF
13940     OS_DIRENTRY_IS_FILE_METHODDEF
13941     OS_DIRENTRY_IS_SYMLINK_METHODDEF
13942     OS_DIRENTRY_STAT_METHODDEF
13943     OS_DIRENTRY_INODE_METHODDEF
13944     OS_DIRENTRY___FSPATH___METHODDEF
13945     {"__class_getitem__",       Py_GenericAlias,
13946     METH_O|METH_CLASS,          PyDoc_STR("See PEP 585")},
13947     {NULL}
13948 };
13949 
13950 static PyType_Slot DirEntryType_slots[] = {
13951     {Py_tp_dealloc, DirEntry_dealloc},
13952     {Py_tp_repr, DirEntry_repr},
13953     {Py_tp_methods, DirEntry_methods},
13954     {Py_tp_members, DirEntry_members},
13955     {0, 0},
13956 };
13957 
13958 static PyType_Spec DirEntryType_spec = {
13959     MODNAME ".DirEntry",
13960     sizeof(DirEntry),
13961     0,
13962     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
13963     DirEntryType_slots
13964 };
13965 
13966 
13967 #ifdef MS_WINDOWS
13968 
13969 static wchar_t *
join_path_filenameW(const wchar_t * path_wide,const wchar_t * filename)13970 join_path_filenameW(const wchar_t *path_wide, const wchar_t *filename)
13971 {
13972     Py_ssize_t path_len;
13973     Py_ssize_t size;
13974     wchar_t *result;
13975     wchar_t ch;
13976 
13977     if (!path_wide) { /* Default arg: "." */
13978         path_wide = L".";
13979         path_len = 1;
13980     }
13981     else {
13982         path_len = wcslen(path_wide);
13983     }
13984 
13985     /* The +1's are for the path separator and the NUL */
13986     size = path_len + 1 + wcslen(filename) + 1;
13987     result = PyMem_New(wchar_t, size);
13988     if (!result) {
13989         PyErr_NoMemory();
13990         return NULL;
13991     }
13992     wcscpy(result, path_wide);
13993     if (path_len > 0) {
13994         ch = result[path_len - 1];
13995         if (ch != SEP && ch != ALTSEP && ch != L':')
13996             result[path_len++] = SEP;
13997         wcscpy(result + path_len, filename);
13998     }
13999     return result;
14000 }
14001 
14002 static PyObject *
DirEntry_from_find_data(PyObject * module,path_t * path,WIN32_FIND_DATAW * dataW)14003 DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
14004 {
14005     DirEntry *entry;
14006     BY_HANDLE_FILE_INFORMATION file_info;
14007     ULONG reparse_tag;
14008     wchar_t *joined_path;
14009 
14010     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14011     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14012     if (!entry)
14013         return NULL;
14014     entry->name = NULL;
14015     entry->path = NULL;
14016     entry->stat = NULL;
14017     entry->lstat = NULL;
14018     entry->got_file_index = 0;
14019 
14020     entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1);
14021     if (!entry->name)
14022         goto error;
14023     if (path->narrow) {
14024         Py_SETREF(entry->name, PyUnicode_EncodeFSDefault(entry->name));
14025         if (!entry->name)
14026             goto error;
14027     }
14028 
14029     joined_path = join_path_filenameW(path->wide, dataW->cFileName);
14030     if (!joined_path)
14031         goto error;
14032 
14033     entry->path = PyUnicode_FromWideChar(joined_path, -1);
14034     PyMem_Free(joined_path);
14035     if (!entry->path)
14036         goto error;
14037     if (path->narrow) {
14038         Py_SETREF(entry->path, PyUnicode_EncodeFSDefault(entry->path));
14039         if (!entry->path)
14040             goto error;
14041     }
14042 
14043     find_data_to_file_info(dataW, &file_info, &reparse_tag);
14044     _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat);
14045 
14046     return (PyObject *)entry;
14047 
14048 error:
14049     Py_DECREF(entry);
14050     return NULL;
14051 }
14052 
14053 #else /* POSIX */
14054 
14055 static char *
join_path_filename(const char * path_narrow,const char * filename,Py_ssize_t filename_len)14056 join_path_filename(const char *path_narrow, const char* filename, Py_ssize_t filename_len)
14057 {
14058     Py_ssize_t path_len;
14059     Py_ssize_t size;
14060     char *result;
14061 
14062     if (!path_narrow) { /* Default arg: "." */
14063         path_narrow = ".";
14064         path_len = 1;
14065     }
14066     else {
14067         path_len = strlen(path_narrow);
14068     }
14069 
14070     if (filename_len == -1)
14071         filename_len = strlen(filename);
14072 
14073     /* The +1's are for the path separator and the NUL */
14074     size = path_len + 1 + filename_len + 1;
14075     result = PyMem_New(char, size);
14076     if (!result) {
14077         PyErr_NoMemory();
14078         return NULL;
14079     }
14080     strcpy(result, path_narrow);
14081     if (path_len > 0 && result[path_len - 1] != '/')
14082         result[path_len++] = '/';
14083     strcpy(result + path_len, filename);
14084     return result;
14085 }
14086 
14087 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)14088 DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
14089                          Py_ssize_t name_len, ino_t d_ino
14090 #ifdef HAVE_DIRENT_D_TYPE
14091                          , unsigned char d_type
14092 #endif
14093                          )
14094 {
14095     DirEntry *entry;
14096     char *joined_path;
14097 
14098     PyObject *DirEntryType = get_posix_state(module)->DirEntryType;
14099     entry = PyObject_New(DirEntry, (PyTypeObject *)DirEntryType);
14100     if (!entry)
14101         return NULL;
14102     entry->name = NULL;
14103     entry->path = NULL;
14104     entry->stat = NULL;
14105     entry->lstat = NULL;
14106 
14107     if (path->fd != -1) {
14108         entry->dir_fd = path->fd;
14109         joined_path = NULL;
14110     }
14111     else {
14112         entry->dir_fd = DEFAULT_DIR_FD;
14113         joined_path = join_path_filename(path->narrow, name, name_len);
14114         if (!joined_path)
14115             goto error;
14116     }
14117 
14118     if (!path->narrow || !PyObject_CheckBuffer(path->object)) {
14119         entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len);
14120         if (joined_path)
14121             entry->path = PyUnicode_DecodeFSDefault(joined_path);
14122     }
14123     else {
14124         entry->name = PyBytes_FromStringAndSize(name, name_len);
14125         if (joined_path)
14126             entry->path = PyBytes_FromString(joined_path);
14127     }
14128     PyMem_Free(joined_path);
14129     if (!entry->name)
14130         goto error;
14131 
14132     if (path->fd != -1) {
14133         entry->path = entry->name;
14134         Py_INCREF(entry->path);
14135     }
14136     else if (!entry->path)
14137         goto error;
14138 
14139 #ifdef HAVE_DIRENT_D_TYPE
14140     entry->d_type = d_type;
14141 #endif
14142     entry->d_ino = d_ino;
14143 
14144     return (PyObject *)entry;
14145 
14146 error:
14147     Py_XDECREF(entry);
14148     return NULL;
14149 }
14150 
14151 #endif
14152 
14153 
14154 typedef struct {
14155     PyObject_HEAD
14156     path_t path;
14157 #ifdef MS_WINDOWS
14158     HANDLE handle;
14159     WIN32_FIND_DATAW file_data;
14160     int first_time;
14161 #else /* POSIX */
14162     DIR *dirp;
14163 #endif
14164 #ifdef HAVE_FDOPENDIR
14165     int fd;
14166 #endif
14167 } ScandirIterator;
14168 
14169 #ifdef MS_WINDOWS
14170 
14171 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14172 ScandirIterator_is_closed(ScandirIterator *iterator)
14173 {
14174     return iterator->handle == INVALID_HANDLE_VALUE;
14175 }
14176 
14177 static void
ScandirIterator_closedir(ScandirIterator * iterator)14178 ScandirIterator_closedir(ScandirIterator *iterator)
14179 {
14180     HANDLE handle = iterator->handle;
14181 
14182     if (handle == INVALID_HANDLE_VALUE)
14183         return;
14184 
14185     iterator->handle = INVALID_HANDLE_VALUE;
14186     Py_BEGIN_ALLOW_THREADS
14187     FindClose(handle);
14188     Py_END_ALLOW_THREADS
14189 }
14190 
14191 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14192 ScandirIterator_iternext(ScandirIterator *iterator)
14193 {
14194     WIN32_FIND_DATAW *file_data = &iterator->file_data;
14195     BOOL success;
14196     PyObject *entry;
14197 
14198     /* Happens if the iterator is iterated twice, or closed explicitly */
14199     if (iterator->handle == INVALID_HANDLE_VALUE)
14200         return NULL;
14201 
14202     while (1) {
14203         if (!iterator->first_time) {
14204             Py_BEGIN_ALLOW_THREADS
14205             success = FindNextFileW(iterator->handle, file_data);
14206             Py_END_ALLOW_THREADS
14207             if (!success) {
14208                 /* Error or no more files */
14209                 if (GetLastError() != ERROR_NO_MORE_FILES)
14210                     path_error(&iterator->path);
14211                 break;
14212             }
14213         }
14214         iterator->first_time = 0;
14215 
14216         /* Skip over . and .. */
14217         if (wcscmp(file_data->cFileName, L".") != 0 &&
14218             wcscmp(file_data->cFileName, L"..") != 0)
14219         {
14220             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14221             entry = DirEntry_from_find_data(module, &iterator->path, file_data);
14222             if (!entry)
14223                 break;
14224             return entry;
14225         }
14226 
14227         /* Loop till we get a non-dot directory or finish iterating */
14228     }
14229 
14230     /* Error or no more files */
14231     ScandirIterator_closedir(iterator);
14232     return NULL;
14233 }
14234 
14235 #else /* POSIX */
14236 
14237 static int
ScandirIterator_is_closed(ScandirIterator * iterator)14238 ScandirIterator_is_closed(ScandirIterator *iterator)
14239 {
14240     return !iterator->dirp;
14241 }
14242 
14243 static void
ScandirIterator_closedir(ScandirIterator * iterator)14244 ScandirIterator_closedir(ScandirIterator *iterator)
14245 {
14246     DIR *dirp = iterator->dirp;
14247 
14248     if (!dirp)
14249         return;
14250 
14251     iterator->dirp = NULL;
14252     Py_BEGIN_ALLOW_THREADS
14253 #ifdef HAVE_FDOPENDIR
14254     if (iterator->path.fd != -1)
14255         rewinddir(dirp);
14256 #endif
14257     closedir(dirp);
14258     Py_END_ALLOW_THREADS
14259     return;
14260 }
14261 
14262 static PyObject *
ScandirIterator_iternext(ScandirIterator * iterator)14263 ScandirIterator_iternext(ScandirIterator *iterator)
14264 {
14265     struct dirent *direntp;
14266     Py_ssize_t name_len;
14267     int is_dot;
14268     PyObject *entry;
14269 
14270     /* Happens if the iterator is iterated twice, or closed explicitly */
14271     if (!iterator->dirp)
14272         return NULL;
14273 
14274     while (1) {
14275         errno = 0;
14276         Py_BEGIN_ALLOW_THREADS
14277         direntp = readdir(iterator->dirp);
14278         Py_END_ALLOW_THREADS
14279 
14280         if (!direntp) {
14281             /* Error or no more files */
14282             if (errno != 0)
14283                 path_error(&iterator->path);
14284             break;
14285         }
14286 
14287         /* Skip over . and .. */
14288         name_len = NAMLEN(direntp);
14289         is_dot = direntp->d_name[0] == '.' &&
14290                  (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2));
14291         if (!is_dot) {
14292             PyObject *module = PyType_GetModule(Py_TYPE(iterator));
14293             entry = DirEntry_from_posix_info(module,
14294                                              &iterator->path, direntp->d_name,
14295                                              name_len, direntp->d_ino
14296 #ifdef HAVE_DIRENT_D_TYPE
14297                                              , direntp->d_type
14298 #endif
14299                                             );
14300             if (!entry)
14301                 break;
14302             return entry;
14303         }
14304 
14305         /* Loop till we get a non-dot directory or finish iterating */
14306     }
14307 
14308     /* Error or no more files */
14309     ScandirIterator_closedir(iterator);
14310     return NULL;
14311 }
14312 
14313 #endif
14314 
14315 static PyObject *
ScandirIterator_close(ScandirIterator * self,PyObject * args)14316 ScandirIterator_close(ScandirIterator *self, PyObject *args)
14317 {
14318     ScandirIterator_closedir(self);
14319     Py_RETURN_NONE;
14320 }
14321 
14322 static PyObject *
ScandirIterator_enter(PyObject * self,PyObject * args)14323 ScandirIterator_enter(PyObject *self, PyObject *args)
14324 {
14325     Py_INCREF(self);
14326     return self;
14327 }
14328 
14329 static PyObject *
ScandirIterator_exit(ScandirIterator * self,PyObject * args)14330 ScandirIterator_exit(ScandirIterator *self, PyObject *args)
14331 {
14332     ScandirIterator_closedir(self);
14333     Py_RETURN_NONE;
14334 }
14335 
14336 static void
ScandirIterator_finalize(ScandirIterator * iterator)14337 ScandirIterator_finalize(ScandirIterator *iterator)
14338 {
14339     PyObject *error_type, *error_value, *error_traceback;
14340 
14341     /* Save the current exception, if any. */
14342     PyErr_Fetch(&error_type, &error_value, &error_traceback);
14343 
14344     if (!ScandirIterator_is_closed(iterator)) {
14345         ScandirIterator_closedir(iterator);
14346 
14347         if (PyErr_ResourceWarning((PyObject *)iterator, 1,
14348                                   "unclosed scandir iterator %R", iterator)) {
14349             /* Spurious errors can appear at shutdown */
14350             if (PyErr_ExceptionMatches(PyExc_Warning)) {
14351                 PyErr_WriteUnraisable((PyObject *) iterator);
14352             }
14353         }
14354     }
14355 
14356     path_cleanup(&iterator->path);
14357 
14358     /* Restore the saved exception. */
14359     PyErr_Restore(error_type, error_value, error_traceback);
14360 }
14361 
14362 static void
ScandirIterator_dealloc(ScandirIterator * iterator)14363 ScandirIterator_dealloc(ScandirIterator *iterator)
14364 {
14365     PyTypeObject *tp = Py_TYPE(iterator);
14366     if (PyObject_CallFinalizerFromDealloc((PyObject *)iterator) < 0)
14367         return;
14368 
14369     freefunc free_func = PyType_GetSlot(tp, Py_tp_free);
14370     free_func(iterator);
14371     Py_DECREF(tp);
14372 }
14373 
14374 static PyMethodDef ScandirIterator_methods[] = {
14375     {"__enter__", (PyCFunction)ScandirIterator_enter, METH_NOARGS},
14376     {"__exit__", (PyCFunction)ScandirIterator_exit, METH_VARARGS},
14377     {"close", (PyCFunction)ScandirIterator_close, METH_NOARGS},
14378     {NULL}
14379 };
14380 
14381 static PyType_Slot ScandirIteratorType_slots[] = {
14382     {Py_tp_dealloc, ScandirIterator_dealloc},
14383     {Py_tp_finalize, ScandirIterator_finalize},
14384     {Py_tp_iter, PyObject_SelfIter},
14385     {Py_tp_iternext, ScandirIterator_iternext},
14386     {Py_tp_methods, ScandirIterator_methods},
14387     {0, 0},
14388 };
14389 
14390 static PyType_Spec ScandirIteratorType_spec = {
14391     MODNAME ".ScandirIterator",
14392     sizeof(ScandirIterator),
14393     0,
14394     // bpo-40549: Py_TPFLAGS_BASETYPE should not be used, since
14395     // PyType_GetModule(Py_TYPE(self)) doesn't work on a subclass instance.
14396     (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_FINALIZE
14397         | Py_TPFLAGS_DISALLOW_INSTANTIATION),
14398     ScandirIteratorType_slots
14399 };
14400 
14401 /*[clinic input]
14402 os.scandir
14403 
14404     path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None
14405 
14406 Return an iterator of DirEntry objects for given path.
14407 
14408 path can be specified as either str, bytes, or a path-like object.  If path
14409 is bytes, the names of yielded DirEntry objects will also be bytes; in
14410 all other circumstances they will be str.
14411 
14412 If path is None, uses the path='.'.
14413 [clinic start generated code]*/
14414 
14415 static PyObject *
os_scandir_impl(PyObject * module,path_t * path)14416 os_scandir_impl(PyObject *module, path_t *path)
14417 /*[clinic end generated code: output=6eb2668b675ca89e input=6bdd312708fc3bb0]*/
14418 {
14419     ScandirIterator *iterator;
14420 #ifdef MS_WINDOWS
14421     wchar_t *path_strW;
14422 #else
14423     const char *path_str;
14424 #ifdef HAVE_FDOPENDIR
14425     int fd = -1;
14426 #endif
14427 #endif
14428 
14429     if (PySys_Audit("os.scandir", "O",
14430                     path->object ? path->object : Py_None) < 0) {
14431         return NULL;
14432     }
14433 
14434     PyObject *ScandirIteratorType = get_posix_state(module)->ScandirIteratorType;
14435     iterator = PyObject_New(ScandirIterator, (PyTypeObject *)ScandirIteratorType);
14436     if (!iterator)
14437         return NULL;
14438 
14439 #ifdef MS_WINDOWS
14440     iterator->handle = INVALID_HANDLE_VALUE;
14441 #else
14442     iterator->dirp = NULL;
14443 #endif
14444 
14445     /* Move the ownership to iterator->path */
14446     memcpy(&iterator->path, path, sizeof(path_t));
14447     memset(path, 0, sizeof(path_t));
14448 
14449 #ifdef MS_WINDOWS
14450     iterator->first_time = 1;
14451 
14452     path_strW = join_path_filenameW(iterator->path.wide, L"*.*");
14453     if (!path_strW)
14454         goto error;
14455 
14456     Py_BEGIN_ALLOW_THREADS
14457     iterator->handle = FindFirstFileW(path_strW, &iterator->file_data);
14458     Py_END_ALLOW_THREADS
14459 
14460     PyMem_Free(path_strW);
14461 
14462     if (iterator->handle == INVALID_HANDLE_VALUE) {
14463         path_error(&iterator->path);
14464         goto error;
14465     }
14466 #else /* POSIX */
14467     errno = 0;
14468 #ifdef HAVE_FDOPENDIR
14469     if (iterator->path.fd != -1) {
14470       if (HAVE_FDOPENDIR_RUNTIME) {
14471         /* closedir() closes the FD, so we duplicate it */
14472         fd = _Py_dup(iterator->path.fd);
14473         if (fd == -1)
14474             goto error;
14475 
14476         Py_BEGIN_ALLOW_THREADS
14477         iterator->dirp = fdopendir(fd);
14478         Py_END_ALLOW_THREADS
14479       } else {
14480         PyErr_SetString(PyExc_TypeError,
14481             "scandir: path should be string, bytes, os.PathLike or None, not int");
14482         return NULL;
14483       }
14484     }
14485     else
14486 #endif
14487     {
14488         if (iterator->path.narrow)
14489             path_str = iterator->path.narrow;
14490         else
14491             path_str = ".";
14492 
14493         Py_BEGIN_ALLOW_THREADS
14494         iterator->dirp = opendir(path_str);
14495         Py_END_ALLOW_THREADS
14496     }
14497 
14498     if (!iterator->dirp) {
14499         path_error(&iterator->path);
14500 #ifdef HAVE_FDOPENDIR
14501         if (fd != -1) {
14502             Py_BEGIN_ALLOW_THREADS
14503             close(fd);
14504             Py_END_ALLOW_THREADS
14505         }
14506 #endif
14507         goto error;
14508     }
14509 #endif
14510 
14511     return (PyObject *)iterator;
14512 
14513 error:
14514     Py_DECREF(iterator);
14515     return NULL;
14516 }
14517 
14518 /*
14519     Return the file system path representation of the object.
14520 
14521     If the object is str or bytes, then allow it to pass through with
14522     an incremented refcount. If the object defines __fspath__(), then
14523     return the result of that method. All other types raise a TypeError.
14524 */
14525 PyObject *
PyOS_FSPath(PyObject * path)14526 PyOS_FSPath(PyObject *path)
14527 {
14528     /* For error message reasons, this function is manually inlined in
14529        path_converter(). */
14530     PyObject *func = NULL;
14531     PyObject *path_repr = NULL;
14532 
14533     if (PyUnicode_Check(path) || PyBytes_Check(path)) {
14534         Py_INCREF(path);
14535         return path;
14536     }
14537 
14538     func = _PyObject_LookupSpecial(path, &_Py_ID(__fspath__));
14539     if (NULL == func) {
14540         return PyErr_Format(PyExc_TypeError,
14541                             "expected str, bytes or os.PathLike object, "
14542                             "not %.200s",
14543                             _PyType_Name(Py_TYPE(path)));
14544     }
14545 
14546     path_repr = _PyObject_CallNoArgs(func);
14547     Py_DECREF(func);
14548     if (NULL == path_repr) {
14549         return NULL;
14550     }
14551 
14552     if (!(PyUnicode_Check(path_repr) || PyBytes_Check(path_repr))) {
14553         PyErr_Format(PyExc_TypeError,
14554                      "expected %.200s.__fspath__() to return str or bytes, "
14555                      "not %.200s", _PyType_Name(Py_TYPE(path)),
14556                      _PyType_Name(Py_TYPE(path_repr)));
14557         Py_DECREF(path_repr);
14558         return NULL;
14559     }
14560 
14561     return path_repr;
14562 }
14563 
14564 /*[clinic input]
14565 os.fspath
14566 
14567     path: object
14568 
14569 Return the file system path representation of the object.
14570 
14571 If the object is str or bytes, then allow it to pass through as-is. If the
14572 object defines __fspath__(), then return the result of that method. All other
14573 types raise a TypeError.
14574 [clinic start generated code]*/
14575 
14576 static PyObject *
os_fspath_impl(PyObject * module,PyObject * path)14577 os_fspath_impl(PyObject *module, PyObject *path)
14578 /*[clinic end generated code: output=c3c3b78ecff2914f input=e357165f7b22490f]*/
14579 {
14580     return PyOS_FSPath(path);
14581 }
14582 
14583 #ifdef HAVE_GETRANDOM_SYSCALL
14584 /*[clinic input]
14585 os.getrandom
14586 
14587     size: Py_ssize_t
14588     flags: int=0
14589 
14590 Obtain a series of random bytes.
14591 [clinic start generated code]*/
14592 
14593 static PyObject *
os_getrandom_impl(PyObject * module,Py_ssize_t size,int flags)14594 os_getrandom_impl(PyObject *module, Py_ssize_t size, int flags)
14595 /*[clinic end generated code: output=b3a618196a61409c input=59bafac39c594947]*/
14596 {
14597     PyObject *bytes;
14598     Py_ssize_t n;
14599 
14600     if (size < 0) {
14601         errno = EINVAL;
14602         return posix_error();
14603     }
14604 
14605     bytes = PyBytes_FromStringAndSize(NULL, size);
14606     if (bytes == NULL) {
14607         PyErr_NoMemory();
14608         return NULL;
14609     }
14610 
14611     while (1) {
14612         n = syscall(SYS_getrandom,
14613                     PyBytes_AS_STRING(bytes),
14614                     PyBytes_GET_SIZE(bytes),
14615                     flags);
14616         if (n < 0 && errno == EINTR) {
14617             if (PyErr_CheckSignals() < 0) {
14618                 goto error;
14619             }
14620 
14621             /* getrandom() was interrupted by a signal: retry */
14622             continue;
14623         }
14624         break;
14625     }
14626 
14627     if (n < 0) {
14628         PyErr_SetFromErrno(PyExc_OSError);
14629         goto error;
14630     }
14631 
14632     if (n != size) {
14633         _PyBytes_Resize(&bytes, n);
14634     }
14635 
14636     return bytes;
14637 
14638 error:
14639     Py_DECREF(bytes);
14640     return NULL;
14641 }
14642 #endif   /* HAVE_GETRANDOM_SYSCALL */
14643 
14644 #ifdef MS_WINDOWS
14645 /* bpo-36085: Helper functions for managing DLL search directories
14646  * on win32
14647  */
14648 
14649 typedef DLL_DIRECTORY_COOKIE (WINAPI *PAddDllDirectory)(PCWSTR newDirectory);
14650 typedef BOOL (WINAPI *PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE cookie);
14651 
14652 /*[clinic input]
14653 os._add_dll_directory
14654 
14655     path: path_t
14656 
14657 Add a path to the DLL search path.
14658 
14659 This search path is used when resolving dependencies for imported
14660 extension modules (the module itself is resolved through sys.path),
14661 and also by ctypes.
14662 
14663 Returns an opaque value that may be passed to os.remove_dll_directory
14664 to remove this directory from the search path.
14665 [clinic start generated code]*/
14666 
14667 static PyObject *
os__add_dll_directory_impl(PyObject * module,path_t * path)14668 os__add_dll_directory_impl(PyObject *module, path_t *path)
14669 /*[clinic end generated code: output=80b025daebb5d683 input=1de3e6c13a5808c8]*/
14670 {
14671     HMODULE hKernel32;
14672     PAddDllDirectory AddDllDirectory;
14673     DLL_DIRECTORY_COOKIE cookie = 0;
14674     DWORD err = 0;
14675 
14676     if (PySys_Audit("os.add_dll_directory", "(O)", path->object) < 0) {
14677         return NULL;
14678     }
14679 
14680     /* For Windows 7, we have to load this. As this will be a fairly
14681        infrequent operation, just do it each time. Kernel32 is always
14682        loaded. */
14683     Py_BEGIN_ALLOW_THREADS
14684     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14685         !(AddDllDirectory = (PAddDllDirectory)GetProcAddress(
14686             hKernel32, "AddDllDirectory")) ||
14687         !(cookie = (*AddDllDirectory)(path->wide))) {
14688         err = GetLastError();
14689     }
14690     Py_END_ALLOW_THREADS
14691 
14692     if (err) {
14693         return win32_error_object_err("add_dll_directory",
14694                                       path->object, err);
14695     }
14696 
14697     return PyCapsule_New(cookie, "DLL directory cookie", NULL);
14698 }
14699 
14700 /*[clinic input]
14701 os._remove_dll_directory
14702 
14703     cookie: object
14704 
14705 Removes a path from the DLL search path.
14706 
14707 The parameter is an opaque value that was returned from
14708 os.add_dll_directory. You can only remove directories that you added
14709 yourself.
14710 [clinic start generated code]*/
14711 
14712 static PyObject *
os__remove_dll_directory_impl(PyObject * module,PyObject * cookie)14713 os__remove_dll_directory_impl(PyObject *module, PyObject *cookie)
14714 /*[clinic end generated code: output=594350433ae535bc input=c1d16a7e7d9dc5dc]*/
14715 {
14716     HMODULE hKernel32;
14717     PRemoveDllDirectory RemoveDllDirectory;
14718     DLL_DIRECTORY_COOKIE cookieValue;
14719     DWORD err = 0;
14720 
14721     if (!PyCapsule_IsValid(cookie, "DLL directory cookie")) {
14722         PyErr_SetString(PyExc_TypeError,
14723             "Provided cookie was not returned from os.add_dll_directory");
14724         return NULL;
14725     }
14726 
14727     cookieValue = (DLL_DIRECTORY_COOKIE)PyCapsule_GetPointer(
14728         cookie, "DLL directory cookie");
14729 
14730     /* For Windows 7, we have to load this. As this will be a fairly
14731        infrequent operation, just do it each time. Kernel32 is always
14732        loaded. */
14733     Py_BEGIN_ALLOW_THREADS
14734     if (!(hKernel32 = GetModuleHandleW(L"kernel32")) ||
14735         !(RemoveDllDirectory = (PRemoveDllDirectory)GetProcAddress(
14736             hKernel32, "RemoveDllDirectory")) ||
14737         !(*RemoveDllDirectory)(cookieValue)) {
14738         err = GetLastError();
14739     }
14740     Py_END_ALLOW_THREADS
14741 
14742     if (err) {
14743         return win32_error_object_err("remove_dll_directory",
14744                                       NULL, err);
14745     }
14746 
14747     if (PyCapsule_SetName(cookie, NULL)) {
14748         return NULL;
14749     }
14750 
14751     Py_RETURN_NONE;
14752 }
14753 
14754 #endif
14755 
14756 
14757 /* Only check if WIFEXITED is available: expect that it comes
14758    with WEXITSTATUS, WIFSIGNALED, etc.
14759 
14760    os.waitstatus_to_exitcode() is implemented in C and not in Python, so
14761    subprocess can safely call it during late Python finalization without
14762    risking that used os attributes were set to None by finalize_modules(). */
14763 #if defined(WIFEXITED) || defined(MS_WINDOWS)
14764 /*[clinic input]
14765 os.waitstatus_to_exitcode
14766 
14767     status as status_obj: object
14768 
14769 Convert a wait status to an exit code.
14770 
14771 On Unix:
14772 
14773 * If WIFEXITED(status) is true, return WEXITSTATUS(status).
14774 * If WIFSIGNALED(status) is true, return -WTERMSIG(status).
14775 * Otherwise, raise a ValueError.
14776 
14777 On Windows, return status shifted right by 8 bits.
14778 
14779 On Unix, if the process is being traced or if waitpid() was called with
14780 WUNTRACED option, the caller must first check if WIFSTOPPED(status) is true.
14781 This function must not be called if WIFSTOPPED(status) is true.
14782 [clinic start generated code]*/
14783 
14784 static PyObject *
os_waitstatus_to_exitcode_impl(PyObject * module,PyObject * status_obj)14785 os_waitstatus_to_exitcode_impl(PyObject *module, PyObject *status_obj)
14786 /*[clinic end generated code: output=db50b1b0ba3c7153 input=7fe2d7fdaea3db42]*/
14787 {
14788 #ifndef MS_WINDOWS
14789     int status = _PyLong_AsInt(status_obj);
14790     if (status == -1 && PyErr_Occurred()) {
14791         return NULL;
14792     }
14793 
14794     WAIT_TYPE wait_status;
14795     WAIT_STATUS_INT(wait_status) = status;
14796     int exitcode;
14797     if (WIFEXITED(wait_status)) {
14798         exitcode = WEXITSTATUS(wait_status);
14799         /* Sanity check to provide warranty on the function behavior.
14800            It should not occur in practice */
14801         if (exitcode < 0) {
14802             PyErr_Format(PyExc_ValueError, "invalid WEXITSTATUS: %i", exitcode);
14803             return NULL;
14804         }
14805     }
14806     else if (WIFSIGNALED(wait_status)) {
14807         int signum = WTERMSIG(wait_status);
14808         /* Sanity check to provide warranty on the function behavior.
14809            It should not occurs in practice */
14810         if (signum <= 0) {
14811             PyErr_Format(PyExc_ValueError, "invalid WTERMSIG: %i", signum);
14812             return NULL;
14813         }
14814         exitcode = -signum;
14815     } else if (WIFSTOPPED(wait_status)) {
14816         /* Status only received if the process is being traced
14817            or if waitpid() was called with WUNTRACED option. */
14818         int signum = WSTOPSIG(wait_status);
14819         PyErr_Format(PyExc_ValueError,
14820                      "process stopped by delivery of signal %i",
14821                      signum);
14822         return NULL;
14823     }
14824     else {
14825         PyErr_Format(PyExc_ValueError, "invalid wait status: %i", status);
14826         return NULL;
14827     }
14828     return PyLong_FromLong(exitcode);
14829 #else
14830     /* Windows implementation: see os.waitpid() implementation
14831        which uses _cwait(). */
14832     unsigned long long status = PyLong_AsUnsignedLongLong(status_obj);
14833     if (status == (unsigned long long)-1 && PyErr_Occurred()) {
14834         return NULL;
14835     }
14836 
14837     unsigned long long exitcode = (status >> 8);
14838     /* ExitProcess() accepts an UINT type:
14839        reject exit code which doesn't fit in an UINT */
14840     if (exitcode > UINT_MAX) {
14841         PyErr_Format(PyExc_ValueError, "invalid exit code: %llu", exitcode);
14842         return NULL;
14843     }
14844     return PyLong_FromUnsignedLong((unsigned long)exitcode);
14845 #endif
14846 }
14847 #endif
14848 
14849 
14850 static PyMethodDef posix_methods[] = {
14851 
14852     OS_STAT_METHODDEF
14853     OS_ACCESS_METHODDEF
14854     OS_TTYNAME_METHODDEF
14855     OS_CHDIR_METHODDEF
14856     OS_CHFLAGS_METHODDEF
14857     OS_CHMOD_METHODDEF
14858     OS_FCHMOD_METHODDEF
14859     OS_LCHMOD_METHODDEF
14860     OS_CHOWN_METHODDEF
14861     OS_FCHOWN_METHODDEF
14862     OS_LCHOWN_METHODDEF
14863     OS_LCHFLAGS_METHODDEF
14864     OS_CHROOT_METHODDEF
14865     OS_CTERMID_METHODDEF
14866     OS_GETCWD_METHODDEF
14867     OS_GETCWDB_METHODDEF
14868     OS_LINK_METHODDEF
14869     OS_LISTDIR_METHODDEF
14870     OS_LSTAT_METHODDEF
14871     OS_MKDIR_METHODDEF
14872     OS_NICE_METHODDEF
14873     OS_GETPRIORITY_METHODDEF
14874     OS_SETPRIORITY_METHODDEF
14875     OS_POSIX_SPAWN_METHODDEF
14876     OS_POSIX_SPAWNP_METHODDEF
14877     OS_READLINK_METHODDEF
14878     OS_COPY_FILE_RANGE_METHODDEF
14879     OS_SPLICE_METHODDEF
14880     OS_RENAME_METHODDEF
14881     OS_REPLACE_METHODDEF
14882     OS_RMDIR_METHODDEF
14883     OS_SYMLINK_METHODDEF
14884     OS_SYSTEM_METHODDEF
14885     OS_UMASK_METHODDEF
14886     OS_UNAME_METHODDEF
14887     OS_UNLINK_METHODDEF
14888     OS_REMOVE_METHODDEF
14889     OS_UTIME_METHODDEF
14890     OS_TIMES_METHODDEF
14891     OS__EXIT_METHODDEF
14892     OS__FCOPYFILE_METHODDEF
14893     OS_EXECV_METHODDEF
14894     OS_EXECVE_METHODDEF
14895     OS_SPAWNV_METHODDEF
14896     OS_SPAWNVE_METHODDEF
14897     OS_FORK1_METHODDEF
14898     OS_FORK_METHODDEF
14899     OS_REGISTER_AT_FORK_METHODDEF
14900     OS_SCHED_GET_PRIORITY_MAX_METHODDEF
14901     OS_SCHED_GET_PRIORITY_MIN_METHODDEF
14902     OS_SCHED_GETPARAM_METHODDEF
14903     OS_SCHED_GETSCHEDULER_METHODDEF
14904     OS_SCHED_RR_GET_INTERVAL_METHODDEF
14905     OS_SCHED_SETPARAM_METHODDEF
14906     OS_SCHED_SETSCHEDULER_METHODDEF
14907     OS_SCHED_YIELD_METHODDEF
14908     OS_SCHED_SETAFFINITY_METHODDEF
14909     OS_SCHED_GETAFFINITY_METHODDEF
14910     OS_OPENPTY_METHODDEF
14911     OS_LOGIN_TTY_METHODDEF
14912     OS_FORKPTY_METHODDEF
14913     OS_GETEGID_METHODDEF
14914     OS_GETEUID_METHODDEF
14915     OS_GETGID_METHODDEF
14916     OS_GETGROUPLIST_METHODDEF
14917     OS_GETGROUPS_METHODDEF
14918     OS_GETPID_METHODDEF
14919     OS_GETPGRP_METHODDEF
14920     OS_GETPPID_METHODDEF
14921     OS_GETUID_METHODDEF
14922     OS_GETLOGIN_METHODDEF
14923     OS_KILL_METHODDEF
14924     OS_KILLPG_METHODDEF
14925     OS_PLOCK_METHODDEF
14926     OS_STARTFILE_METHODDEF
14927     OS_SETUID_METHODDEF
14928     OS_SETEUID_METHODDEF
14929     OS_SETREUID_METHODDEF
14930     OS_SETGID_METHODDEF
14931     OS_SETEGID_METHODDEF
14932     OS_SETREGID_METHODDEF
14933     OS_SETGROUPS_METHODDEF
14934     OS_INITGROUPS_METHODDEF
14935     OS_GETPGID_METHODDEF
14936     OS_SETPGRP_METHODDEF
14937     OS_WAIT_METHODDEF
14938     OS_WAIT3_METHODDEF
14939     OS_WAIT4_METHODDEF
14940     OS_WAITID_METHODDEF
14941     OS_WAITPID_METHODDEF
14942     OS_PIDFD_OPEN_METHODDEF
14943     OS_GETSID_METHODDEF
14944     OS_SETSID_METHODDEF
14945     OS_SETPGID_METHODDEF
14946     OS_TCGETPGRP_METHODDEF
14947     OS_TCSETPGRP_METHODDEF
14948     OS_OPEN_METHODDEF
14949     OS_CLOSE_METHODDEF
14950     OS_CLOSERANGE_METHODDEF
14951     OS_DEVICE_ENCODING_METHODDEF
14952     OS_DUP_METHODDEF
14953     OS_DUP2_METHODDEF
14954     OS_LOCKF_METHODDEF
14955     OS_LSEEK_METHODDEF
14956     OS_READ_METHODDEF
14957     OS_READV_METHODDEF
14958     OS_PREAD_METHODDEF
14959     OS_PREADV_METHODDEF
14960     OS_WRITE_METHODDEF
14961     OS_WRITEV_METHODDEF
14962     OS_PWRITE_METHODDEF
14963     OS_PWRITEV_METHODDEF
14964     OS_SENDFILE_METHODDEF
14965     OS_FSTAT_METHODDEF
14966     OS_ISATTY_METHODDEF
14967     OS_PIPE_METHODDEF
14968     OS_PIPE2_METHODDEF
14969     OS_MKFIFO_METHODDEF
14970     OS_MKNOD_METHODDEF
14971     OS_MAJOR_METHODDEF
14972     OS_MINOR_METHODDEF
14973     OS_MAKEDEV_METHODDEF
14974     OS_FTRUNCATE_METHODDEF
14975     OS_TRUNCATE_METHODDEF
14976     OS_POSIX_FALLOCATE_METHODDEF
14977     OS_POSIX_FADVISE_METHODDEF
14978     OS_PUTENV_METHODDEF
14979     OS_UNSETENV_METHODDEF
14980     OS_STRERROR_METHODDEF
14981     OS_FCHDIR_METHODDEF
14982     OS_FSYNC_METHODDEF
14983     OS_SYNC_METHODDEF
14984     OS_FDATASYNC_METHODDEF
14985     OS_WCOREDUMP_METHODDEF
14986     OS_WIFCONTINUED_METHODDEF
14987     OS_WIFSTOPPED_METHODDEF
14988     OS_WIFSIGNALED_METHODDEF
14989     OS_WIFEXITED_METHODDEF
14990     OS_WEXITSTATUS_METHODDEF
14991     OS_WTERMSIG_METHODDEF
14992     OS_WSTOPSIG_METHODDEF
14993     OS_FSTATVFS_METHODDEF
14994     OS_STATVFS_METHODDEF
14995     OS_CONFSTR_METHODDEF
14996     OS_SYSCONF_METHODDEF
14997     OS_FPATHCONF_METHODDEF
14998     OS_PATHCONF_METHODDEF
14999     OS_ABORT_METHODDEF
15000     OS__GETFULLPATHNAME_METHODDEF
15001     OS__GETDISKUSAGE_METHODDEF
15002     OS__GETFINALPATHNAME_METHODDEF
15003     OS__GETVOLUMEPATHNAME_METHODDEF
15004     OS__PATH_SPLITROOT_METHODDEF
15005     OS__PATH_NORMPATH_METHODDEF
15006     OS_GETLOADAVG_METHODDEF
15007     OS_URANDOM_METHODDEF
15008     OS_SETRESUID_METHODDEF
15009     OS_SETRESGID_METHODDEF
15010     OS_GETRESUID_METHODDEF
15011     OS_GETRESGID_METHODDEF
15012 
15013     OS_GETXATTR_METHODDEF
15014     OS_SETXATTR_METHODDEF
15015     OS_REMOVEXATTR_METHODDEF
15016     OS_LISTXATTR_METHODDEF
15017 
15018     OS_GET_TERMINAL_SIZE_METHODDEF
15019     OS_CPU_COUNT_METHODDEF
15020     OS_GET_INHERITABLE_METHODDEF
15021     OS_SET_INHERITABLE_METHODDEF
15022     OS_GET_HANDLE_INHERITABLE_METHODDEF
15023     OS_SET_HANDLE_INHERITABLE_METHODDEF
15024     OS_GET_BLOCKING_METHODDEF
15025     OS_SET_BLOCKING_METHODDEF
15026     OS_SCANDIR_METHODDEF
15027     OS_FSPATH_METHODDEF
15028     OS_GETRANDOM_METHODDEF
15029     OS_MEMFD_CREATE_METHODDEF
15030     OS_EVENTFD_METHODDEF
15031     OS_EVENTFD_READ_METHODDEF
15032     OS_EVENTFD_WRITE_METHODDEF
15033     OS__ADD_DLL_DIRECTORY_METHODDEF
15034     OS__REMOVE_DLL_DIRECTORY_METHODDEF
15035     OS_WAITSTATUS_TO_EXITCODE_METHODDEF
15036     {NULL,              NULL}            /* Sentinel */
15037 };
15038 
15039 static int
all_ins(PyObject * m)15040 all_ins(PyObject *m)
15041 {
15042 #ifdef F_OK
15043     if (PyModule_AddIntMacro(m, F_OK)) return -1;
15044 #endif
15045 #ifdef R_OK
15046     if (PyModule_AddIntMacro(m, R_OK)) return -1;
15047 #endif
15048 #ifdef W_OK
15049     if (PyModule_AddIntMacro(m, W_OK)) return -1;
15050 #endif
15051 #ifdef X_OK
15052     if (PyModule_AddIntMacro(m, X_OK)) return -1;
15053 #endif
15054 #ifdef NGROUPS_MAX
15055     if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1;
15056 #endif
15057 #ifdef TMP_MAX
15058     if (PyModule_AddIntMacro(m, TMP_MAX)) return -1;
15059 #endif
15060 #ifdef WCONTINUED
15061     if (PyModule_AddIntMacro(m, WCONTINUED)) return -1;
15062 #endif
15063 #ifdef WNOHANG
15064     if (PyModule_AddIntMacro(m, WNOHANG)) return -1;
15065 #endif
15066 #ifdef WUNTRACED
15067     if (PyModule_AddIntMacro(m, WUNTRACED)) return -1;
15068 #endif
15069 #ifdef O_RDONLY
15070     if (PyModule_AddIntMacro(m, O_RDONLY)) return -1;
15071 #endif
15072 #ifdef O_WRONLY
15073     if (PyModule_AddIntMacro(m, O_WRONLY)) return -1;
15074 #endif
15075 #ifdef O_RDWR
15076     if (PyModule_AddIntMacro(m, O_RDWR)) return -1;
15077 #endif
15078 #ifdef O_NDELAY
15079     if (PyModule_AddIntMacro(m, O_NDELAY)) return -1;
15080 #endif
15081 #ifdef O_NONBLOCK
15082     if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1;
15083 #endif
15084 #ifdef O_APPEND
15085     if (PyModule_AddIntMacro(m, O_APPEND)) return -1;
15086 #endif
15087 #ifdef O_DSYNC
15088     if (PyModule_AddIntMacro(m, O_DSYNC)) return -1;
15089 #endif
15090 #ifdef O_RSYNC
15091     if (PyModule_AddIntMacro(m, O_RSYNC)) return -1;
15092 #endif
15093 #ifdef O_SYNC
15094     if (PyModule_AddIntMacro(m, O_SYNC)) return -1;
15095 #endif
15096 #ifdef O_NOCTTY
15097     if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1;
15098 #endif
15099 #ifdef O_CREAT
15100     if (PyModule_AddIntMacro(m, O_CREAT)) return -1;
15101 #endif
15102 #ifdef O_EXCL
15103     if (PyModule_AddIntMacro(m, O_EXCL)) return -1;
15104 #endif
15105 #ifdef O_TRUNC
15106     if (PyModule_AddIntMacro(m, O_TRUNC)) return -1;
15107 #endif
15108 #ifdef O_BINARY
15109     if (PyModule_AddIntMacro(m, O_BINARY)) return -1;
15110 #endif
15111 #ifdef O_TEXT
15112     if (PyModule_AddIntMacro(m, O_TEXT)) return -1;
15113 #endif
15114 #ifdef O_XATTR
15115     if (PyModule_AddIntMacro(m, O_XATTR)) return -1;
15116 #endif
15117 #ifdef O_LARGEFILE
15118     if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1;
15119 #endif
15120 #ifndef __GNU__
15121 #ifdef O_SHLOCK
15122     if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1;
15123 #endif
15124 #ifdef O_EXLOCK
15125     if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1;
15126 #endif
15127 #endif
15128 #ifdef O_EXEC
15129     if (PyModule_AddIntMacro(m, O_EXEC)) return -1;
15130 #endif
15131 #ifdef O_SEARCH
15132     if (PyModule_AddIntMacro(m, O_SEARCH)) return -1;
15133 #endif
15134 #ifdef O_PATH
15135     if (PyModule_AddIntMacro(m, O_PATH)) return -1;
15136 #endif
15137 #ifdef O_TTY_INIT
15138     if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1;
15139 #endif
15140 #ifdef O_TMPFILE
15141     if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1;
15142 #endif
15143 #ifdef PRIO_PROCESS
15144     if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1;
15145 #endif
15146 #ifdef PRIO_PGRP
15147     if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1;
15148 #endif
15149 #ifdef PRIO_USER
15150     if (PyModule_AddIntMacro(m, PRIO_USER)) return -1;
15151 #endif
15152 #ifdef O_CLOEXEC
15153     if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1;
15154 #endif
15155 #ifdef O_ACCMODE
15156     if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1;
15157 #endif
15158 #ifdef O_EVTONLY
15159     if (PyModule_AddIntMacro(m, O_EVTONLY)) return -1;
15160 #endif
15161 #ifdef O_FSYNC
15162     if (PyModule_AddIntMacro(m, O_FSYNC)) return -1;
15163 #endif
15164 #ifdef O_SYMLINK
15165     if (PyModule_AddIntMacro(m, O_SYMLINK)) return -1;
15166 #endif
15167 
15168 #ifdef SEEK_HOLE
15169     if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1;
15170 #endif
15171 #ifdef SEEK_DATA
15172     if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1;
15173 #endif
15174 
15175 /* MS Windows */
15176 #ifdef O_NOINHERIT
15177     /* Don't inherit in child processes. */
15178     if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1;
15179 #endif
15180 #ifdef _O_SHORT_LIVED
15181     /* Optimize for short life (keep in memory). */
15182     /* MS forgot to define this one with a non-underscore form too. */
15183     if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1;
15184 #endif
15185 #ifdef O_TEMPORARY
15186     /* Automatically delete when last handle is closed. */
15187     if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1;
15188 #endif
15189 #ifdef O_RANDOM
15190     /* Optimize for random access. */
15191     if (PyModule_AddIntMacro(m, O_RANDOM)) return -1;
15192 #endif
15193 #ifdef O_SEQUENTIAL
15194     /* Optimize for sequential access. */
15195     if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1;
15196 #endif
15197 
15198 /* GNU extensions. */
15199 #ifdef O_ASYNC
15200     /* Send a SIGIO signal whenever input or output
15201        becomes available on file descriptor */
15202     if (PyModule_AddIntMacro(m, O_ASYNC)) return -1;
15203 #endif
15204 #ifdef O_DIRECT
15205     /* Direct disk access. */
15206     if (PyModule_AddIntMacro(m, O_DIRECT)) return -1;
15207 #endif
15208 #ifdef O_DIRECTORY
15209     /* Must be a directory.      */
15210     if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1;
15211 #endif
15212 #ifdef O_NOFOLLOW
15213     /* Do not follow links.      */
15214     if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1;
15215 #endif
15216 #ifdef O_NOFOLLOW_ANY
15217     if (PyModule_AddIntMacro(m, O_NOFOLLOW_ANY)) return -1;
15218 #endif
15219 #ifdef O_NOLINKS
15220     /* Fails if link count of the named file is greater than 1 */
15221     if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1;
15222 #endif
15223 #ifdef O_NOATIME
15224     /* Do not update the access time. */
15225     if (PyModule_AddIntMacro(m, O_NOATIME)) return -1;
15226 #endif
15227 
15228     /* These come from sysexits.h */
15229 #ifdef EX_OK
15230     if (PyModule_AddIntMacro(m, EX_OK)) return -1;
15231 #endif /* EX_OK */
15232 #ifdef EX_USAGE
15233     if (PyModule_AddIntMacro(m, EX_USAGE)) return -1;
15234 #endif /* EX_USAGE */
15235 #ifdef EX_DATAERR
15236     if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1;
15237 #endif /* EX_DATAERR */
15238 #ifdef EX_NOINPUT
15239     if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1;
15240 #endif /* EX_NOINPUT */
15241 #ifdef EX_NOUSER
15242     if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1;
15243 #endif /* EX_NOUSER */
15244 #ifdef EX_NOHOST
15245     if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1;
15246 #endif /* EX_NOHOST */
15247 #ifdef EX_UNAVAILABLE
15248     if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1;
15249 #endif /* EX_UNAVAILABLE */
15250 #ifdef EX_SOFTWARE
15251     if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1;
15252 #endif /* EX_SOFTWARE */
15253 #ifdef EX_OSERR
15254     if (PyModule_AddIntMacro(m, EX_OSERR)) return -1;
15255 #endif /* EX_OSERR */
15256 #ifdef EX_OSFILE
15257     if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1;
15258 #endif /* EX_OSFILE */
15259 #ifdef EX_CANTCREAT
15260     if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1;
15261 #endif /* EX_CANTCREAT */
15262 #ifdef EX_IOERR
15263     if (PyModule_AddIntMacro(m, EX_IOERR)) return -1;
15264 #endif /* EX_IOERR */
15265 #ifdef EX_TEMPFAIL
15266     if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1;
15267 #endif /* EX_TEMPFAIL */
15268 #ifdef EX_PROTOCOL
15269     if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1;
15270 #endif /* EX_PROTOCOL */
15271 #ifdef EX_NOPERM
15272     if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1;
15273 #endif /* EX_NOPERM */
15274 #ifdef EX_CONFIG
15275     if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1;
15276 #endif /* EX_CONFIG */
15277 #ifdef EX_NOTFOUND
15278     if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1;
15279 #endif /* EX_NOTFOUND */
15280 
15281     /* statvfs */
15282 #ifdef ST_RDONLY
15283     if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1;
15284 #endif /* ST_RDONLY */
15285 #ifdef ST_NOSUID
15286     if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1;
15287 #endif /* ST_NOSUID */
15288 
15289        /* GNU extensions */
15290 #ifdef ST_NODEV
15291     if (PyModule_AddIntMacro(m, ST_NODEV)) return -1;
15292 #endif /* ST_NODEV */
15293 #ifdef ST_NOEXEC
15294     if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1;
15295 #endif /* ST_NOEXEC */
15296 #ifdef ST_SYNCHRONOUS
15297     if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1;
15298 #endif /* ST_SYNCHRONOUS */
15299 #ifdef ST_MANDLOCK
15300     if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1;
15301 #endif /* ST_MANDLOCK */
15302 #ifdef ST_WRITE
15303     if (PyModule_AddIntMacro(m, ST_WRITE)) return -1;
15304 #endif /* ST_WRITE */
15305 #ifdef ST_APPEND
15306     if (PyModule_AddIntMacro(m, ST_APPEND)) return -1;
15307 #endif /* ST_APPEND */
15308 #ifdef ST_NOATIME
15309     if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1;
15310 #endif /* ST_NOATIME */
15311 #ifdef ST_NODIRATIME
15312     if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1;
15313 #endif /* ST_NODIRATIME */
15314 #ifdef ST_RELATIME
15315     if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1;
15316 #endif /* ST_RELATIME */
15317 
15318     /* FreeBSD sendfile() constants */
15319 #ifdef SF_NODISKIO
15320     if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1;
15321 #endif
15322     /* is obsolete since the 11.x release */
15323 #ifdef SF_MNOWAIT
15324     if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1;
15325 #endif
15326 #ifdef SF_SYNC
15327     if (PyModule_AddIntMacro(m, SF_SYNC)) return -1;
15328 #endif
15329 #ifdef SF_NOCACHE
15330     if (PyModule_AddIntMacro(m, SF_NOCACHE)) return -1;
15331 #endif
15332 
15333     /* constants for posix_fadvise */
15334 #ifdef POSIX_FADV_NORMAL
15335     if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1;
15336 #endif
15337 #ifdef POSIX_FADV_SEQUENTIAL
15338     if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1;
15339 #endif
15340 #ifdef POSIX_FADV_RANDOM
15341     if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1;
15342 #endif
15343 #ifdef POSIX_FADV_NOREUSE
15344     if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1;
15345 #endif
15346 #ifdef POSIX_FADV_WILLNEED
15347     if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1;
15348 #endif
15349 #ifdef POSIX_FADV_DONTNEED
15350     if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1;
15351 #endif
15352 
15353     /* constants for waitid */
15354 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID)
15355     if (PyModule_AddIntMacro(m, P_PID)) return -1;
15356     if (PyModule_AddIntMacro(m, P_PGID)) return -1;
15357     if (PyModule_AddIntMacro(m, P_ALL)) return -1;
15358 #ifdef P_PIDFD
15359     if (PyModule_AddIntMacro(m, P_PIDFD)) return -1;
15360 #endif
15361 #endif
15362 #ifdef WEXITED
15363     if (PyModule_AddIntMacro(m, WEXITED)) return -1;
15364 #endif
15365 #ifdef WNOWAIT
15366     if (PyModule_AddIntMacro(m, WNOWAIT)) return -1;
15367 #endif
15368 #ifdef WSTOPPED
15369     if (PyModule_AddIntMacro(m, WSTOPPED)) return -1;
15370 #endif
15371 #ifdef CLD_EXITED
15372     if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1;
15373 #endif
15374 #ifdef CLD_KILLED
15375     if (PyModule_AddIntMacro(m, CLD_KILLED)) return -1;
15376 #endif
15377 #ifdef CLD_DUMPED
15378     if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1;
15379 #endif
15380 #ifdef CLD_TRAPPED
15381     if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1;
15382 #endif
15383 #ifdef CLD_STOPPED
15384     if (PyModule_AddIntMacro(m, CLD_STOPPED)) return -1;
15385 #endif
15386 #ifdef CLD_CONTINUED
15387     if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1;
15388 #endif
15389 
15390     /* constants for lockf */
15391 #ifdef F_LOCK
15392     if (PyModule_AddIntMacro(m, F_LOCK)) return -1;
15393 #endif
15394 #ifdef F_TLOCK
15395     if (PyModule_AddIntMacro(m, F_TLOCK)) return -1;
15396 #endif
15397 #ifdef F_ULOCK
15398     if (PyModule_AddIntMacro(m, F_ULOCK)) return -1;
15399 #endif
15400 #ifdef F_TEST
15401     if (PyModule_AddIntMacro(m, F_TEST)) return -1;
15402 #endif
15403 
15404 #ifdef RWF_DSYNC
15405     if (PyModule_AddIntConstant(m, "RWF_DSYNC", RWF_DSYNC)) return -1;
15406 #endif
15407 #ifdef RWF_HIPRI
15408     if (PyModule_AddIntConstant(m, "RWF_HIPRI", RWF_HIPRI)) return -1;
15409 #endif
15410 #ifdef RWF_SYNC
15411     if (PyModule_AddIntConstant(m, "RWF_SYNC", RWF_SYNC)) return -1;
15412 #endif
15413 #ifdef RWF_NOWAIT
15414     if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1;
15415 #endif
15416 #ifdef RWF_APPEND
15417     if (PyModule_AddIntConstant(m, "RWF_APPEND", RWF_APPEND)) return -1;
15418 #endif
15419 
15420 /* constants for splice */
15421 #if defined(HAVE_SPLICE) && defined(__linux__)
15422     if (PyModule_AddIntConstant(m, "SPLICE_F_MOVE", SPLICE_F_MOVE)) return -1;
15423     if (PyModule_AddIntConstant(m, "SPLICE_F_NONBLOCK", SPLICE_F_NONBLOCK)) return -1;
15424     if (PyModule_AddIntConstant(m, "SPLICE_F_MORE", SPLICE_F_MORE)) return -1;
15425 #endif
15426 
15427 /* constants for posix_spawn */
15428 #ifdef HAVE_POSIX_SPAWN
15429     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
15430     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
15431     if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
15432 #endif
15433 
15434 #if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
15435     if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1;
15436     if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1;
15437     if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1;
15438 #endif
15439 #ifdef HAVE_SPAWNV
15440     if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1;
15441     if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1;
15442 #endif
15443 
15444 #ifdef HAVE_SCHED_H
15445 #ifdef SCHED_OTHER
15446     if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1;
15447 #endif
15448 #ifdef SCHED_FIFO
15449     if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1;
15450 #endif
15451 #ifdef SCHED_RR
15452     if (PyModule_AddIntMacro(m, SCHED_RR)) return -1;
15453 #endif
15454 #ifdef SCHED_SPORADIC
15455     if (PyModule_AddIntMacro(m, SCHED_SPORADIC)) return -1;
15456 #endif
15457 #ifdef SCHED_BATCH
15458     if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1;
15459 #endif
15460 #ifdef SCHED_IDLE
15461     if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1;
15462 #endif
15463 #ifdef SCHED_RESET_ON_FORK
15464     if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1;
15465 #endif
15466 #ifdef SCHED_SYS
15467     if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1;
15468 #endif
15469 #ifdef SCHED_IA
15470     if (PyModule_AddIntMacro(m, SCHED_IA)) return -1;
15471 #endif
15472 #ifdef SCHED_FSS
15473     if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1;
15474 #endif
15475 #ifdef SCHED_FX
15476     if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1;
15477 #endif
15478 #endif
15479 
15480 #ifdef USE_XATTRS
15481     if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1;
15482     if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1;
15483     if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1;
15484 #endif
15485 
15486 #if HAVE_DECL_RTLD_LAZY
15487     if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1;
15488 #endif
15489 #if HAVE_DECL_RTLD_NOW
15490     if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1;
15491 #endif
15492 #if HAVE_DECL_RTLD_GLOBAL
15493     if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1;
15494 #endif
15495 #if HAVE_DECL_RTLD_LOCAL
15496     if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1;
15497 #endif
15498 #if HAVE_DECL_RTLD_NODELETE
15499     if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1;
15500 #endif
15501 #if HAVE_DECL_RTLD_NOLOAD
15502     if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1;
15503 #endif
15504 #if HAVE_DECL_RTLD_DEEPBIND
15505     if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1;
15506 #endif
15507 #if HAVE_DECL_RTLD_MEMBER
15508     if (PyModule_AddIntMacro(m, RTLD_MEMBER)) return -1;
15509 #endif
15510 
15511 #ifdef HAVE_GETRANDOM_SYSCALL
15512     if (PyModule_AddIntMacro(m, GRND_RANDOM)) return -1;
15513     if (PyModule_AddIntMacro(m, GRND_NONBLOCK)) return -1;
15514 #endif
15515 #ifdef HAVE_MEMFD_CREATE
15516     if (PyModule_AddIntMacro(m, MFD_CLOEXEC)) return -1;
15517     if (PyModule_AddIntMacro(m, MFD_ALLOW_SEALING)) return -1;
15518 #ifdef MFD_HUGETLB
15519     if (PyModule_AddIntMacro(m, MFD_HUGETLB)) return -1;
15520 #endif
15521 #ifdef MFD_HUGE_SHIFT
15522     if (PyModule_AddIntMacro(m, MFD_HUGE_SHIFT)) return -1;
15523 #endif
15524 #ifdef MFD_HUGE_MASK
15525     if (PyModule_AddIntMacro(m, MFD_HUGE_MASK)) return -1;
15526 #endif
15527 #ifdef MFD_HUGE_64KB
15528     if (PyModule_AddIntMacro(m, MFD_HUGE_64KB)) return -1;
15529 #endif
15530 #ifdef MFD_HUGE_512KB
15531     if (PyModule_AddIntMacro(m, MFD_HUGE_512KB)) return -1;
15532 #endif
15533 #ifdef MFD_HUGE_1MB
15534     if (PyModule_AddIntMacro(m, MFD_HUGE_1MB)) return -1;
15535 #endif
15536 #ifdef MFD_HUGE_2MB
15537     if (PyModule_AddIntMacro(m, MFD_HUGE_2MB)) return -1;
15538 #endif
15539 #ifdef MFD_HUGE_8MB
15540     if (PyModule_AddIntMacro(m, MFD_HUGE_8MB)) return -1;
15541 #endif
15542 #ifdef MFD_HUGE_16MB
15543     if (PyModule_AddIntMacro(m, MFD_HUGE_16MB)) return -1;
15544 #endif
15545 #ifdef MFD_HUGE_32MB
15546     if (PyModule_AddIntMacro(m, MFD_HUGE_32MB)) return -1;
15547 #endif
15548 #ifdef MFD_HUGE_256MB
15549     if (PyModule_AddIntMacro(m, MFD_HUGE_256MB)) return -1;
15550 #endif
15551 #ifdef MFD_HUGE_512MB
15552     if (PyModule_AddIntMacro(m, MFD_HUGE_512MB)) return -1;
15553 #endif
15554 #ifdef MFD_HUGE_1GB
15555     if (PyModule_AddIntMacro(m, MFD_HUGE_1GB)) return -1;
15556 #endif
15557 #ifdef MFD_HUGE_2GB
15558     if (PyModule_AddIntMacro(m, MFD_HUGE_2GB)) return -1;
15559 #endif
15560 #ifdef MFD_HUGE_16GB
15561     if (PyModule_AddIntMacro(m, MFD_HUGE_16GB)) return -1;
15562 #endif
15563 #endif /* HAVE_MEMFD_CREATE */
15564 
15565 #if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
15566     if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
15567 #ifdef EFD_NONBLOCK
15568     if (PyModule_AddIntMacro(m, EFD_NONBLOCK)) return -1;
15569 #endif
15570 #ifdef EFD_SEMAPHORE
15571     if (PyModule_AddIntMacro(m, EFD_SEMAPHORE)) return -1;
15572 #endif
15573 #endif  /* HAVE_EVENTFD && EFD_CLOEXEC */
15574 
15575 #if defined(__APPLE__)
15576     if (PyModule_AddIntConstant(m, "_COPYFILE_DATA", COPYFILE_DATA)) return -1;
15577     if (PyModule_AddIntConstant(m, "_COPYFILE_STAT", COPYFILE_STAT)) return -1;
15578     if (PyModule_AddIntConstant(m, "_COPYFILE_ACL", COPYFILE_ACL)) return -1;
15579     if (PyModule_AddIntConstant(m, "_COPYFILE_XATTR", COPYFILE_XATTR)) return -1;
15580 #endif
15581 
15582 #ifdef MS_WINDOWS
15583     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", LOAD_LIBRARY_SEARCH_DEFAULT_DIRS)) return -1;
15584     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_APPLICATION_DIR", LOAD_LIBRARY_SEARCH_APPLICATION_DIR)) return -1;
15585     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_SYSTEM32", LOAD_LIBRARY_SEARCH_SYSTEM32)) return -1;
15586     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_USER_DIRS", LOAD_LIBRARY_SEARCH_USER_DIRS)) return -1;
15587     if (PyModule_AddIntConstant(m, "_LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR", LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)) return -1;
15588 #endif
15589 
15590     return 0;
15591 }
15592 
15593 
15594 
15595 #define PROBE(name, test) \
15596    static int name(void)  \
15597    {                      \
15598       if (test) {        \
15599           return 1;       \
15600       } else {            \
15601           return 0;       \
15602       }                   \
15603    }
15604 
15605 #ifdef HAVE_FSTATAT
15606 PROBE(probe_fstatat, HAVE_FSTATAT_RUNTIME)
15607 #endif
15608 
15609 #ifdef HAVE_FACCESSAT
15610 PROBE(probe_faccessat, HAVE_FACCESSAT_RUNTIME)
15611 #endif
15612 
15613 #ifdef HAVE_FCHMODAT
15614 PROBE(probe_fchmodat, HAVE_FCHMODAT_RUNTIME)
15615 #endif
15616 
15617 #ifdef HAVE_FCHOWNAT
15618 PROBE(probe_fchownat, HAVE_FCHOWNAT_RUNTIME)
15619 #endif
15620 
15621 #ifdef HAVE_LINKAT
15622 PROBE(probe_linkat, HAVE_LINKAT_RUNTIME)
15623 #endif
15624 
15625 #ifdef HAVE_FDOPENDIR
15626 PROBE(probe_fdopendir, HAVE_FDOPENDIR_RUNTIME)
15627 #endif
15628 
15629 #ifdef HAVE_MKDIRAT
15630 PROBE(probe_mkdirat, HAVE_MKDIRAT_RUNTIME)
15631 #endif
15632 
15633 #ifdef HAVE_MKFIFOAT
15634 PROBE(probe_mkfifoat, HAVE_MKFIFOAT_RUNTIME)
15635 #endif
15636 
15637 #ifdef HAVE_MKNODAT
15638 PROBE(probe_mknodat, HAVE_MKNODAT_RUNTIME)
15639 #endif
15640 
15641 #ifdef HAVE_RENAMEAT
15642 PROBE(probe_renameat, HAVE_RENAMEAT_RUNTIME)
15643 #endif
15644 
15645 #ifdef HAVE_UNLINKAT
15646 PROBE(probe_unlinkat, HAVE_UNLINKAT_RUNTIME)
15647 #endif
15648 
15649 #ifdef HAVE_OPENAT
15650 PROBE(probe_openat, HAVE_OPENAT_RUNTIME)
15651 #endif
15652 
15653 #ifdef HAVE_READLINKAT
15654 PROBE(probe_readlinkat, HAVE_READLINKAT_RUNTIME)
15655 #endif
15656 
15657 #ifdef HAVE_SYMLINKAT
15658 PROBE(probe_symlinkat, HAVE_SYMLINKAT_RUNTIME)
15659 #endif
15660 
15661 #ifdef HAVE_FUTIMENS
15662 PROBE(probe_futimens, HAVE_FUTIMENS_RUNTIME)
15663 #endif
15664 
15665 #ifdef HAVE_UTIMENSAT
15666 PROBE(probe_utimensat, HAVE_UTIMENSAT_RUNTIME)
15667 #endif
15668 
15669 
15670 
15671 
15672 static const struct have_function {
15673     const char * const label;
15674     int (*probe)(void);
15675 } have_functions[] = {
15676 
15677 #ifdef HAVE_EVENTFD
15678     {"HAVE_EVENTFD", NULL},
15679 #endif
15680 
15681 #ifdef HAVE_FACCESSAT
15682     { "HAVE_FACCESSAT", probe_faccessat },
15683 #endif
15684 
15685 #ifdef HAVE_FCHDIR
15686     { "HAVE_FCHDIR", NULL },
15687 #endif
15688 
15689 #ifdef HAVE_FCHMOD
15690     { "HAVE_FCHMOD", NULL },
15691 #endif
15692 
15693 #ifdef HAVE_FCHMODAT
15694     { "HAVE_FCHMODAT", probe_fchmodat },
15695 #endif
15696 
15697 #ifdef HAVE_FCHOWN
15698     { "HAVE_FCHOWN", NULL },
15699 #endif
15700 
15701 #ifdef HAVE_FCHOWNAT
15702     { "HAVE_FCHOWNAT", probe_fchownat },
15703 #endif
15704 
15705 #ifdef HAVE_FEXECVE
15706     { "HAVE_FEXECVE", NULL },
15707 #endif
15708 
15709 #ifdef HAVE_FDOPENDIR
15710     { "HAVE_FDOPENDIR", probe_fdopendir },
15711 #endif
15712 
15713 #ifdef HAVE_FPATHCONF
15714     { "HAVE_FPATHCONF", NULL },
15715 #endif
15716 
15717 #ifdef HAVE_FSTATAT
15718     { "HAVE_FSTATAT", probe_fstatat },
15719 #endif
15720 
15721 #ifdef HAVE_FSTATVFS
15722     { "HAVE_FSTATVFS", NULL },
15723 #endif
15724 
15725 #if defined HAVE_FTRUNCATE || defined MS_WINDOWS
15726     { "HAVE_FTRUNCATE", NULL },
15727 #endif
15728 
15729 #ifdef HAVE_FUTIMENS
15730     { "HAVE_FUTIMENS", probe_futimens },
15731 #endif
15732 
15733 #ifdef HAVE_FUTIMES
15734     { "HAVE_FUTIMES", NULL },
15735 #endif
15736 
15737 #ifdef HAVE_FUTIMESAT
15738     { "HAVE_FUTIMESAT", NULL },
15739 #endif
15740 
15741 #ifdef HAVE_LINKAT
15742     { "HAVE_LINKAT", probe_linkat },
15743 #endif
15744 
15745 #ifdef HAVE_LCHFLAGS
15746     { "HAVE_LCHFLAGS", NULL },
15747 #endif
15748 
15749 #ifdef HAVE_LCHMOD
15750     { "HAVE_LCHMOD", NULL },
15751 #endif
15752 
15753 #ifdef HAVE_LCHOWN
15754     { "HAVE_LCHOWN", NULL },
15755 #endif
15756 
15757 #ifdef HAVE_LSTAT
15758     { "HAVE_LSTAT", NULL },
15759 #endif
15760 
15761 #ifdef HAVE_LUTIMES
15762     { "HAVE_LUTIMES", NULL },
15763 #endif
15764 
15765 #ifdef HAVE_MEMFD_CREATE
15766     { "HAVE_MEMFD_CREATE", NULL },
15767 #endif
15768 
15769 #ifdef HAVE_MKDIRAT
15770     { "HAVE_MKDIRAT", probe_mkdirat },
15771 #endif
15772 
15773 #ifdef HAVE_MKFIFOAT
15774     { "HAVE_MKFIFOAT", probe_mkfifoat },
15775 #endif
15776 
15777 #ifdef HAVE_MKNODAT
15778     { "HAVE_MKNODAT", probe_mknodat },
15779 #endif
15780 
15781 #ifdef HAVE_OPENAT
15782     { "HAVE_OPENAT", probe_openat },
15783 #endif
15784 
15785 #ifdef HAVE_READLINKAT
15786     { "HAVE_READLINKAT", probe_readlinkat },
15787 #endif
15788 
15789 #ifdef HAVE_RENAMEAT
15790     { "HAVE_RENAMEAT", probe_renameat },
15791 #endif
15792 
15793 #ifdef HAVE_SYMLINKAT
15794     { "HAVE_SYMLINKAT", probe_symlinkat },
15795 #endif
15796 
15797 #ifdef HAVE_UNLINKAT
15798     { "HAVE_UNLINKAT", probe_unlinkat },
15799 #endif
15800 
15801 #ifdef HAVE_UTIMENSAT
15802     { "HAVE_UTIMENSAT", probe_utimensat },
15803 #endif
15804 
15805 #ifdef MS_WINDOWS
15806     { "MS_WINDOWS", NULL },
15807 #endif
15808 
15809     { NULL, NULL }
15810 };
15811 
15812 
15813 static int
posixmodule_exec(PyObject * m)15814 posixmodule_exec(PyObject *m)
15815 {
15816     _posixstate *state = get_posix_state(m);
15817 
15818 #if defined(HAVE_PWRITEV)
15819     if (HAVE_PWRITEV_RUNTIME) {} else {
15820         PyObject* dct = PyModule_GetDict(m);
15821 
15822         if (dct == NULL) {
15823             return -1;
15824         }
15825 
15826         if (PyDict_DelItemString(dct, "pwritev") == -1) {
15827             PyErr_Clear();
15828         }
15829         if (PyDict_DelItemString(dct, "preadv") == -1) {
15830             PyErr_Clear();
15831         }
15832     }
15833 #endif
15834 
15835     /* Initialize environ dictionary */
15836     PyObject *v = convertenviron();
15837     Py_XINCREF(v);
15838     if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
15839         return -1;
15840     Py_DECREF(v);
15841 
15842     if (all_ins(m))
15843         return -1;
15844 
15845     if (setup_confname_tables(m))
15846         return -1;
15847 
15848     Py_INCREF(PyExc_OSError);
15849     PyModule_AddObject(m, "error", PyExc_OSError);
15850 
15851 #if defined(HAVE_WAITID) && !defined(__APPLE__)
15852     waitid_result_desc.name = MODNAME ".waitid_result";
15853     PyObject *WaitidResultType = (PyObject *)PyStructSequence_NewType(&waitid_result_desc);
15854     if (WaitidResultType == NULL) {
15855         return -1;
15856     }
15857     Py_INCREF(WaitidResultType);
15858     PyModule_AddObject(m, "waitid_result", WaitidResultType);
15859     state->WaitidResultType = WaitidResultType;
15860 #endif
15861 
15862     stat_result_desc.name = "os.stat_result"; /* see issue #19209 */
15863     stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
15864     stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
15865     stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
15866     PyObject *StatResultType = (PyObject *)PyStructSequence_NewType(&stat_result_desc);
15867     if (StatResultType == NULL) {
15868         return -1;
15869     }
15870     Py_INCREF(StatResultType);
15871     PyModule_AddObject(m, "stat_result", StatResultType);
15872     state->StatResultType = StatResultType;
15873     structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15874     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
15875 
15876     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
15877     PyObject *StatVFSResultType = (PyObject *)PyStructSequence_NewType(&statvfs_result_desc);
15878     if (StatVFSResultType == NULL) {
15879         return -1;
15880     }
15881     Py_INCREF(StatVFSResultType);
15882     PyModule_AddObject(m, "statvfs_result", StatVFSResultType);
15883     state->StatVFSResultType = StatVFSResultType;
15884 #ifdef NEED_TICKS_PER_SECOND
15885 #  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15886     ticks_per_second = sysconf(_SC_CLK_TCK);
15887 #  elif defined(HZ)
15888     ticks_per_second = HZ;
15889 #  else
15890     ticks_per_second = 60; /* magic fallback value; may be bogus */
15891 #  endif
15892 #endif
15893 
15894 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
15895     sched_param_desc.name = MODNAME ".sched_param";
15896     PyObject *SchedParamType = (PyObject *)PyStructSequence_NewType(&sched_param_desc);
15897     if (SchedParamType == NULL) {
15898         return -1;
15899     }
15900     Py_INCREF(SchedParamType);
15901     PyModule_AddObject(m, "sched_param", SchedParamType);
15902     state->SchedParamType = SchedParamType;
15903     ((PyTypeObject *)SchedParamType)->tp_new = os_sched_param;
15904 #endif
15905 
15906     /* initialize TerminalSize_info */
15907     PyObject *TerminalSizeType = (PyObject *)PyStructSequence_NewType(&TerminalSize_desc);
15908     if (TerminalSizeType == NULL) {
15909         return -1;
15910     }
15911     Py_INCREF(TerminalSizeType);
15912     PyModule_AddObject(m, "terminal_size", TerminalSizeType);
15913     state->TerminalSizeType = TerminalSizeType;
15914 
15915     /* initialize scandir types */
15916     PyObject *ScandirIteratorType = PyType_FromModuleAndSpec(m, &ScandirIteratorType_spec, NULL);
15917     if (ScandirIteratorType == NULL) {
15918         return -1;
15919     }
15920     state->ScandirIteratorType = ScandirIteratorType;
15921 
15922     PyObject *DirEntryType = PyType_FromModuleAndSpec(m, &DirEntryType_spec, NULL);
15923     if (DirEntryType == NULL) {
15924         return -1;
15925     }
15926     Py_INCREF(DirEntryType);
15927     PyModule_AddObject(m, "DirEntry", DirEntryType);
15928     state->DirEntryType = DirEntryType;
15929 
15930     times_result_desc.name = MODNAME ".times_result";
15931     PyObject *TimesResultType = (PyObject *)PyStructSequence_NewType(&times_result_desc);
15932     if (TimesResultType == NULL) {
15933         return -1;
15934     }
15935     Py_INCREF(TimesResultType);
15936     PyModule_AddObject(m, "times_result", TimesResultType);
15937     state->TimesResultType = TimesResultType;
15938 
15939     PyTypeObject *UnameResultType = PyStructSequence_NewType(&uname_result_desc);
15940     if (UnameResultType == NULL) {
15941         return -1;
15942     }
15943     Py_INCREF(UnameResultType);
15944     PyModule_AddObject(m, "uname_result", (PyObject *)UnameResultType);
15945     state->UnameResultType = (PyObject *)UnameResultType;
15946 
15947     if ((state->billion = PyLong_FromLong(1000000000)) == NULL)
15948         return -1;
15949 #if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
15950     state->struct_rusage = PyUnicode_InternFromString("struct_rusage");
15951     if (state->struct_rusage == NULL)
15952         return -1;
15953 #endif
15954     state->st_mode = PyUnicode_InternFromString("st_mode");
15955     if (state->st_mode == NULL)
15956         return -1;
15957 
15958     /* suppress "function not used" warnings */
15959     {
15960     int ignored;
15961     fd_specified("", -1);
15962     follow_symlinks_specified("", 1);
15963     dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1);
15964     dir_fd_converter(Py_None, &ignored);
15965     dir_fd_unavailable(Py_None, &ignored);
15966     }
15967 
15968     /*
15969      * provide list of locally available functions
15970      * so os.py can populate support_* lists
15971      */
15972     PyObject *list = PyList_New(0);
15973     if (!list) {
15974         return -1;
15975     }
15976     for (const struct have_function *trace = have_functions; trace->label; trace++) {
15977         PyObject *unicode;
15978         if (trace->probe && !trace->probe()) continue;
15979         unicode = PyUnicode_DecodeASCII(trace->label, strlen(trace->label), NULL);
15980         if (!unicode)
15981             return -1;
15982         if (PyList_Append(list, unicode))
15983             return -1;
15984         Py_DECREF(unicode);
15985     }
15986 
15987     PyModule_AddObject(m, "_have_functions", list);
15988 
15989     return 0;
15990 }
15991 
15992 
15993 static PyModuleDef_Slot posixmodile_slots[] = {
15994     {Py_mod_exec, posixmodule_exec},
15995     {0, NULL}
15996 };
15997 
15998 static struct PyModuleDef posixmodule = {
15999     PyModuleDef_HEAD_INIT,
16000     .m_name = MODNAME,
16001     .m_doc = posix__doc__,
16002     .m_size = sizeof(_posixstate),
16003     .m_methods = posix_methods,
16004     .m_slots = posixmodile_slots,
16005     .m_traverse = _posix_traverse,
16006     .m_clear = _posix_clear,
16007     .m_free = _posix_free,
16008 };
16009 
16010 PyMODINIT_FUNC
INITFUNC(void)16011 INITFUNC(void)
16012 {
16013     return PyModuleDef_Init(&posixmodule);
16014 }
16015 
16016 #ifdef __cplusplus
16017 }
16018 #endif
16019